본문 바로가기

Python 파이썬 공부하기

파이썬 초보의 Daybit API 이용하기 - 8. 주문 잘못된 조건 예외처리들

728x90
반응형

모든 예제는 Daybit API 문서를 참고합니다.

https://docs.daybit.com/kr


 오늘은 create_order를 이용해서 주문을 할 때 예외처리 해야하는 것들에 대해 알아보겠습니다.


 일단 주문 실패한 경우를 볼까요?


이전에 했던 주문을 넣는 예제를 이용했습니다.

BTC 로 ETH을 사려고 시도 했는데,

다음과 같이 에러가 나면서 프로그램이 종료가 됩니다.

에러 문구를 보시면 error: order_violates_min_usd라고 되어있습니다.

daybit에서는 최소 주문 금액이 10달러 이상인데 이를 만족하지 못해서 띄우는 에러입니다.


실제로 내 주문 내역을 보면 주문 내역은 있으나 상태가 거절됨으로 표시된 것을 알 수 있습니다.

잘못된 조건의 주문이 들어오면 거절이 됩니다.


실제로 ETH 0.00377888개를 살 수 있는 양밖에 가지고 있지 않아서 (10달러에 택도없는 먼지같은 금액이군요..)

그만큼 주문을 넣었더니 최소 주문 금액을 만족하지 못해 에러가 발생한 것입니다.

이렇게 에러가 발생하면 While문 반복하고 있어도 프로그램이 종료가 됩니다.

따라서 예외처리를 해주어야 합니다.


 일단 기본적으로 최소주문금액(10달러 이상)을 만족하는지와, 주문할 수량이 내가 가지고 있는 자산을 초과하지 않는지,

두가지를 확인하면 됩니다.


위의 create_order 함수로 주문을 하게 되는데, 예를 들어 봅시다.

최소주문금액 10달러 이상은 어떻게 확인할 까요?

BTC로 ETH을 사고 판다고 가정합시다. 

다음과 같이 됩니다.

 amount(ETH 주문 수량) x ETH의 현재 USD  >= 10달러

즉, amount 값과 ETH의 USD값을 곱한 값을 알면 최소주문금액을 만족하는지 알 수 있습니다.


 어라 그런데 ETH의 현재 USD 값을 알아야하네요?

요건 어디서 알 수 있을까요

다행히 API로 제공을 해주더군요.

coin_prices() 함수를 쓰면 됩니다!

이 함수는 다음과 같은 딕셔너리를 반환합니다.


이를 이용하면 다음과 같이 활용할 수 있습니다.

 


coin_prices = await daybit.coin_prices()


ETH_USD_price = coin_prices['ETH']['usd_price']
minETHUSD = Decimal(ETH_USD_price) * sell_amount

if minETHUSD > Decimal(10.0):
print("최소주문금액 만족")
else:
print("최소주문금액 만족안함")

ETH의 USD가격을 불러와서

매도할 수량과 곱합니다.

이 값이 10을 넘으면 최소주문금액을 만족하는 것입니다.


create_order 주문을 넣을 때 최소주문금액을 만족하는 주문만 넣어줘야 합니다. 

그렇지 않으면 아까도 봤듯이 주문이 거절당합니다.




 두번째는 주문수량입니다. 가능한 주문 수량을 초과해도 마찬가지로 주문이 거절당합니다.

예를 들어 자신은 1ETH를 살 수 있는 BTC 밖에 없는데 5ETH 매수 주문을 걸면 거절당합니다.

사실 이전 예제들에서 보듯이

일단 자신의 자산을 가져와서 거기에 맞춰 주문을 하기 때문에 더 많은 수량을 주문할 일은 거의 없습니다만,,

가끔 소수점 오차나, 내가 계산을 잘못해서 (코딩을 잘못한다던지..) 수량초과하여 거절당하는 경우가 있었습니다.


 이것은 간단하게 try~ except 구문을 이용하여

에러를 받아내도록 합시다. 사실 위의 최소주문 금액도 이걸로 가능합니다.




예제

import asyncio
from contextlib import suppress
from decimal import Decimal
from pprint import pprint

from pydaybit.exceptions import OrderExceededAssetValues, OrderOutOfPriceRange, OrderViolatesMinUSD
from pydaybit import Daybit, PARAM_API_KEY, PARAM_API_SECRET
from pydaybit.exceptions import OrderAlreadyClosed


async def current_price(daybit, quote, base):
summary_intvl = sorted((await daybit.market_summary_intvls()).keys())[0]
price = (await (daybit.market_summaries / summary_intvl)())['{}-{}'.format(quote, base)]['close']
return Decimal(price)


async def daybit_create_order():
async with Daybit(params={PARAM_API_KEY: "Your active Key",
PARAM_API_SECRET: "Your secret Key"}) as daybit:
quote = 'BTC'
base = 'ETH'


