Last active
March 30, 2021 21:10
-
-
Save jeakwon/17edc0e416ddcab1fbdab9f5757ddad0 to your computer and use it in GitHub Desktop.
rebalance in upbit api
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UpbitAPI: | |
""" | |
:라이브러리: | |
import requests, jwt, uuid, hashlib, time | |
from urllib.parse import urlencode | |
:사용법: | |
with open(r"C:\Users\Jay\Desktop\upbit.txt", 'r') as f: | |
access_key, secret_key = f.read().splitlines() | |
api = UpbitAPI(access_key, secret_key) | |
api.rebalance(cash_ratio=0.1) | |
""" | |
urls = { | |
"전체계좌조회": "https://api.upbit.com/v1/accounts", | |
"주문가능정보": "https://api.upbit.com/v1/orders/chance", | |
"개별주문조회": "https://api.upbit.com/v1/order", | |
"주문리스트조회": "https://api.upbit.com/v1/orders", | |
"주문취소접수": "https://api.upbit.com/v1/order", | |
"주문하기": "https://api.upbit.com/v1/orders", | |
"출금리스트조회": "https://api.upbit.com/v1/withdraws", | |
"개별출금조회": "https://api.upbit.com/v1/v1/withdraw", | |
"출금가능정보": "https://api.upbit.com/v1/withdraws/chance", | |
"코인출금하기": "https://api.upbit.com/v1/withdraws/coin", | |
"원화출금하기": "https://api.upbit.com/v1/withdraws/krw", | |
"입금리스트조회": "https://api.upbit.com/v1/deposits", | |
"개별입금조회": "https://api.upbit.com/v1/deposit", | |
"입금주소생성요청": "https://api.upbit.com/v1/deposits/generate_coin_address", | |
"전체입금주소조회": "https://api.upbit.com/v1/deposits/coin_addresses", | |
"개별입금주소조회": "https://api.upbit.com/v1/deposits/coin_address", | |
"원화입금하기": "https://api.upbit.com/v1/deposits/krw", | |
"입출금현황": "https://api.upbit.com/v1/status/wallet", | |
"API키리스트조회": "https://api.upbit.com/v1/api_keys", | |
"마켓코드조회": "https://api.upbit.com/v1/market/all", | |
"분캔들1": "https://api.upbit.com/v1/candles/minutes/1", | |
"분캔들3": "https://api.upbit.com/v1/candles/minutes/3", | |
"분캔들5": "https://api.upbit.com/v1/candles/minutes/5", | |
"분캔들10": "https://api.upbit.com/v1/candles/minutes/10", | |
"분캔들15": "https://api.upbit.com/v1/candles/minutes/15", | |
"분캔들30": "https://api.upbit.com/v1/candles/minutes/30", | |
"분캔들60": "https://api.upbit.com/v1/candles/minutes/60", | |
"분캔들240": "https://api.upbit.com/v1/candles/minutes/240", | |
"일캔들": "https://api.upbit.com/v1/candles/days", | |
"주캔들": "https://api.upbit.com/v1/candles/weeks", | |
"월캔들": "https://api.upbit.com/v1/candles/months", | |
"최근체결내역": "https://api.upbit.com/v1/trades/ticks", | |
"현재가정보": "https://api.upbit.com/v1/ticker", | |
"호가정보조회": "https://api.upbit.com/v1/orderbook", | |
} | |
def __init__(self, access_key, secret_key): | |
self.access_key = access_key | |
self.secret_key = secret_key | |
def get_headers(self, query=None, uuids=None, txids=None): | |
if query: | |
query_string = urlencode(query).encode() | |
if uuids: | |
uuids_query_string = '&'.join( | |
["uuids[]={}".format(uuid) for uuid in uuids]) | |
query['uuids[]'] = uuids | |
query_string = "{0}&{1}".format( | |
query_string, uuids_query_string).encode() | |
if txids: | |
txids_query_string = '&'.join( | |
["txids[]={}".format(txid) for txid in txids]) | |
query['txids[]'] = txids | |
query_string = "{0}&{1}".format( | |
query_string, txids_query_string).encode() | |
m = hashlib.sha512() | |
m.update(query_string) | |
query_hash = m.hexdigest() | |
else: | |
query_hash = None | |
payload = { | |
'access_key': self.access_key, | |
'nonce': str(uuid.uuid4()), | |
'query_hash': query_hash, | |
'query_hash_alg': 'SHA512', | |
} | |
jwt_token = jwt.encode(payload, self.secret_key) | |
authorize_token = 'Bearer {}'.format(jwt_token) | |
headers = {"Authorization": authorize_token} | |
return headers | |
def get_account(self): | |
headers = self.get_headers() | |
return requests.get(self.urls["전체계좌조회"], headers=headers) | |
def buy(self, market, price): | |
query = dict( | |
market=market, | |
side='bid', | |
price=price, | |
ord_type='price', | |
) | |
headers = self.get_headers(query=query) | |
return requests.post(self.urls["주문하기"], params=query, headers=headers) | |
def sell(self, market, volume): | |
query = dict( | |
market=market, | |
side='ask', | |
volume=volume, | |
ord_type='market', | |
) | |
headers = self.get_headers(query=query) | |
return requests.post(self.urls["주문하기"], params=query, headers=headers) | |
def get_order_chance(self, market): | |
query = dict( | |
market=market, | |
) | |
headers = self.get_headers(query=query) | |
return requests.get(self.urls["주문가능정보"], params=query, headers=headers) | |
def get_ticker(self, markets): | |
query = dict( | |
markets=markets, | |
) | |
return requests.get(self.urls["현재가정보"], params=query) | |
def get_assets(self): | |
assets = dict() | |
while True: | |
resp = self.get_account() | |
if resp.ok: break | |
else: time.sleep(1) | |
account = resp.json() | |
for item in account: | |
if item['currency'] == 'KRW': | |
cash = float(item['balance']) | |
market = '{}-{}'.format(item['unit_currency'], item['currency']) | |
print(f"{market} 주문가능정보 조회중 ", end='\r') | |
resp = self.get_order_chance(market) | |
if resp.ok: | |
data = resp.json() | |
assets[market] = dict( | |
avg_buy_price=float(data['ask_account']['avg_buy_price']), | |
balance=float(data['ask_account']['balance']), | |
) | |
markets = ', '.join(list(assets.keys())) | |
while True: | |
resp = self.get_ticker(markets) | |
if resp.ok: break | |
else: time.sleep(1) | |
tickers = resp.json() | |
for ticker in tickers: | |
market = ticker['market'] | |
assets[market]['price'] = float(ticker['trade_price']) | |
evaluation = assets[market]['price'] * assets[market]['balance'] | |
assets[market]['evaluation'] = evaluation | |
assets_total_evaluation = 0 | |
for market, asset_info in assets.items(): | |
assets_total_evaluation += asset_info['evaluation'] | |
total_evaluation = cash + assets_total_evaluation | |
return dict( | |
cash=cash, | |
assets=assets, | |
assets_total_evaluation=assets_total_evaluation, | |
total_evaluation=total_evaluation, | |
) | |
def rebalance(self, cash_ratio=0.1): | |
assets = self.get_assets() | |
target_evaluation = assets['total_evaluation']*(1-cash_ratio)/len(assets['assets']) | |
print(f'종목별 목표평가금액(KRW): {target_evaluation:10,.0f}') | |
print(f"현금/자산/총합(KRW): {assets['cash']:10,.0f}/{assets['assets_total_evaluation']:10,.0f}/{assets['total_evaluation']:10,.0f}") | |
for market, info in assets['assets'].items(): | |
delta_evaluation = target_evaluation-info['evaluation'] | |
if delta_evaluation>5000: # Buy | |
while True: | |
resp = self.buy(market=market, price=delta_evaluation) | |
if resp.ok: | |
print(f'[매수 {market:10}] 차액:{delta_evaluation:+10,.0f}') | |
break | |
else: | |
print(f'[지연 {market:10}] 차액:{delta_evaluation:+10,.0f}', end='\r') | |
time.sleep(1) | |
elif delta_evaluation<-5000: # Sell | |
while True: | |
resp = self.sell(market=market, volume=-delta_evaluation/info['price']) | |
if resp.ok: | |
print(f'[매도 {market:10}] 차액:{delta_evaluation:+10,.0f}') | |
break | |
else: | |
print(f'[지연 {market:10}] 차액:{delta_evaluation:+10,.0f}', end='\r') | |
time.sleep(1) | |
else: | |
print(f'[홀드 {market:10}] 차액:{delta_evaluation:+10,.0f}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment