Skip to content

Commit 97c5636

Browse files
committed
Added trade capping
1 parent 4fc5600 commit 97c5636

9 files changed

+81
-17
lines changed

API/TradeInfo.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from Bot.AccountBalances import Balance, AccountBalances
2+
from Bot.Strategy.TargetsAndStopLossStrategy import TargetsAndStopLossStrategy
3+
from Bot.Strategy.TradingStrategy import TradingStrategy
4+
5+
6+
class TradeInfo:
7+
def __init__(self, strategy: TradingStrategy):
8+
self.status = None
9+
self.symbol = None
10+
self.balance = 0
11+
12+
self.possible_strategies = []
13+
self.active_strategy = None
14+
self.active_target = None
15+
16+
self.stop_loss_traget = None
17+
self.entry_target = None
18+
self.exit_targets = []
19+
20+
21+
if strategy:
22+
self.extract_info(strategy)
23+
24+
def extract_info(self, strategy):
25+
trade = strategy.trade
26+
self.symbol = trade.symbol
27+
self.status = trade
28+
self.balance = AccountBalances().get_balance(trade.asset)
29+
30+
if isinstance(strategy, TargetsAndStopLossStrategy):
31+
if strategy.strategy_sl:
32+
sl_name = self.class_name(strategy.strategy_sl)
33+
if strategy.strategy_sl.is_stoploss_order_active():
34+
self.active_strategy = sl_name
35+
36+
self.possible_strategies.append(sl_name)
37+
38+
if strategy.strategy_entry and not strategy.strategy_entry.is_completed() and trade.is_new():
39+
enty_name = self.class_name(strategy.strategy_exit)
40+
self.active_strategy = enty_name
41+
self.possible_strategies.append(enty_name)
42+
43+
44+
def class_name(self, obj):
45+
return obj.__class__.__name__

