Adding templates for leverage/short tests
This commit is contained in:
parent
8f944283da
commit
a9bd0700ed
27
TODO
27
TODO
@ -12,6 +12,33 @@ Files to edit
|
|||||||
|
|
||||||
Tests
|
Tests
|
||||||
tests/test_persistence.pys
|
tests/test_persistence.pys
|
||||||
|
init with
|
||||||
|
lev & bor
|
||||||
|
lev
|
||||||
|
bor
|
||||||
|
neither lev nor bor
|
||||||
|
adjust_stop_loss
|
||||||
|
short
|
||||||
|
leverage
|
||||||
|
is_opening_trade
|
||||||
|
short
|
||||||
|
long
|
||||||
|
shortBuy
|
||||||
|
longSell
|
||||||
|
is_closing_trade
|
||||||
|
short
|
||||||
|
long
|
||||||
|
shortBuy
|
||||||
|
longSell
|
||||||
|
update, close, update fee
|
||||||
|
possible to test?
|
||||||
|
calc_profit
|
||||||
|
* * create a few shorts, a few leveraged longs test correct ratio
|
||||||
|
calc_profit_ratio
|
||||||
|
* create a few shorts, a few leveraged longs test correct ratio
|
||||||
|
get_open_trades
|
||||||
|
* create a short, check if exists
|
||||||
|
|
||||||
tests/test_freqtradebot.py
|
tests/test_freqtradebot.py
|
||||||
|
|
||||||
later
|
later
|
||||||
|
@ -66,7 +66,8 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
|||||||
close_profit_abs = get_column_def(
|
close_profit_abs = get_column_def(
|
||||||
cols, 'close_profit_abs',
|
cols, 'close_profit_abs',
|
||||||
f"(amount * close_rate * (1 - {fee_close})) - {open_trade_value}")
|
f"(amount * close_rate * (1 - {fee_close})) - {open_trade_value}")
|
||||||
close_order_status = get_column_def(cols, 'close_order_status', 'null')
|
# TODO-mg: update to exit order status
|
||||||
|
sell_order_status = get_column_def(cols, 'sell_order_status', 'null')
|
||||||
amount_requested = get_column_def(cols, 'amount_requested', 'amount')
|
amount_requested = get_column_def(cols, 'amount_requested', 'amount')
|
||||||
|
|
||||||
# Schema migration necessary
|
# Schema migration necessary
|
||||||
@ -88,7 +89,7 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
|||||||
stake_amount, amount, amount_requested, open_date, close_date, open_order_id,
|
stake_amount, amount, amount_requested, open_date, close_date, open_order_id,
|
||||||
stop_loss, stop_loss_pct, initial_stop_loss, initial_stop_loss_pct,
|
stop_loss, stop_loss_pct, initial_stop_loss, initial_stop_loss_pct,
|
||||||
stoploss_order_id, stoploss_last_update,
|
stoploss_order_id, stoploss_last_update,
|
||||||
max_rate, min_rate, sell_reason, close_order_status, strategy,
|
max_rate, min_rate, sell_reason, sell_order_status, strategy,
|
||||||
timeframe, open_trade_value, close_profit_abs,
|
timeframe, open_trade_value, close_profit_abs,
|
||||||
leverage, borrowed, borrowed_currency, collateral_currency, interest_rate, liquidation_price, is_short
|
leverage, borrowed, borrowed_currency, collateral_currency, interest_rate, liquidation_price, is_short
|
||||||
)
|
)
|
||||||
@ -111,7 +112,7 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
|||||||
{initial_stop_loss_pct} initial_stop_loss_pct,
|
{initial_stop_loss_pct} initial_stop_loss_pct,
|
||||||
{stoploss_order_id} stoploss_order_id, {stoploss_last_update} stoploss_last_update,
|
{stoploss_order_id} stoploss_order_id, {stoploss_last_update} stoploss_last_update,
|
||||||
{max_rate} max_rate, {min_rate} min_rate, {sell_reason} sell_reason,
|
{max_rate} max_rate, {min_rate} min_rate, {sell_reason} sell_reason,
|
||||||
{close_order_status} close_order_status,
|
{sell_order_status} sell_order_status,
|
||||||
{strategy} strategy, {timeframe} timeframe,
|
{strategy} strategy, {timeframe} timeframe,
|
||||||
{open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs,
|
{open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs,
|
||||||
{leverage} leverage, {borrowed} borrowed, {borrowed_currency} borrowed_currency,
|
{leverage} leverage, {borrowed} borrowed, {borrowed_currency} borrowed_currency,
|
||||||
@ -121,6 +122,8 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
|||||||
"""))
|
"""))
|
||||||
|
|
||||||
# TODO: Does leverage go in here?
|
# TODO: Does leverage go in here?
|
||||||
|
|
||||||
|
|
||||||
def migrate_open_orders_to_trades(engine):
|
def migrate_open_orders_to_trades(engine):
|
||||||
with engine.begin() as connection:
|
with engine.begin() as connection:
|
||||||
connection.execute(text("""
|
connection.execute(text("""
|
||||||
|
@ -258,7 +258,7 @@ class LocalTrade():
|
|||||||
# Lowest price reached
|
# Lowest price reached
|
||||||
min_rate: float = 0.0
|
min_rate: float = 0.0
|
||||||
sell_reason: str = ''
|
sell_reason: str = ''
|
||||||
close_order_status: str = ''
|
sell_order_status: str = ''
|
||||||
strategy: str = ''
|
strategy: str = ''
|
||||||
timeframe: Optional[int] = None
|
timeframe: Optional[int] = None
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ class LocalTrade():
|
|||||||
'profit_abs': self.close_profit_abs,
|
'profit_abs': self.close_profit_abs,
|
||||||
|
|
||||||
'sell_reason': self.sell_reason,
|
'sell_reason': self.sell_reason,
|
||||||
'close_order_status': self.close_order_status,
|
'sell_order_status': self.sell_order_status,
|
||||||
'stop_loss_abs': self.stop_loss,
|
'stop_loss_abs': self.stop_loss,
|
||||||
'stop_loss_ratio': self.stop_loss_pct if self.stop_loss_pct else None,
|
'stop_loss_ratio': self.stop_loss_pct if self.stop_loss_pct else None,
|
||||||
'stop_loss_pct': (self.stop_loss_pct * 100) if self.stop_loss_pct else None,
|
'stop_loss_pct': (self.stop_loss_pct * 100) if self.stop_loss_pct else None,
|
||||||
@ -502,7 +502,7 @@ class LocalTrade():
|
|||||||
self.close_profit = self.calc_profit_ratio()
|
self.close_profit = self.calc_profit_ratio()
|
||||||
self.close_profit_abs = self.calc_profit()
|
self.close_profit_abs = self.calc_profit()
|
||||||
self.is_open = False
|
self.is_open = False
|
||||||
self.close_order_status = 'closed'
|
self.sell_order_status = 'closed'
|
||||||
self.open_order_id = None
|
self.open_order_id = None
|
||||||
if show_msg:
|
if show_msg:
|
||||||
logger.info(
|
logger.info(
|
||||||
@ -576,8 +576,10 @@ class LocalTrade():
|
|||||||
|
|
||||||
close_trade = Decimal(self.amount) * Decimal(rate or self.close_rate) # type: ignore
|
close_trade = Decimal(self.amount) * Decimal(rate or self.close_rate) # type: ignore
|
||||||
fees = close_trade * Decimal(fee or self.fee_close)
|
fees = close_trade * Decimal(fee or self.fee_close)
|
||||||
#TODO: Interest rate could be hourly instead of daily
|
# TODO: This interest rate is bad, doesn't get fractions of days
|
||||||
interest = ((Decimal(self.interest_rate) * Decimal(self.borrowed)) * Decimal((datetime.utcnow() - self.open_date).days)) or 0 # Interest/day * num of days
|
|
||||||
|
interest = ((Decimal(self.interest_rate) * Decimal(self.borrowed)) *
|
||||||
|
Decimal((datetime.utcnow() - self.open_date).days)) or 0 # Interest/day * num of days
|
||||||
if (self.is_short):
|
if (self.is_short):
|
||||||
return float(close_trade + fees + interest)
|
return float(close_trade + fees + interest)
|
||||||
else:
|
else:
|
||||||
@ -621,6 +623,9 @@ class LocalTrade():
|
|||||||
return 0.0
|
return 0.0
|
||||||
if self.is_short:
|
if self.is_short:
|
||||||
profit_ratio = (close_trade_value / self.open_trade_value) - 1
|
profit_ratio = (close_trade_value / self.open_trade_value) - 1
|
||||||
|
else:
|
||||||
|
if close_trade_value == 0:
|
||||||
|
profit_ratio = 0
|
||||||
else:
|
else:
|
||||||
profit_ratio = (self.open_trade_value / close_trade_value) - 1
|
profit_ratio = (self.open_trade_value / close_trade_value) - 1
|
||||||
return float(f"{profit_ratio:.8f}")
|
return float(f"{profit_ratio:.8f}")
|
||||||
@ -769,7 +774,7 @@ class Trade(_DECL_BASE, LocalTrade):
|
|||||||
# Lowest price reached
|
# Lowest price reached
|
||||||
min_rate = Column(Float, nullable=True)
|
min_rate = Column(Float, nullable=True)
|
||||||
sell_reason = Column(String(100), nullable=True) # TODO: Change to close_reason
|
sell_reason = Column(String(100), nullable=True) # TODO: Change to close_reason
|
||||||
close_order_status = Column(String(100), nullable=True)
|
sell_order_status = Column(String(100), nullable=True)
|
||||||
strategy = Column(String(100), nullable=True)
|
strategy = Column(String(100), nullable=True)
|
||||||
timeframe = Column(Integer, nullable=True)
|
timeframe = Column(Integer, nullable=True)
|
||||||
|
|
||||||
|
@ -221,6 +221,8 @@ def create_mock_trades(fee, use_db: bool = True):
|
|||||||
trade = mock_trade_6(fee)
|
trade = mock_trade_6(fee)
|
||||||
add_trade(trade)
|
add_trade(trade)
|
||||||
|
|
||||||
|
# TODO-mg: Add margin trades
|
||||||
|
|
||||||
if use_db:
|
if use_db:
|
||||||
Trade.query.session.flush()
|
Trade.query.session.flush()
|
||||||
|
|
||||||
@ -250,6 +252,7 @@ def patch_coingekko(mocker) -> None:
|
|||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def init_persistence(default_conf):
|
def init_persistence(default_conf):
|
||||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||||
|
# TODO-mg: margin with leverage and/or borrowed?
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
@ -914,8 +917,7 @@ def limit_sell_order_old():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def limit_buy_order_old_partial():
|
def limit_buy_order_old_partial():
|
||||||
return {
|
return {'id': 'mocked_limit_buy_old_partial',
|
||||||
'id': 'mocked_limit_buy_old_partial',
|
|
||||||
'type': 'limit',
|
'type': 'limit',
|
||||||
'side': 'buy',
|
'side': 'buy',
|
||||||
'symbol': 'ETH/BTC',
|
'symbol': 'ETH/BTC',
|
||||||
@ -1735,6 +1737,7 @@ def rpc_balance():
|
|||||||
'used': 0.0
|
'used': 0.0
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
# TODO-mg: Add shorts and leverage?
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -2049,3 +2052,95 @@ def saved_hyperopt_results():
|
|||||||
].total_seconds()
|
].total_seconds()
|
||||||
|
|
||||||
return hyperopt_res
|
return hyperopt_res
|
||||||
|
|
||||||
|
|
||||||
|
# * Margin Tests
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def leveraged_fee():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def short_fee():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def ticker_short():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def ticker_exit_short_up():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def ticker_exit_short_down():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def leveraged_markets():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def limit_short_order_open():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def limit_short_order(limit_short_order_open):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def market_short_order():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def market_short_exit_order():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def limit_short_order_old():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def limit_exit_short_order_old():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def limit_short_order_old_partial():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def limit_short_order_old_partial_canceled(limit_short_order_old_partial):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def limit_short_order_canceled_empty(request):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def limit_exit_short_order_open():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def limit_exit_short_order(limit_sell_order_open):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def short_order_fee():
|
||||||
|
return
|
||||||
|
@ -3,7 +3,7 @@ from datetime import datetime, timedelta, timezone
|
|||||||
from freqtrade.persistence.models import Order, Trade
|
from freqtrade.persistence.models import Order, Trade
|
||||||
|
|
||||||
|
|
||||||
MOCK_TRADE_COUNT = 6
|
MOCK_TRADE_COUNT = 6 # TODO-mg: Increase for short and leverage
|
||||||
|
|
||||||
|
|
||||||
def mock_order_1():
|
def mock_order_1():
|
||||||
@ -303,3 +303,5 @@ def mock_trade_6(fee):
|
|||||||
o = Order.parse_from_ccxt_object(mock_order_6_sell(), 'LTC/BTC', 'sell')
|
o = Order.parse_from_ccxt_object(mock_order_6_sell(), 'LTC/BTC', 'sell')
|
||||||
trade.orders.append(o)
|
trade.orders.append(o)
|
||||||
return trade
|
return trade
|
||||||
|
|
||||||
|
# TODO-mg: Mock orders for leveraged and short trades
|
||||||
|
@ -129,6 +129,9 @@ def test_update_with_binance(limit_buy_order, limit_sell_order, fee, caplog):
|
|||||||
r"pair=ETH/BTC, amount=90.99181073, open_rate=0.00001099, open_since=.*\).",
|
r"pair=ETH/BTC, amount=90.99181073, open_rate=0.00001099, open_since=.*\).",
|
||||||
caplog)
|
caplog)
|
||||||
|
|
||||||
|
# TODO-mg: create a short order
|
||||||
|
# TODO-mg: create a leveraged long order
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("init_persistence")
|
@pytest.mark.usefixtures("init_persistence")
|
||||||
def test_update_market_order(market_buy_order, market_sell_order, fee, caplog):
|
def test_update_market_order(market_buy_order, market_sell_order, fee, caplog):
|
||||||
@ -167,6 +170,9 @@ def test_update_market_order(market_buy_order, market_sell_order, fee, caplog):
|
|||||||
r"pair=ETH/BTC, amount=91.99181073, open_rate=0.00004099, open_since=.*\).",
|
r"pair=ETH/BTC, amount=91.99181073, open_rate=0.00004099, open_since=.*\).",
|
||||||
caplog)
|
caplog)
|
||||||
|
|
||||||
|
# TODO-mg: market short
|
||||||
|
# TODO-mg: market leveraged long
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("init_persistence")
|
@pytest.mark.usefixtures("init_persistence")
|
||||||
def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order, fee):
|
def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order, fee):
|
||||||
|
Loading…
Reference in New Issue
Block a user