Merge branch 'feat/short' into lev-exchange

This commit is contained in:
Sam Germain 2021-09-16 23:27:44 -06:00
commit ff5b402f58
3 changed files with 221 additions and 483 deletions

View File

@ -320,6 +320,7 @@ class LocalTrade():
if self.isolated_liq: if self.isolated_liq:
self.set_isolated_liq(self.isolated_liq) self.set_isolated_liq(self.isolated_liq)
self.recalc_open_trade_value() self.recalc_open_trade_value()
# TODO-lev: Throw exception if on margin and interest_rate is none
def _set_stop_loss(self, stop_loss: float, percent: float): def _set_stop_loss(self, stop_loss: float, percent: float):
""" """

View File

@ -6,6 +6,7 @@ from copy import deepcopy
from datetime import datetime, timedelta from datetime import datetime, timedelta
from functools import reduce from functools import reduce
from pathlib import Path from pathlib import Path
from typing import Tuple
from unittest.mock import MagicMock, Mock, PropertyMock from unittest.mock import MagicMock, Mock, PropertyMock
import arrow import arrow
@ -262,6 +263,10 @@ def create_mock_trades_with_leverage(fee, use_db: bool = True):
Trade.query.session.flush() Trade.query.session.flush()
def get_sides(is_short: bool) -> Tuple[str, str]:
return ("sell", "buy") if is_short else ("buy", "sell")
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def patch_coingekko(mocker) -> None: def patch_coingekko(mocker) -> None:
""" """

View File