Bot/EntryExitSettings.py

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ def __init__(self,
2727
if not self.sl_threshold:
2828
self.sl_threshold = Value("1%")
2929
self.pullback_threshold = Value("1%")
30+
else:
31+
if not self.sl_threshold:
32+
self.sl_threshold = Value("0")
3033

3134
self.side = Side(side.lower()) if side else None
3235
self.type = Entry(type.lower())

Bot/Strategy/EntryStrategy.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import traceback
2+
13
from binance.exceptions import BinanceAPIException
24

35
from Bot.TradeEnums import OrderStatus, Side
@@ -67,7 +69,7 @@ def get_trade_volume(self, exchange_rate):
6769
# self.exchange_info.adjust_quanity(t.vol)
6870
return buying_currency_vol / exchange_rate
6971

70-
return t.vol.get_val(self.balance.avail)
72+
return t.vol.get_val(self.trade.get_cap(self.balance.avail))
7173

7274
def on_smart_buy(self, trigger_order_price, current_price):
7375
if not trigger_order_price:
@@ -113,12 +115,15 @@ def handle_stoploss_order(self, trigger_order_price, current_price):
113115
t = self.trade_target()
114116

115117
if t.is_active():
116-
status = self.fx.get_order_status(self.symbol(), t.id)
118+
try:
119+
status = self.fx.get_order_status(self.symbol(), t.id)
117120

118-
if self.fx.cancel_order(self.symbol(), t.id):
119-
t.set_canceled()
120-
self.trigger_target_updated()
121-
self.balance.avail = float(status["origQty"]) - float(status["executedQty"])
121+
if self.fx.cancel_order(self.symbol(), t.id):
122+
t.set_canceled()
123+
self.trigger_target_updated()
124+
self.balance.avail = float(status["origQty"]) - float(status["executedQty"])
125+
except BinanceAPIException:
126+
self.logError(traceback.format_exc())
122127

123128

124129
th_sl_price = self.smart_order.sl_threshold.get_val(t.price)
@@ -153,7 +158,6 @@ def handle_stoploss_order(self, trigger_order_price, current_price):
153158
t.set_active(order['orderId'])
154159
self.trigger_target_updated()
155160

156-
157161
def update_last_smart_price(self, trigger_price):
158162
if self.need_update_last_trigger_price(trigger_price):
159163
self.get_trade_section().best_price = trigger_price

Bot/Strategy/PlaceOrderStrategy.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def validate_all_completed(self, targets):
7979
return all(t.status.is_completed() for t in targets)
8080

8181
def prepare_volume_allocation(self, targets):
82-
bal = self.balance.avail + (self.balance.locked if any(t.is_active() for t in targets) else 0)
82+
bal = self.trade.get_cap(self.balance.avail) + (self.balance.locked if any(t.is_active() for t in targets) else 0)
8383

8484
if bal <= 0:
8585
self.logWarning('Available balance is 0')

Bot/Strategy/StopLossStrategy.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def set_stoploss_order(self):
144144

145145
# stop_trigger
146146

147-
volume = self.initial_sl().vol.get_val(self.balance.avail)
147+
volume = self.initial_sl().vol.get_val(self.trade.get_cap(self.balance.avail))
148148

149149
try:
150150
order = self.fx.create_stop_order(

Bot/Strategy/TargetsAndStopLossStrategy.py

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ def on_order_status_changed(self, t: Target, data):
127127
# validate balance and activate trade only if there are trading targets
128128
if self.strategy_exit:
129129
AccountBalances().update_balances(self.fx.get_all_balances_dict())
130+
self.trade.cap = self.balance.avail
130131
self.trade.set_active()
131132
self.trigger_target_updated()
132133
else:

Bot/Strategy/TradingStrategy.py

+4
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ def get_single_price(self, price, selector=None):
160160

161161
return price[selector]
162162

163+
def get_info(self):
164+
# return TradeInfo(self)
165+
pass
166+
163167
def price_selector(self, side=None):
164168
if not side:
165169
side = self.trade_side()

Bot/Target.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ def is_entry_target(self):
5656

5757
def __str__(self):
5858
if PriceHelper.is_float_price(self.price):
59-
return '{}:{:.08f}@{}'.format('StopLoss' if self.is_stoploss_target() else 'Regular', self.price, self.vol)
59+
return '{}:{:.08f}@{}'.format(self.__class__.__name__, self.price, self.vol)
6060
else:
61-
return '{}:{}@{}'.format('StopLoss' if self.is_stoploss_target() else 'Regular', self.price, self.vol)
61+
return '{}:{}@{}'.format(self.__class__.__name__, self.price, self.vol)
6262

6363

6464
def serializable_dict(self):

Bot/Trade.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,26 @@
66

77

88
class Trade(CustomSerializable):
9-
def __init__(self, symbol, side, asset, sl_settings=None, status=None, entry=None, exit=None):
10-
9+
# def __init__(self, symbol, side, asset, status=None, sl_settings=None, entry=None, exit=None):
10+
def __init__(self, symbol, side, asset, status=None, *args, **kvargs):
1111
self.side = Side(side.lower())
1212
self.symbol = symbol.upper()
1313
self.asset = asset.upper()
1414

1515
self.entry: EntryExitSettings = None
1616
self.exit: EntryExitSettings = None
1717

18-
self._init_entry_exit(True, entry, self.side)
19-
self._init_entry_exit(False, exit, self.side)
18+
self._init_entry_exit(True, kvargs.get('entry'), self.side)
19+
self._init_entry_exit(False, kvargs.get('exit'), self.side)
2020

21-
self.sl_settings = StopLossSettings(**sl_settings) if sl_settings else None
21+
self.sl_settings = StopLossSettings(**kvargs.get('sl_settings')) if kvargs.get('sl_settings') else None
2222

2323
if status:
2424
self.status = OrderStatus(status.lower())
2525
else:
26-
self.status = OrderStatus.ACTIVE if not entry else OrderStatus.NEW
26+
self.status = OrderStatus.ACTIVE if not kvargs.get('entry') else OrderStatus.NEW
27+
28+
self.cap = float(kvargs.get('cap')) if kvargs.get('cap') else None
2729

2830
def _init_entry_exit(self, is_entry, data, side: Side):
2931
if data:
@@ -35,6 +37,9 @@ def _init_entry_exit(self, is_entry, data, side: Side):
3537
else:
3638
self.exit = EntryExitSettings(is_entry=is_entry, **data)
3739

40+
def get_cap(self, available_balance):
41+
return min(self.cap if self.cap else available_balance, available_balance)
42+
3843
def is_sell(self):
3944
return self.side.is_sell()
4045

@@ -63,6 +68,8 @@ def serializable_dict(self):
6368
d.pop('entry', None)
6469
if not self.exit:
6570
d.pop('exit', None)
71+
if not self.cap:
72+
d.pop('cap', None)
6673
return d
6774

6875
def get_all_active_placed_targets(self) -> List[Target]:

0 commit comments

Comments
 (0)