Skip to content

Commit

Permalink
Merge pull request #362 from enarjord/v5.8.1_score_func
Browse files Browse the repository at this point in the history
V5.8.1 score func

- improved score logic
- add leverage kwarg
- fixes and improvements
  • Loading branch information
enarjord authored Nov 23, 2022
2 parents 4ab1671 + 1ce72fd commit e1055cf
Show file tree
Hide file tree
Showing 19 changed files with 623 additions and 954 deletions.
13 changes: 8 additions & 5 deletions binance.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import aiohttp
import numpy as np

from passivbot import Bot
from passivbot import Bot, logging
from procedures import print_, print_async_exception
from pure_funcs import ts_to_date, sort_dict_keys, format_float

Expand Down Expand Up @@ -209,7 +209,7 @@ async def transfer_from_derivatives_to_spot(self, coin: str, amount: float):
)

async def execute_leverage_change(self):
lev = 7 # arbitrary
lev = self.leverage
return await self.private_post(
self.endpoints["leverage"], {"symbol": self.symbol, "leverage": lev}
)
Expand Down Expand Up @@ -362,9 +362,12 @@ async def execute_cancellation(self, order: dict) -> dict:
"price": float(cancellation["price"]),
}
except Exception as e:
print(f"error cancelling order {order} {e}")
print_async_exception(cancellation)
traceback.print_exc()
if cancellation is not None and "code" in cancellation and cancellation["code"] == -2011:
logging.error(f"error cancelling order {cancellation} {order}") # neater error message
else:
print(f"error cancelling order {order} {e}")
print_async_exception(cancellation)
traceback.print_exc()
self.ts_released["force_update"] = 0.0
return {}

Expand Down
106 changes: 68 additions & 38 deletions bitget.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import pprint

from njit_funcs import round_
from passivbot import Bot
from passivbot import Bot, logging
from procedures import print_async_exception, print_
from pure_funcs import ts_to_date, sort_dict_keys, date_to_ts

Expand All @@ -24,12 +24,15 @@ def first_capitalized(s: str):


def truncate_float(x: float, d: int) -> float:
if x is None:
return 0.0
xs = str(x)
return float(xs[: xs.find(".") + d + 1])


class BitgetBot(Bot):
def __init__(self, config: dict):
self.is_logged_into_user_stream = False
self.exchange = "bitget"
super().__init__(config)
self.base_endpoint = "https://api.bitget.com"
Expand Down Expand Up @@ -82,7 +85,7 @@ def init_market_type(self):
self.market_type += "_linear_perpetual"
self.product_type = "umcbl"
self.inverse = self.config["inverse"] = False
self.min_cost = self.config["min_cost"] = 5.1
self.min_cost = self.config["min_cost"] = 5.5
elif self.symbol.endswith("USD"):
print("inverse perpetual")
self.symbol += "_DMCBL"
Expand Down Expand Up @@ -254,15 +257,19 @@ async def fetch_position(self) -> dict:
if elm["holdSide"] == "long":
position["long"] = {
"size": round_(float(elm["total"]), self.qty_step),
"price": truncate_float(float(elm["averageOpenPrice"]), self.price_rounding),
"liquidation_price": float(elm["liquidationPrice"]),
"price": truncate_float(elm["averageOpenPrice"], self.price_rounding),
"liquidation_price": 0.0
if elm["liquidationPrice"] is None
else float(elm["liquidationPrice"]),
}

elif elm["holdSide"] == "short":
position["short"] = {
"size": -abs(round_(float(elm["total"]), self.qty_step)),
"price": truncate_float(float(elm["averageOpenPrice"]), self.price_rounding),
"liquidation_price": float(elm["liquidationPrice"]),
"price": truncate_float(elm["averageOpenPrice"], self.price_rounding),
"liquidation_price": 0.0
if elm["liquidationPrice"] is None
else float(elm["liquidationPrice"]),
}
for elm in fetched_balance["data"]:
if elm["marginCoin"] == self.margin_coin:
Expand Down Expand Up @@ -567,7 +574,11 @@ async def init_exchange_config(self):
# set leverage
res = await self.private_post(
self.endpoints["set_leverage"],
params={"symbol": self.symbol, "marginCoin": self.margin_coin, "leverage": 20},
params={
"symbol": self.symbol,
"marginCoin": self.margin_coin,
"leverage": self.leverage,
},
)
print(res)
except Exception as e:
Expand Down Expand Up @@ -610,7 +621,7 @@ async def beat_heart_market_stream(self) -> None:
print_(["error sending heartbeat market", e])

