ENHANCEMENT: New common API round_tick and round_step before placing order
Opened this issue · 1 comments
Problem Statement
Often for take profit (TP) and stop loss (SL) calculation, if they are certain percentage away from the order price, the result will not be matching with the tick size (step size for quantity).
Observation
Chances are users would have created their own version of round_tick and round_step function call to change TP, SL and quantity in order to cater for need to comply with exchange's rick size and step size requirements.
Opportunity
I've came across one of the exchanges providing roundStep API to their users, I would like to extend the request for PyBit to consider providing both round_tick and round_step to lead the crypto market instead.
Example Use Case
take_profit = round_tick(ask * (1 + 10/100))
stop_loss = round_tick(bid * (1 + 5/100))
single_quantity = round_step(total_quantity / 5))
Things to Watch Out
- Assuming user doesn't have to deal with symbol's decimal point precision by default.
- Assuming API is intelligent enough to decide it is round up or round down.
Benefits for PyBit Users
Prevent non-obvious error such as the following that I've spend an hour and eventually figured out it is caused by TP and SL are not complying with tick size:
Traceback (most recent call last):
File "D:\venv\lib\site-packages\pybit\__init__.py", line 1812, in _submit_request
s_json = s.json()
File "D:\venv\lib\site-packages\requests\models.py", line 900, in json
return complexjson.loads(self.text, **kwargs)
File "C:\Users\xxx\AppData\Local\Programs\Python\Python39\lib\json\__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "C:\Users\xxx\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 340, in decode
raise JSONDecodeError("Extra data", s, end)
json.decoder.JSONDecodeError: Extra data: line 1 column 194 (char 193)
This would definitely be a really useful "helper" method, and I have implemented similar functionality in the past which has the same goal
def conform_price(price: float, tick_size=0.5, floor=False, ceil=False):
tick_multiple = 1 / tick_size
if not floor and not ceil:
return round(price * tick_multiple) / tick_multiple
elif floor:
return math.floor(price * tick_multiple) / tick_multiple
else: # ceil
return math.ceil(price * tick_multiple) / tick_multiple
For ease of use tick_size
defaults to 0.5
as that is what the most popular bybit futures markets use, but the function works regardless of its value.
I will do this at some point in the future