tick_price = Decimal((await daybit.markets())['{}-{}'.format(quote, base)]['tick_price'])
tick_amount = Decimal((await daybit.coins())[base]['tick_amount'])

print(tick_amount)

# 현재 가격
price = (await current_price(daybit, quote, base)).quantize(tick_price)
sellPrice = (price + tick_price*10).quantize(tick_price) #매도 주문을 넣을 가격
buyPrice = (price - tick_price*10).quantize(tick_price) #매수 주문을 넣을 가격


myAsset = await daybit.my_assets()
btcAsset = myAsset['BTC']
ethAsset = myAsset['ETH']

buy_amount = (Decimal(btcAsset['available']) / buyPrice).quantize(tick_amount)
sell_amount = (Decimal(ethAsset['available'])).quantize(tick_amount)


coin_prices = await daybit.coin_prices()


ETH_USD_price = coin_prices['ETH']['usd_price']
minETHUSD = Decimal(ETH_USD_price) * sell_amount

if minETHUSD > Decimal(10.0):
print("최소주문금액 만족")
else:
print("최소주문금액 만족안함")





#BTC 가 ETH 보다 더 많을 때
#ETH 매수 주문
if Decimal(btcAsset['available']) > (Decimal(ethAsset['available']) * price):

print(tick_amount)
print(buyPrice)
print("buy_amount : %s" %buy_amount)

try:
response = await daybit.create_order(
sell=False,
role='both',
quote=quote,
base=base,
price=buyPrice,
amount=buy_amount,
cond_type='none',
)
except OrderExceededAssetValues as e:
print(e)
#주문가능한 수량 초과

except OrderOutOfPriceRange as e:
print(e)
#주문 가격 범위 초과
except OrderViolatesMinUSD as e:
print(e)
#최소주문수량 만족하지 않음.
except:
print("fail buy order another except !!")


#BTC 가 ETH 보다 적을 때
#ETH 매도 주문
elif Decimal(btcAsset['available']) < (Decimal(ethAsset['available']) * price):
try:
response = await daybit.create_order(
sell=True,
role='both',
quote=quote,
base=base,
price=sellPrice,
amount=sell_amount,
cond_type='none',
)
except OrderExceededAssetValues as e:
print(e)
#주문가능한 수량 초과

except OrderOutOfPriceRange as e:
print(e)
#주문 가격 범위 초과
except OrderViolatesMinUSD as e:
print(e)
#최소주문수량 만족하지 않음.
except:
print("fail sell order another except !!")




pprint(response)

with suppress(OrderAlreadyClosed):
await daybit.cancel_order(response['id'])


asyncio.get_event_loop().run_until_complete(daybit_create_order())


 

저번에 했던 사고 파는 주문을 넣는 예제에서 추가한 것입니다.



 


from pydaybit.exceptions import OrderExceededAssetValues, OrderOutOfPriceRange, OrderViolatesMinUSD

일단 위 부분이 추가되었습니다.

에러를 받을 수 있는 여러가지 exceptions들이 있는데 그 중에서 주문할 때 가장 많이 발생할만한 3가지를 추가하였습니다.

이 부분은 API문서에도 잘 나와있지 않더라구요.




try:
response = await daybit.create_order(
sell=False,
role='both',
quote=quote,
base=base,
price=buyPrice,
amount=buy_amount,
cond_type='none',
)
except OrderExceededAssetValues as e:
print(e)
#주문가능한 수량 초과

except OrderOutOfPriceRange as e:
print(e)
#주문 가격 범위 초과
except OrderViolatesMinUSD as e:
print(e)
#최소주문수량 만족하지 않음.
except:
print("fail buy order another except !!")

 

주문하는 부분입니다. create_order 함수를 try로 덮어주고

except를 각각 나눠서 적어줍니다.

예를 들어 최수수량주문을 만족하지 않고 에러가 발생할 경우 

except OrderViolatesMinUSD as e:
print(e)

이 부분을 실행하게 됩니다.

e를 출력하면 에러에 대한 정보를 출력합니다.



except:
print("fail buy order another except !!")

이 부분은 위의 세가지 에러유형이 아닌 에러가 발생했을 때 실행되게 됩니다.


이렇게 try ~ except 구문을 사용하면

잘못된 주문을 걸어도 예외처리를 할 수 있게 되고

프로그램이 종료가 되지 않습니다.


그래서 while문으로 반복하는 프로그램에서도 

에러 발생해도 프로그램이 종료가 되지 않으므로 적절하게 에러를 처리하면

자동으로 다시 정상주문을 걸 수 있습니다.



 




읽어주셔서 감사합니다.

혹시 제 글이 도움이 되셨다면,

Daybit 초대 코드를 입력하지 않으신 분이 있다면 저의 초대코드를 입력해주시면 감사하겠습니다.

초대 코드 : ZkMZdral










반응형