async def subscribe_to_market_stream(self, ws):
await ws.send(
res = await ws.send(
json.dumps(
{
"op": "subscribe",
Expand All @@ -625,25 +636,16 @@ async def subscribe_to_market_stream(self, ws):
)
)

async def subscribe_to_user_stream(self, ws):
timestamp = int(time())
signature = base64.b64encode(
hmac.new(
self.secret.encode("utf-8"),
f"{timestamp}GET/user/verify".encode("utf-8"),
digestmod="sha256",
).digest()
).decode("utf-8")
async def subscribe_to_user_streams(self, ws):
res = await ws.send(
json.dumps(
{
"op": "login",
"op": "subscribe",
"args": [
{
"apiKey": self.key,
"passphrase": self.passphrase,
"timestamp": timestamp,
"sign": signature,
"instType": self.product_type.upper(),
"channel": "account",
"instId": "default",
}
],
}
Expand All @@ -657,7 +659,7 @@ async def subscribe_to_user_stream(self, ws):
"args": [
{
"instType": self.product_type.upper(),
"channel": "account",
"channel": "positions",
"instId": "default",
}
],
Expand All @@ -671,24 +673,41 @@ async def subscribe_to_user_stream(self, ws):
"op": "subscribe",
"args": [
{
"channel": "orders",
"instType": self.product_type.upper(),
"channel": "positions",
"instId": "default",
}
],
}
)
)
print(res)

async def subscribe_to_user_stream(self, ws):
if self.is_logged_into_user_stream:
await self.subscribe_to_user_streams(ws)
else:
await self.login_to_user_stream(ws)

async def login_to_user_stream(self, ws):
timestamp = int(time())
signature = base64.b64encode(
hmac.new(
self.secret.encode("utf-8"),
f"{timestamp}GET/user/verify".encode("utf-8"),
digestmod="sha256",
).digest()
).decode("utf-8")
res = await ws.send(
json.dumps(
{
"op": "subscribe",
"op": "login",
"args": [
{
"channel": "orders",
"instType": self.product_type.upper(),
"instId": "default",
"apiKey": self.key,
"passphrase": self.passphrase,
"timestamp": timestamp,
"sign": signature,
}
],
}
Expand All @@ -697,13 +716,17 @@ async def subscribe_to_user_stream(self, ws):
print(res)

async def transfer(self, type_: str, amount: float, asset: str = "USDT"):
return {"code": "-1", "msg": "Transferring funds not supported for Bybit"}
return {"code": "-1", "msg": "Transferring funds not supported for Bitget"}

def standardize_user_stream_event(
self, event: Union[List[Dict], Dict]
) -> Union[List[Dict], Dict]:

events = []
if "event" in event and event["event"] == "login":
self.is_logged_into_user_stream = True
return {"logged_in": True}
# logging.info(f"debug 0 {event}")
if "arg" in event and "data" in event and "channel" in event["arg"]:
if event["arg"]["channel"] == "orders":
for elm in event["data"]:
Expand All @@ -730,18 +753,25 @@ def standardize_user_stream_event(
standardized["filled"] = True
events.append(standardized)
if event["arg"]["channel"] == "positions":
long_pos = {"psize_long": 0.0, "pprice_long": 0.0}
short_pos = {"psize_short": 0.0, "pprice_short": 0.0}
for elm in event["data"]:
if elm["instId"] == self.symbol and "averageOpenPrice" in elm:
standardized = {
f"psize_{elm['holdSide']}": round_(
abs(float(elm["total"])), self.qty_step
if elm["holdSide"] == "long":
long_pos["psize_long"] = round_(abs(float(elm["total"])), self.qty_step)
long_pos["pprice_long"] = truncate_float(
elm["averageOpenPrice"], self.price_rounding
)
* (-1 if elm["holdSide"] == "short" else 1),
f"pprice_{elm['holdSide']}": truncate_float(
float(elm["averageOpenPrice"]), self.price_rounding
),
}
events.append(standardized)
elif elm["holdSide"] == "short":
short_pos["psize_short"] = -abs(
round_(abs(float(elm["total"])), self.qty_step)
)
short_pos["pprice_short"] = truncate_float(
elm["averageOpenPrice"], self.price_rounding
)
# absence of elemet means no pos
events.append(long_pos)
events.append(short_pos)

if event["arg"]["channel"] == "account":
for elm in event["data"]:
Expand Down
43 changes: 25 additions & 18 deletions bybit.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import numpy as np

from njit_funcs import round_
from passivbot import Bot
from passivbot import Bot, logging
from procedures import print_async_exception, print_
from pure_funcs import ts_to_date, sort_dict_keys, date_to_ts

Expand Down Expand Up @@ -333,9 +333,13 @@ async def execute_cancellation(self, order: dict) -> dict:
"price": order["price"],
}
except Exception as e:
print(f"error cancelling order {order} {e}")
print_async_exception(cancellation)
traceback.print_exc()
if cancellation is not None and "ret_code" in cancellation and cancellation["ret_code"] == 20001:
error_cropped = {k: v for k, v in cancellation.items() if k in ["ret_msg", "ret_code"]}
logging.error(f"error cancelling order {error_cropped} {order}") # neater error message
else:
print(f"error cancelling order {order} {e}")
print_async_exception(cancellation)
traceback.print_exc()
self.ts_released["force_update"] = 0.0
return {}

Expand Down Expand Up @@ -558,7 +562,6 @@ async def fetch_fills(
except Exception as e:
print("error fetching fills", e)
return []
print("ntufnt")
return fetched
print("fetch_fills not implemented for Bybit")
return []
Expand All @@ -572,18 +575,17 @@ async def init_exchange_config(self):
"/futures/private/position/leverage/save",
{
"symbol": self.symbol,
"position_idx": 1,
"buy_leverage": 0,
"sell_leverage": 0,
"buy_leverage": self.leverage,
"sell_leverage": self.leverage,
},
),
self.private_post(
"/futures/private/position/leverage/save",
"/futures/private/position/switch-isolated",
{
"symbol": self.symbol,
"position_idx": 2,
"buy_leverage": 0,
"sell_leverage": 0,
"is_isolated": False,
"buy_leverage": self.leverage,
"sell_leverage": self.leverage,
},
),
)
Expand All @@ -599,23 +601,28 @@ async def init_exchange_config(self):
{
"symbol": self.symbol,
"is_isolated": False,
"buy_leverage": 7,
"sell_leverage": 7,
"buy_leverage": self.leverage,
"sell_leverage": self.leverage,
},
)
print(res)
res = await self.private_post(
"/private/linear/position/set-leverage",
{"symbol": self.symbol, "buy_leverage": 7, "sell_leverage": 7},
{"symbol": self.symbol, "buy_leverage": self.leverage, "sell_leverage": self.leverage},
)
print(res)
elif "inverse_perpetual" in self.market_type:
res = await self.private_post(
"/v2/private/position/switch-isolated",
{"symbol": self.symbol, "is_isolated": False,
"buy_leverage": self.leverage, "sell_leverage": self.leverage},
)
print('1', res)
res = await self.private_post(
"/v2/private/position/leverage/save",
{"symbol": self.symbol, "leverage": 0},
{"symbol": self.symbol, "leverage": self.leverage, "leverage_only": True},
)

print(res)
print('2', res)
except Exception as e:
print(e)

Expand Down
34 changes: 34 additions & 0 deletions configs/live/neat_grid_mode.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{"config_name": "neat_grid_118_symbols_626days",
"logging_level": 0,
"long": {"auto_unstuck_ema_dist": 0,
"auto_unstuck_wallet_exposure_threshold": 0.012195009245955374,
"backwards_tp": true,
"ema_span_0": 240,
"ema_span_1": 307.0566300659701,
"enabled": true,
"eprice_exp_base": 0.9814428052289045,
"eqty_exp_base": 1.8910056941476132,
"grid_span": 0.35120092600982644,
"initial_eprice_ema_dist": -0.0724883315452062,
"initial_qty_pct": 0.015,
"markup_range": 0.029915290808625504,
"max_n_entry_orders": 9,
"min_markup": 0.003,
"n_close_orders": 10,
"wallet_exposure_limit": 0.1},
"short": {"auto_unstuck_ema_dist": 0.02,
"auto_unstuck_wallet_exposure_threshold": 0.010010044896137589,
"backwards_tp": true,
"ema_span_0": 3578.5992758249126,
"ema_span_1": 1300.2248624251254,
"enabled": true,
"eprice_exp_base": 0.9,
"eqty_exp_base": 2.741199913514829,
"grid_span": 0.35422351795434553,
"initial_eprice_ema_dist": 0.005310285956060753,
"initial_qty_pct": 0.015,
"markup_range": 0.011750423363748088,
"max_n_entry_orders": 7,
"min_markup": 0.003,
"n_close_orders": 8,
"wallet_exposure_limit": 0.1}}
Loading

0 comments on commit e1055cf

Please sign in to comment.