@ -13,7 +13,8 @@ from sqlalchemy import create_engine, inspect, text
from freqtrade import constants from freqtrade import constants
from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exceptions import DependencyException, OperationalException
from freqtrade.persistence import LocalTrade, Order, Trade, clean_dry_run_db, init_db from freqtrade.persistence import LocalTrade, Order, Trade, clean_dry_run_db, init_db
from tests.conftest import create_mock_trades, create_mock_trades_with_leverage, log_has, log_has_re from tests.conftest import (create_mock_trades, create_mock_trades_with_leverage, get_sides,
log_has, log_has_re)
def test_init_create_session(default_conf): def test_init_create_session(default_conf):
@ -64,8 +65,10 @@ def test_init_dryrun_db(default_conf, tmpdir):
assert Path(filename).is_file() assert Path(filename).is_file()
@pytest.mark.parametrize('is_short', [False, True])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_enter_exit_side(fee): def test_enter_exit_side(fee, is_short):
enter_side, exit_side = get_sides(is_short)
trade = Trade( trade = Trade(
id=2, id=2,
pair='ADA/USDT', pair='ADA/USDT',
@ -77,16 +80,11 @@ def test_enter_exit_side(fee):
fee_open=fee.return_value, fee_open=fee.return_value,
fee_close=fee.return_value, fee_close=fee.return_value,
exchange='binance', exchange='binance',
is_short=False, is_short=is_short,
leverage=2.0 leverage=2.0
) )
assert trade.enter_side == 'buy' assert trade.enter_side == enter_side
assert trade.exit_side == 'sell' assert trade.exit_side == exit_side
trade.is_short = True
assert trade.enter_side == 'sell'
assert trade.exit_side == 'buy'
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
@ -170,8 +168,32 @@ def test_set_stop_loss_isolated_liq(fee):
assert trade.initial_stop_loss == 0.09 assert trade.initial_stop_loss == 0.09
@pytest.mark.parametrize('exchange,is_short,lev,minutes,rate,interest', [
("binance", False, 3, 10, 0.0005, round(0.0008333333333333334, 8)),
("binance", True, 3, 10, 0.0005, 0.000625),
("binance", False, 3, 295, 0.0005, round(0.004166666666666667, 8)),
("binance", True, 3, 295, 0.0005, round(0.0031249999999999997, 8)),
("binance", False, 3, 295, 0.00025, round(0.0020833333333333333, 8)),
("binance", True, 3, 295, 0.00025, round(0.0015624999999999999, 8)),
("binance", False, 5, 295, 0.0005, 0.005),
("binance", True, 5, 295, 0.0005, round(0.0031249999999999997, 8)),
("binance", False, 1, 295, 0.0005, 0.0),
("binance", True, 1, 295, 0.0005, 0.003125),
("kraken", False, 3, 10, 0.0005, 0.040),
("kraken", True, 3, 10, 0.0005, 0.030),
("kraken", False, 3, 295, 0.0005, 0.06),
("kraken", True, 3, 295, 0.0005, 0.045),
("kraken", False, 3, 295, 0.00025, 0.03),
("kraken", True, 3, 295, 0.00025, 0.0225),
("kraken", False, 5, 295, 0.0005, round(0.07200000000000001, 8)),
("kraken", True, 5, 295, 0.0005, 0.045),
("kraken", False, 1, 295, 0.0005, 0.0),
("kraken", True, 1, 295, 0.0005, 0.045),
])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_interest(market_buy_order_usdt, fee): def test_interest(market_buy_order_usdt, fee, exchange, is_short, lev, minutes, rate, interest):
""" """
10min, 5hr limit trade on Binance/Kraken at 3x,5x leverage 10min, 5hr limit trade on Binance/Kraken at 3x,5x leverage
fee: 0.25 % quote fee: 0.25 % quote
@ -230,114 +252,27 @@ def test_interest(market_buy_order_usdt, fee):
stake_amount=20.0, stake_amount=20.0,
amount=30.0, amount=30.0,
open_rate=2.0, open_rate=2.0,
open_date=datetime.utcnow() - timedelta(hours=0, minutes=10), open_date=datetime.utcnow() - timedelta(minutes=minutes),
fee_open=fee.return_value, fee_open=fee.return_value,
fee_close=fee.return_value, fee_close=fee.return_value,
exchange='binance', exchange=exchange,
leverage=3.0, leverage=lev,
interest_rate=0.0005, interest_rate=rate,
is_short=is_short
) )
# 10min, 3x leverage assert round(float(trade.calculate_interest()), 8) == interest
# binance
assert round(float(trade.calculate_interest()), 8) == round(0.0008333333333333334, 8)
# kraken
trade.exchange = "kraken"
assert float(trade.calculate_interest()) == 0.040
# Short
trade.is_short = True
trade.recalc_open_trade_value()
# binace
trade.exchange = "binance"
assert float(trade.calculate_interest()) == 0.000625
# kraken
trade.exchange = "kraken"
assert isclose(float(trade.calculate_interest()), 0.030)
# 5hr, long
trade.open_date = datetime.utcnow() - timedelta(hours=4, minutes=55)
trade.is_short = False
trade.recalc_open_trade_value()
# binance
trade.exchange = "binance"
assert round(float(trade.calculate_interest()), 8) == round(0.004166666666666667, 8)
# kraken
trade.exchange = "kraken"
assert float(trade.calculate_interest()) == 0.06
# short
trade.is_short = True
trade.recalc_open_trade_value()
# binace
trade.exchange = "binance"
assert round(float(trade.calculate_interest()), 8) == round(0.0031249999999999997, 8)
# kraken
trade.exchange = "kraken"
assert float(trade.calculate_interest()) == 0.045
# 0.00025 interest, 5hr, long
trade.is_short = False
trade.recalc_open_trade_value()
# binance
trade.exchange = "binance"
assert round(float(trade.calculate_interest(interest_rate=0.00025)),
8) == round(0.0020833333333333333, 8)
# kraken
trade.exchange = "kraken"
assert isclose(float(trade.calculate_interest(interest_rate=0.00025)), 0.03)
# short
trade.is_short = True
trade.recalc_open_trade_value()
# binace
trade.exchange = "binance"
assert round(float(trade.calculate_interest(interest_rate=0.00025)),
8) == round(0.0015624999999999999, 8)
# kraken
trade.exchange = "kraken"
assert float(trade.calculate_interest(interest_rate=0.00025)) == 0.0225
# 5x leverage, 0.0005 interest, 5hr, long
trade.is_short = False
trade.recalc_open_trade_value()
trade.leverage = 5.0
# binance
trade.exchange = "binance"
assert round(float(trade.calculate_interest()), 8) == 0.005
# kraken
trade.exchange = "kraken"
assert float(trade.calculate_interest()) == round(0.07200000000000001, 8)
# short
trade.is_short = True
trade.recalc_open_trade_value()
# binace
trade.exchange = "binance"
assert round(float(trade.calculate_interest()), 8) == round(0.0031249999999999997, 8)
# kraken
trade.exchange = "kraken"
assert float(trade.calculate_interest()) == 0.045
# 1x leverage, 0.0005 interest, 5hr
trade.is_short = False
trade.recalc_open_trade_value()
trade.leverage = 1.0
# binance
trade.exchange = "binance"
assert float(trade.calculate_interest()) == 0.0
# kraken
trade.exchange = "kraken"
assert float(trade.calculate_interest()) == 0.0
# short
trade.is_short = True
trade.recalc_open_trade_value()
# binace
trade.exchange = "binance"
assert float(trade.calculate_interest()) == 0.003125
# kraken
trade.exchange = "kraken"
assert float(trade.calculate_interest()) == 0.045
@pytest.mark.parametrize('is_short,lev,borrowed', [
(False, 1.0, 0.0),
(True, 1.0, 30.0),
(False, 3.0, 40.0),
(True, 3.0, 30.0),
])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_borrowed(limit_buy_order_usdt, limit_sell_order_usdt, fee, caplog): def test_borrowed(limit_buy_order_usdt, limit_sell_order_usdt, fee,
caplog, is_short, lev, borrowed):
""" """
10 minute limit trade on Binance/Kraken at 1x, 3x leverage 10 minute limit trade on Binance/Kraken at 1x, 3x leverage
fee: 0.25% quote fee: 0.25% quote
@ -411,20 +346,19 @@ def test_borrowed(limit_buy_order_usdt, limit_sell_order_usdt, fee, caplog):
fee_open=fee.return_value, fee_open=fee.return_value,
fee_close=fee.return_value, fee_close=fee.return_value,
exchange='binance', exchange='binance',
is_short=is_short,
leverage=lev
) )
assert trade.borrowed == 0 assert trade.borrowed == borrowed
trade.is_short = True
trade.recalc_open_trade_value()
assert trade.borrowed == 30.0
trade.leverage = 3.0
assert trade.borrowed == 30.0
trade.is_short = False
trade.recalc_open_trade_value()
assert trade.borrowed == 40.0
@pytest.mark.parametrize('is_short,open_rate,close_rate,lev,profit', [
(False, 2.0, 2.2, 1.0, round(0.0945137157107232, 8)),
(True, 2.2, 2.0, 3.0, round(0.2589996297562085, 8))
])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_update_limit_order(limit_buy_order_usdt, limit_sell_order_usdt, fee, caplog): def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_usdt,
is_short, open_rate, close_rate, lev, profit):
""" """
10 minute limit trade on Binance/Kraken at 1x, 3x leverage 10 minute limit trade on Binance/Kraken at 1x, 3x leverage
fee: 0.25% quote fee: 0.25% quote
@ -494,84 +428,52 @@ def test_update_limit_order(limit_buy_order_usdt, limit_sell_order_usdt, fee, ca
""" """
enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt
exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt
enter_side, exit_side = get_sides(is_short)
trade = Trade( trade = Trade(
id=2, id=2,
pair='ADA/USDT', pair='ADA/USDT',
stake_amount=60.0, stake_amount=60.0,
open_rate=2.0, open_rate=open_rate,
amount=30.0,
is_open=True,
open_date=arrow.utcnow().datetime,
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance'
)
assert trade.open_order_id is None
assert trade.close_profit is None
assert trade.close_date is None
trade.open_order_id = 'something'
trade.update(limit_buy_order_usdt)
assert trade.open_order_id is None
assert trade.open_rate == 2.00
assert trade.close_profit is None
assert trade.close_date is None
assert log_has_re(r"LIMIT_BUY has been fulfilled for Trade\(id=2, "
r'pair=ADA/USDT, amount=30.00000000, '
r"is_short=False, leverage=1.0, open_rate=2.00000000, open_since=.*\).",
caplog)
caplog.clear()
trade.open_order_id = 'something'
trade.update(limit_sell_order_usdt)
assert trade.open_order_id is None
assert trade.close_rate == 2.20
assert trade.close_profit == round(0.0945137157107232, 8)
assert trade.close_date is not None
assert log_has_re(r"LIMIT_SELL has been fulfilled for Trade\(id=2, "
r"pair=ADA/USDT, amount=30.00000000, "
r"is_short=False, leverage=1.0, open_rate=2.00000000, open_since=.*\).",
caplog)
caplog.clear()
trade = Trade(
id=226531,
pair='ADA/USDT',
stake_amount=20.0,
open_rate=2.0,
amount=30.0, amount=30.0,
is_open=True, is_open=True,
open_date=arrow.utcnow().datetime, open_date=arrow.utcnow().datetime,
fee_open=fee.return_value, fee_open=fee.return_value,
fee_close=fee.return_value, fee_close=fee.return_value,
exchange='binance', exchange='binance',
is_short=True, is_short=is_short,
leverage=3.0,
interest_rate=0.0005, interest_rate=0.0005,
leverage=lev
) )
trade.open_order_id = 'something'
trade.update(limit_sell_order_usdt)
assert trade.open_order_id is None assert trade.open_order_id is None
assert trade.open_rate == 2.20
assert trade.close_profit is None assert trade.close_profit is None
assert trade.close_date is None assert trade.close_date is None
assert log_has_re(r"LIMIT_SELL has been fulfilled for Trade\(id=226531, "
r"pair=ADA/USDT, amount=30.00000000, "
r"is_short=True, leverage=3.0, open_rate=2.20000000, open_since=.*\).",
caplog)
caplog.clear()
trade.open_order_id = 'something' trade.open_order_id = 'something'
trade.update(limit_buy_order_usdt) trade.update(enter_order)
assert trade.open_order_id is None assert trade.open_order_id is None
assert trade.close_rate == 2.00 assert trade.open_rate == open_rate
assert trade.close_profit == round(0.2589996297562085, 8) assert trade.close_profit is None
assert trade.close_date is None
assert log_has_re(f"LIMIT_{enter_side.upper()} has been fulfilled for "
r"Trade\(id=2, pair=ADA/USDT, amount=30.00000000, "
f"is_short={is_short}, leverage={lev}, open_rate={open_rate}0000000, "
r"open_since=.*\).",
caplog)
caplog.clear()
trade.open_order_id = 'something'
trade.update(exit_order)
assert trade.open_order_id is None
assert trade.close_rate == close_rate
assert trade.close_profit == profit
assert trade.close_date is not None assert trade.close_date is not None
assert log_has_re(r"LIMIT_BUY has been fulfilled for Trade\(id=226531, " assert log_has_re(f"LIMIT_{exit_side.upper()} has been fulfilled for "
r"pair=ADA/USDT, amount=30.00000000, " r"Trade\(id=2, pair=ADA/USDT, amount=30.00000000, "
r"is_short=True, leverage=3.0, open_rate=2.20000000, open_since=.*\).", f"is_short={is_short}, leverage={lev}, open_rate={open_rate}0000000, "
r"open_since=.*\).",
caplog) caplog)
caplog.clear() caplog.clear()
@ -616,9 +518,21 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee,
caplog) caplog)
@pytest.mark.parametrize('exchange,is_short,lev,open_value,close_value,profit,profit_ratio', [
("binance", False, 1, 60.15, 65.835, 5.685, 0.0945137157107232),
("binance", True, 1, 59.850, 66.1663784375, -6.316378437500013, -0.1055368159983292),
("binance", False, 3, 60.15, 65.83416667, 5.684166670000003, 0.2834995845386534),
("binance", True, 3, 59.85, 66.1663784375, -6.316378437500013, -0.3166104479949876),
("kraken", False, 1, 60.15, 65.835, 5.685, 0.0945137157107232),
("kraken", True, 1, 59.850, 66.231165, -6.381165, -0.106619298245614),
("kraken", False, 3, 60.15, 65.795, 5.645, 0.2815461346633419),
("kraken", True, 3, 59.850, 66.231165, -6.381165000000003, -0.319857894736842),
])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_calc_open_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt, fee): def test_calc_open_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt, fee, exchange,
trade = Trade( is_short, lev, open_value, close_value, profit, profit_ratio):
trade: Trade = Trade(
pair='ADA/USDT', pair='ADA/USDT',
stake_amount=60.0, stake_amount=60.0,
open_rate=2.0, open_rate=2.0,
@ -627,55 +541,22 @@ def test_calc_open_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt
interest_rate=0.0005, interest_rate=0.0005,
fee_open=fee.return_value, fee_open=fee.return_value,
fee_close=fee.return_value, fee_close=fee.return_value,
exchange='binance', exchange=exchange,
is_short=is_short,
leverage=lev
) )
trade.open_order_id = 'something' trade.open_order_id = f'something-{is_short}-{lev}-{exchange}'
trade.update(limit_buy_order_usdt) trade.update(limit_buy_order_usdt)
trade.update(limit_sell_order_usdt) trade.update(limit_sell_order_usdt)
# 1x leverage, binance trade.open_rate = 2.0
assert trade._calc_open_trade_value() == 60.15 trade.close_rate = 2.2
assert isclose(trade.calc_close_trade_value(), 65.835)
assert trade.calc_profit() == 5.685
assert trade.calc_profit_ratio() == round(0.0945137157107232, 8)
# 3x leverage, binance
trade.leverage = 3
trade.exchange = "binance"
assert trade._calc_open_trade_value() == 60.15
assert round(trade.calc_close_trade_value(), 8) == 65.83416667
assert trade.calc_profit() == round(5.684166670000003, 8)
assert trade.calc_profit_ratio() == round(0.2834995845386534, 8)
trade.exchange = "kraken"
# 3x leverage, kraken
assert trade._calc_open_trade_value() == 60.15
assert trade.calc_close_trade_value() == 65.795
assert trade.calc_profit() == 5.645
assert trade.calc_profit_ratio() == round(0.2815461346633419, 8)
trade.is_short = True
trade.recalc_open_trade_value() trade.recalc_open_trade_value()
# 3x leverage, short, kraken assert isclose(trade._calc_open_trade_value(), open_value)
assert trade._calc_open_trade_value() == 59.850 assert isclose(trade.calc_close_trade_value(), close_value)
assert trade.calc_close_trade_value() == 66.231165 assert isclose(trade.calc_profit(), round(profit, 8))
assert trade.calc_profit() == round(-6.381165000000003, 8) assert isclose(trade.calc_profit_ratio(), round(profit_ratio, 8))
assert trade.calc_profit_ratio() == round(-0.319857894736842, 8)
trade.exchange = "binance"
# 3x leverage, short, binance
assert trade._calc_open_trade_value() == 59.85
assert trade.calc_close_trade_value() == 66.1663784375
assert trade.calc_profit() == round(-6.316378437500013, 8)
assert trade.calc_profit_ratio() == round(-0.3166104479949876, 8)
# 1x leverage, short, binance
trade.leverage = 1.0
assert trade._calc_open_trade_value() == 59.850
assert trade.calc_close_trade_value() == 66.1663784375
assert trade.calc_profit() == round(-6.316378437500013, 8)
assert trade.calc_profit_ratio() == round(-0.1055368159983292, 8)
# 1x leverage, short, kraken
trade.exchange = "kraken"
assert trade._calc_open_trade_value() == 59.850
assert trade.calc_close_trade_value() == 66.231165
assert trade.calc_profit() == -6.381165
assert trade.calc_profit_ratio() == round(-0.106619298245614, 8)
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
@ -766,8 +647,27 @@ def test_update_invalid_order(limit_buy_order_usdt):
trade.update(limit_buy_order_usdt) trade.update(limit_buy_order_usdt)
@pytest.mark.parametrize('exchange', ['binance', 'kraken'])
@pytest.mark.parametrize('lev', [1, 3])
@pytest.mark.parametrize('is_short,fee_rate,result', [
(False, 0.003, 60.18),
(False, 0.0025, 60.15),
(False, 0.003, 60.18),
(False, 0.0025, 60.15),
(True, 0.003, 59.82),
(True, 0.0025, 59.85),
(True, 0.003, 59.82),
(True, 0.0025, 59.85)
])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_calc_open_trade_value(limit_buy_order_usdt, fee): def test_calc_open_trade_value(
limit_buy_order_usdt,
exchange,
lev,
is_short,
fee_rate,
result
):
# 10 minute limit trade on Binance/Kraken at 1x, 3x leverage # 10 minute limit trade on Binance/Kraken at 1x, 3x leverage
# fee: 0.25 %, 0.3% quote # fee: 0.25 %, 0.3% quote
# open_rate: 2.00 quote # open_rate: 2.00 quote
@ -787,90 +687,104 @@ def test_calc_open_trade_value(limit_buy_order_usdt, fee):
stake_amount=60.0, stake_amount=60.0,
amount=30.0, amount=30.0,
open_rate=2.0, open_rate=2.0,
fee_open=fee.return_value, open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=10),
fee_close=fee.return_value, fee_open=fee_rate,
exchange='binance', fee_close=fee_rate,
exchange=exchange,
leverage=lev,
is_short=is_short
) )
trade.open_order_id = 'open_trade' trade.open_order_id = 'open_trade'
trade.update(limit_buy_order_usdt)
# Get the open rate price with the standard fee rate # Get the open rate price with the standard fee rate
assert trade._calc_open_trade_value() == 60.15 assert trade._calc_open_trade_value() == result
trade.is_short = True
trade.recalc_open_trade_value()
assert trade._calc_open_trade_value() == 59.85
trade.leverage = 3
trade.exchange = "binance"
assert trade._calc_open_trade_value() == 59.85
trade.is_short = False
trade.recalc_open_trade_value()
assert trade._calc_open_trade_value() == 60.15
# Get the open rate price with a custom fee rate
trade.fee_open = 0.003
assert trade._calc_open_trade_value() == 60.18
trade.is_short = True
trade.recalc_open_trade_value()
assert trade._calc_open_trade_value() == 59.82
@pytest.mark.parametrize('exchange,is_short,lev,open_rate,close_rate,fee_rate,result', [
('binance', False, 1, 2.0, 2.5, 0.0025, 74.8125),
('binance', False, 1, 2.0, 2.5, 0.003, 74.775),
('binance', False, 1, 2.0, 2.2, 0.005, 65.67),
('binance', False, 3, 2.0, 2.5, 0.0025, 74.81166667),
('binance', False, 3, 2.0, 2.5, 0.003, 74.77416667),
('kraken', False, 3, 2.0, 2.5, 0.0025, 74.7725),
('kraken', False, 3, 2.0, 2.5, 0.003, 74.735),
('kraken', True, 3, 2.2, 2.5, 0.0025, 75.2626875),
('kraken', True, 3, 2.2, 2.5, 0.003, 75.300225),
('binance', True, 3, 2.2, 2.5, 0.0025, 75.18906641),
('binance', True, 3, 2.2, 2.5, 0.003, 75.22656719),
('binance', True, 1, 2.2, 2.5, 0.0025, 75.18906641),
('binance', True, 1, 2.2, 2.5, 0.003, 75.22656719),
('kraken', True, 1, 2.2, 2.5, 0.0025, 75.2626875),
('kraken', True, 1, 2.2, 2.5, 0.003, 75.300225),
])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_calc_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt, fee): def test_calc_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt, open_rate,
exchange, is_short, lev, close_rate, fee_rate, result):
trade = Trade( trade = Trade(
pair='ADA/USDT', pair='ADA/USDT',
stake_amount=60.0, stake_amount=60.0,
amount=30.0, amount=30.0,
open_rate=2.0, open_rate=open_rate,
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=10), open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=10),
fee_open=fee.return_value, fee_open=fee_rate,
fee_close=fee.return_value, fee_close=fee_rate,
exchange='binance', exchange=exchange,
interest_rate=0.0005, interest_rate=0.0005,
is_short=is_short,
leverage=lev
) )
trade.open_order_id = 'close_trade' trade.open_order_id = 'close_trade'
trade.update(limit_buy_order_usdt) assert round(trade.calc_close_trade_value(rate=close_rate, fee=fee_rate), 8) == result
# 1x leverage binance
assert trade.calc_close_trade_value(rate=2.5) == 74.8125
assert trade.calc_close_trade_value(rate=2.5, fee=0.003) == 74.775
trade.update(limit_sell_order_usdt)
assert trade.calc_close_trade_value(fee=0.005) == 65.67
# 3x leverage binance
trade.leverage = 3.0
assert round(trade.calc_close_trade_value(rate=2.5), 8) == 74.81166667
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 74.77416667
# 3x leverage kraken
trade.exchange = "kraken"
assert trade.calc_close_trade_value(rate=2.5) == 74.7725
assert trade.calc_close_trade_value(rate=2.5, fee=0.003) == 74.735
# 3x leverage kraken, short
trade.is_short = True
trade.recalc_open_trade_value()
assert round(trade.calc_close_trade_value(rate=2.5), 8) == 75.2626875
assert trade.calc_close_trade_value(rate=2.5, fee=0.003) == 75.300225
# 3x leverage binance, short
trade.exchange = "binance"
assert round(trade.calc_close_trade_value(rate=2.5), 8) == 75.18906641
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 75.22656719
trade.leverage = 1.0
# 1x leverage binance, short
assert round(trade.calc_close_trade_value(rate=2.5), 8) == 75.18906641
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 75.22656719
# 1x leverage kraken, short
trade.exchange = "kraken"
assert round(trade.calc_close_trade_value(rate=2.5), 8) == 75.2626875
assert trade.calc_close_trade_value(rate=2.5, fee=0.003) == 75.300225
@pytest.mark.parametrize('exchange,is_short,lev,close_rate,fee_close,profit,profit_ratio', [
('binance', False, 1, 2.1, 0.0025, 2.6925, 0.04476309226932673),
('binance', False, 3, 2.1, 0.0025, 2.69166667, 0.13424771421446402),
('binance', True, 1, 2.1, 0.0025, -3.308815781249997, -0.05528514254385963),
('binance', True, 3, 2.1, 0.0025, -3.308815781249997, -0.1658554276315789),
('binance', False, 1, 1.9, 0.0025, -3.2925, -0.05473815461346632),
('binance', False, 3, 1.9, 0.0025, -3.29333333, -0.16425602643391513),
('binance', True, 1, 1.9, 0.0025, 2.7063095312499996, 0.045218204365079395),
('binance', True, 3, 1.9, 0.0025, 2.7063095312499996, 0.13565461309523819),
('binance', False, 1, 2.2, 0.0025, 5.685, 0.0945137157107232),
('binance', False, 3, 2.2, 0.0025, 5.68416667, 0.2834995845386534),
('binance', True, 1, 2.2, 0.0025, -6.316378437499999, -0.1055368159983292),
('binance', True, 3, 2.2, 0.0025, -6.316378437499999, -0.3166104479949876),
('kraken', False, 1, 2.1, 0.0025, 2.6925, 0.04476309226932673),
('kraken', False, 3, 2.1, 0.0025, 2.6525, 0.13229426433915248),
('kraken', True, 1, 2.1, 0.0025, -3.3706575, -0.05631842105263152),
('kraken', True, 3, 2.1, 0.0025, -3.3706575, -0.16895526315789455),
('kraken', False, 1, 1.9, 0.0025, -3.2925, -0.05473815461346632),
('kraken', False, 3, 1.9, 0.0025, -3.3325, -0.16620947630922667),
('kraken', True, 1, 1.9, 0.0025, 2.6503575, 0.04428333333333334),
('kraken', True, 3, 1.9, 0.0025, 2.6503575, 0.13285000000000002),
('kraken', False, 1, 2.2, 0.0025, 5.685, 0.0945137157107232),
('kraken', False, 3, 2.2, 0.0025, 5.645, 0.2815461346633419),
('kraken', True, 1, 2.2, 0.0025, -6.381165, -0.106619298245614),
('kraken', True, 3, 2.2, 0.0025, -6.381165, -0.319857894736842),
('binance', False, 1, 2.1, 0.003, 2.6610000000000014, 0.04423940149625927),
('binance', False, 1, 1.9, 0.003, -3.320999999999998, -0.05521197007481293),
('binance', False, 1, 2.2, 0.003, 5.652000000000008, 0.09396508728179565),
])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_calc_profit(limit_buy_order_usdt, limit_sell_order_usdt, fee): def test_calc_profit(
limit_buy_order_usdt,
limit_sell_order_usdt,
fee,
exchange,
is_short,
lev,
close_rate,
fee_close,
profit,
profit_ratio
):
""" """
10 minute limit trade on Binance/Kraken at 1x, 3x leverage 10 minute limit trade on Binance/Kraken at 1x, 3x leverage
arguments: arguments:
@ -1007,198 +921,16 @@ def test_calc_profit(limit_buy_order_usdt, limit_sell_order_usdt, fee):
open_rate=2.0, open_rate=2.0,
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=10), open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=10),
interest_rate=0.0005, interest_rate=0.0005,
fee_open=fee.return_value, exchange=exchange,
fee_close=fee.return_value, is_short=is_short,
exchange='binance' leverage=lev,
fee_open=0.0025,
fee_close=fee_close
) )
trade.open_order_id = 'something' trade.open_order_id = 'something'
trade.update(limit_buy_order_usdt) # Buy @ 2.0
# 1x Leverage, long assert trade.calc_profit(rate=close_rate) == round(profit, 8)
# Custom closing rate and regular fee rate assert trade.calc_profit_ratio(rate=close_rate) == round(profit_ratio, 8)
# Higher than open rate - 2.1 quote
assert trade.calc_profit(rate=2.1) == 2.6925
# Lower than open rate - 1.9 quote
assert trade.calc_profit(rate=1.9) == round(-3.292499999999997, 8)
# fee 0.003
# Higher than open rate - 2.1 quote
assert trade.calc_profit(rate=2.1, fee=0.003) == 2.661
# Lower than open rate - 1.9 quote
assert trade.calc_profit(rate=1.9, fee=0.003) == round(-3.320999999999998, 8)
# Test when we apply a Sell order. Sell higher than open rate @ 2.2
trade.update(limit_sell_order_usdt)
assert trade.calc_profit() == round(5.684999999999995, 8)
# Test with a custom fee rate on the close trade
assert trade.calc_profit(fee=0.003) == round(5.652000000000008, 8)
trade.open_trade_value = 0.0
trade.open_trade_value = trade._calc_open_trade_value()
# 3x leverage, long ###################################################
trade.leverage = 3.0
# Higher than open rate - 2.1 quote
trade.exchange = "binance" # binance
assert trade.calc_profit(rate=2.1, fee=0.0025) == 2.69166667
trade.exchange = "kraken"
assert trade.calc_profit(rate=2.1, fee=0.0025) == 2.6525
# 1.9 quote
trade.exchange = "binance" # binance
assert trade.calc_profit(rate=1.9, fee=0.0025) == -3.29333333
trade.exchange = "kraken"
assert trade.calc_profit(rate=1.9, fee=0.0025) == -3.3325
# 2.2 quote
trade.exchange = "binance" # binance
assert trade.calc_profit(fee=0.0025) == 5.68416667
trade.exchange = "kraken"
assert trade.calc_profit(fee=0.0025) == 5.645
# 3x leverage, short ###################################################
trade.is_short = True
trade.recalc_open_trade_value()
# 2.1 quote - Higher than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit(rate=2.1, fee=0.0025) == round(-3.308815781249997, 8)
trade.exchange = "kraken"
assert trade.calc_profit(rate=2.1, fee=0.0025) == -3.3706575
# 1.9 quote - Lower than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit(rate=1.9, fee=0.0025) == round(2.7063095312499996, 8)
trade.exchange = "kraken"
assert trade.calc_profit(rate=1.9, fee=0.0025) == 2.6503575
# Test when we apply a Sell order. Uses sell order used above
trade.exchange = "binance" # binance
assert trade.calc_profit(fee=0.0025) == round(-6.316378437499999, 8)
trade.exchange = "kraken"
assert trade.calc_profit(fee=0.0025) == -6.381165
# 1x leverage, short ###################################################
trade.leverage = 1.0
# 2.1 quote - Higher than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit(rate=2.1, fee=0.0025) == round(-3.308815781249997, 8)
trade.exchange = "kraken"
assert trade.calc_profit(rate=2.1, fee=0.0025) == -3.3706575
# 1.9 quote - Lower than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit(rate=1.9, fee=0.0025) == round(2.7063095312499996, 8)
trade.exchange = "kraken"
assert trade.calc_profit(rate=1.9, fee=0.0025) == 2.6503575
# Test when we apply a Sell order. Uses sell order used above
trade.exchange = "binance" # binance
assert trade.calc_profit(fee=0.0025) == round(-6.316378437499999, 8)
trade.exchange = "kraken"
assert trade.calc_profit(fee=0.0025) == -6.381165
@pytest.mark.usefixtures("init_persistence")
def test_calc_profit_ratio(limit_buy_order_usdt, limit_sell_order_usdt, fee):
trade = Trade(
pair='ADA/USDT',
stake_amount=60.0,
amount=30.0,
open_rate=2.0,
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=10),
interest_rate=0.0005,
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance'
)
trade.open_order_id = 'something'
trade.update(limit_buy_order_usdt) # Buy @ 2.0
# 1x Leverage, long
# Custom closing rate and regular fee rate
# Higher than open rate - 2.1 quote
assert trade.calc_profit_ratio(rate=2.1) == round(0.04476309226932673, 8)
# Lower than open rate - 1.9 quote
assert trade.calc_profit_ratio(rate=1.9) == round(-0.05473815461346632, 8)
# fee 0.003
# Higher than open rate - 2.1 quote
assert trade.calc_profit_ratio(rate=2.1, fee=0.003) == round(0.04423940149625927, 8)
# Lower than open rate - 1.9 quote
assert trade.calc_profit_ratio(rate=1.9, fee=0.003) == round(-0.05521197007481293, 8)
# Test when we apply a Sell order. Sell higher than open rate @ 2.2
trade.update(limit_sell_order_usdt)
assert trade.calc_profit_ratio() == round(0.0945137157107232, 8)
# Test with a custom fee rate on the close trade
assert trade.calc_profit_ratio(fee=0.003) == round(0.09396508728179565, 8)
trade.open_trade_value = 0.0
assert trade.calc_profit_ratio(fee=0.003) == 0.0
trade.open_trade_value = trade._calc_open_trade_value()
# 3x leverage, long ###################################################
trade.leverage = 3.0
# 2.1 quote - Higher than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit_ratio(rate=2.1) == round(0.13424771421446402, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio(rate=2.1) == round(0.13229426433915248, 8)
# 1.9 quote - Lower than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit_ratio(rate=1.9) == round(-0.16425602643391513, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio(rate=1.9) == round(-0.16620947630922667, 8)
# Test when we apply a Sell order. Uses sell order used above
trade.exchange = "binance" # binance
assert trade.calc_profit_ratio() == round(0.2834995845386534, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio() == round(0.2815461346633419, 8)
# 3x leverage, short ###################################################
trade.is_short = True
trade.recalc_open_trade_value()
# 2.1 quote - Higher than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit_ratio(rate=2.1) == round(-0.1658554276315789, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio(rate=2.1) == round(-0.16895526315789455, 8)
# 1.9 quote - Lower than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit_ratio(rate=1.9) == round(0.13565461309523819, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio(rate=1.9) == round(0.13285000000000002, 8)
# Test when we apply a Sell order. Uses sell order used above
trade.exchange = "binance" # binance
assert trade.calc_profit_ratio() == round(-0.3166104479949876, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio() == round(-0.319857894736842, 8)
# 1x leverage, short ###################################################
trade.leverage = 1.0
# 2.1 quote - Higher than open rate
trade.exchange = "binance" # binance
assert trade.calc_profit_ratio(rate=2.1) == round(-0.05528514254385963, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio(rate=2.1) == round(-0.05631842105263152, 8)
# 1.9 quote - Lower than open rate
trade.exchange = "binance"
assert trade.calc_profit_ratio(rate=1.9) == round(0.045218204365079395, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio(rate=1.9) == round(0.04428333333333334, 8)
# Test when we apply a Sell order. Uses sell order used above
trade.exchange = "binance"
assert trade.calc_profit_ratio() == round(-0.1055368159983292, 8)
trade.exchange = "kraken"
assert trade.calc_profit_ratio() == round(-0.106619298245614, 8)
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")