add contract_size as a config to inverse futures

This commit is contained in:
Saleh Mir
2021-03-09 16:20:50 +01:00
parent 25fb188331
commit 53992318ff
8 changed files with 67 additions and 11 deletions

View File

@@ -116,6 +116,8 @@ config = {
'futures_leverage_mode': 'cross',
# 1x, 2x, 10x, 50x, etc. Enter as integers
'futures_leverage': 1,
# Price per contract, also called the contract-multiplier
'contract_size': 100,
'assets': [
{'asset': 'BTC', 'balance': 1},

View File

@@ -28,12 +28,14 @@ class InverseFuturesExchange(Exchange):
starting_assets: list,
fee_rate: float,
futures_leverage_mode: str,
futures_leverage: int
futures_leverage: int,
contract_size: int,
):
super().__init__(name, starting_assets, fee_rate, 'inverse futures')
self.futures_leverage_mode = futures_leverage_mode
self.futures_leverage = futures_leverage
self.contract_size = contract_size
for item in starting_assets:
self.buy_orders[item['asset']] = DynamicNumpyArray((10, 2))
@@ -63,7 +65,6 @@ class InverseFuturesExchange(Exchange):
settlement_currency = jh.base_asset(symbol)
return self.assets[settlement_currency]
# TODO
def available_margin(self, symbol=''):
if symbol == '':
raise ValueError
@@ -125,8 +126,9 @@ class InverseFuturesExchange(Exchange):
# make sure we don't spend more than we're allowed considering current allowed leverage
if order.type != order_types.MARKET or skip_market_order:
if not order.is_reduce_only:
order_size = abs(order.qty * order.price)
remaining_margin = self.available_margin()
# TODO: add contract_multiplier to the equation
order_size = abs(order.qty / order.price)
remaining_margin = self.available_margin(order.symbol)
if order_size > remaining_margin:
raise InsufficientMargin(
'You cannot submit an order for ${} when your margin balance is ${}'.format(

View File

@@ -106,6 +106,8 @@ config = {
'futures_leverage_mode': 'cross',
# 1x, 2x, 10x, 50x, etc. Enter as integers
'futures_leverage': 1,
# Price per contract, also called the contract-multiplier
'contract_size': 100,
'assets': [
{'asset': 'BTC', 'balance': 1},

View File

@@ -29,6 +29,7 @@ class ExchangesState:
name, starting_assets, fee,
futures_leverage_mode=jh.get_config('env.exchanges.{}.futures_leverage_mode'.format(name)),
futures_leverage=jh.get_config('env.exchanges.{}.futures_leverage'.format(name)),
contract_size=jh.get_config('env.exchanges.{}.contract_size'.format(name)),
)
else:
raise InvalidConfig('Value for exchange type in your config file in not valid. Supported values are "spot" and "futures"')

View File

@@ -6,10 +6,13 @@ class TestCanDetectInverseFutures(Strategy):
def should_long(self) -> bool:
if self.index == 0:
# current capital should be 1 BTC
assert self.capital == 1
assert self.capital == 100
assert self.position.exchange.type == 'inverse futures'
assert self.symbol == 'BTC-PERP'
assert self.leverage == 2
assert self.position.exchange.contract_size == 1
# TODO:
# assert self.contract_size == 1
return False

View File

@@ -0,0 +1,31 @@
from jesse.strategies import Strategy
from jesse import utils
class TestInverseFuturesLongTrade(Strategy):
def should_long(self) -> bool:
if self.index == 0:
assert self.position.exchange.contract_size == 100
return self.price == 10
def should_short(self) -> bool:
return False
def go_long(self):
entry = 10
# assuming contract size is 100, buy with all capital
qty = self.capital * self.price / 100
self.buy = qty, entry
self.take_profit = qty, 20
def go_short(self):
pass
def should_cancel(self):
return False
def update_position(self):
if 20 > self.price > 10:
print(self.position.qty)
assert self.position.qty == 10

View File

@@ -5,5 +5,10 @@ def test_can_detect_inverse_futures():
single_route_backtest('TestCanDetectInverseFutures', is_futures_trading=True, is_inverse_futures=True, leverage=2)
# def test_long_trade():
# single_route_backtest('TestInverseFuturesLongTrade', is_futures_trading=True, is_inverse_futures=True)
def test_long_trade():
single_route_backtest(
'TestInverseFuturesLongTrade',
is_futures_trading=True,
is_inverse_futures=True,
contract_size=100
)

View File

@@ -33,13 +33,21 @@ def get_btc_candles(symbol='BTC-USDT'):
return candles
def set_up(routes=None, is_futures_trading=True, leverage=1, leverage_mode='cross', zero_fee=False, is_inverse_futures=False):
def set_up(
routes=None,
is_futures_trading=True,
leverage=1,
leverage_mode='cross',
zero_fee=False,
is_inverse_futures=False,
contract_size=1,
):
reset_config()
if is_inverse_futures:
config['env']['exchanges'][exchanges.SANDBOX]['assets'] = [
{'asset': 'USDT', 'balance': 0},
{'asset': 'BTC', 'balance': 1},
{'asset': 'BTC', 'balance': 100},
]
else:
config['env']['exchanges'][exchanges.SANDBOX]['assets'] = [
@@ -59,6 +67,7 @@ def set_up(routes=None, is_futures_trading=True, leverage=1, leverage_mode='cros
config['env']['exchanges'][exchanges.SANDBOX]['type'] = 'inverse futures'
config['env']['exchanges'][exchanges.SANDBOX]['futures_leverage_mode'] = leverage_mode
config['env']['exchanges'][exchanges.SANDBOX]['futures_leverage'] = leverage
config['env']['exchanges'][exchanges.SANDBOX]['contract_size'] = contract_size
else:
config['env']['exchanges'][exchanges.SANDBOX]['type'] = 'spot'
@@ -68,7 +77,7 @@ def set_up(routes=None, is_futures_trading=True, leverage=1, leverage_mode='cros
store.reset(True)
def single_route_backtest(strategy_name: str, is_futures_trading=True, is_inverse_futures=False, leverage=1):
def single_route_backtest(strategy_name: str, is_futures_trading=True, is_inverse_futures=False, leverage=1, contract_size=1):
"""
used to simplify simple tests
"""
@@ -76,7 +85,8 @@ def single_route_backtest(strategy_name: str, is_futures_trading=True, is_invers
[(exchanges.SANDBOX, 'BTC-USDT' if not is_inverse_futures else 'BTC-PERP', timeframes.MINUTE_1, strategy_name)],
is_futures_trading=is_futures_trading,
is_inverse_futures=is_inverse_futures,
leverage=leverage
leverage=leverage,
contract_size=contract_size
)
# dates are fake. just to pass required parameters
backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles('BTC-USDT' if not is_inverse_futures else 'BTC-PERP'))