merge with feat/short interest changes
This commit is contained in:
commit
8b87620cbc
@ -1,7 +1,6 @@
|
|||||||
# flake8: noqa: F401
|
# flake8: noqa: F401
|
||||||
from freqtrade.enums.backteststate import BacktestState
|
from freqtrade.enums.backteststate import BacktestState
|
||||||
from freqtrade.enums.collateral import Collateral
|
from freqtrade.enums.collateral import Collateral
|
||||||
from freqtrade.enums.interestmode import InterestMode
|
|
||||||
from freqtrade.enums.rpcmessagetype import RPCMessageType
|
from freqtrade.enums.rpcmessagetype import RPCMessageType
|
||||||
from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode
|
from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode
|
||||||
from freqtrade.enums.selltype import SellType
|
from freqtrade.enums.selltype import SellType
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
from decimal import Decimal
|
|
||||||
from enum import Enum
|
|
||||||
from math import ceil
|
|
||||||
|
|
||||||
from freqtrade.exceptions import OperationalException
|
|
||||||
|
|
||||||
|
|
||||||
one = Decimal(1.0)
|
|
||||||
four = Decimal(4.0)
|
|
||||||
twenty_four = Decimal(24.0)
|
|
||||||
|
|
||||||
|
|
||||||
class InterestMode(Enum):
|
|
||||||
"""Equations to calculate interest"""
|
|
||||||
|
|
||||||
HOURSPERDAY = "HOURSPERDAY"
|
|
||||||
HOURSPER4 = "HOURSPER4" # Hours per 4 hour segment
|
|
||||||
NONE = "NONE"
|
|
||||||
|
|
||||||
def __call__(self, borrowed: Decimal, rate: Decimal, hours: Decimal):
|
|
||||||
|
|
||||||
if self.name == "HOURSPERDAY":
|
|
||||||
return borrowed * rate * ceil(hours)/twenty_four
|
|
||||||
elif self.name == "HOURSPER4":
|
|
||||||
# Rounded based on https://kraken-fees-calculator.github.io/
|
|
||||||
return borrowed * rate * (1+ceil(hours/four))
|
|
||||||
else:
|
|
||||||
raise OperationalException("Leverage not available on this exchange with freqtrade")
|
|
@ -1,2 +1,3 @@
|
|||||||
# flake8: noqa: F401
|
# flake8: noqa: F401
|
||||||
|
from freqtrade.leverage.interest import interest
|
||||||
from freqtrade.leverage.liquidation_price import liquidation_price
|
from freqtrade.leverage.liquidation_price import liquidation_price
|
||||||
|
42
freqtrade/leverage/interest.py
Normal file
42
freqtrade/leverage/interest.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
from decimal import Decimal
|
||||||
|
from math import ceil
|
||||||
|
|
||||||
|
from freqtrade.exceptions import OperationalException
|
||||||
|
|
||||||
|
|
||||||
|
one = Decimal(1.0)
|
||||||
|
four = Decimal(4.0)
|
||||||
|
twenty_four = Decimal(24.0)
|
||||||
|
|
||||||
|
|
||||||
|
def interest(
|
||||||
|
exchange_name: str,
|
||||||
|
borrowed: Decimal,
|
||||||
|
rate: Decimal,
|
||||||
|
hours: Decimal
|
||||||
|
) -> Decimal:
|
||||||
|
"""
|
||||||
|
Equation to calculate interest on margin trades
|
||||||
|
|
||||||
|
:param exchange_name: The exchanged being trading on
|
||||||
|
:param borrowed: The amount of currency being borrowed
|
||||||
|
:param rate: The rate of interest
|
||||||
|
:param hours: The time in hours that the currency has been borrowed for
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OperationalException: Raised if freqtrade does
|
||||||
|
not support margin trading for this exchange
|
||||||
|
|
||||||
|
Returns: The amount of interest owed (currency matches borrowed)
|
||||||
|
"""
|
||||||
|
exchange_name = exchange_name.lower()
|
||||||
|
if exchange_name == "binance":
|
||||||
|
return borrowed * rate * ceil(hours)/twenty_four
|
||||||
|
elif exchange_name == "kraken":
|
||||||
|
# Rounded based on https://kraken-fees-calculator.github.io/
|
||||||
|
return borrowed * rate * (one+ceil(hours/four))
|
||||||
|
elif exchange_name == "ftx":
|
||||||
|
# TODO-lev: Add FTX interest formula
|
||||||
|
raise OperationalException(f"Leverage not available on {exchange_name} with freqtrade")
|
||||||
|
else:
|
||||||
|
raise OperationalException(f"Leverage not available on {exchange_name} with freqtrade")
|
@ -54,7 +54,6 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
|||||||
isolated_liq = get_column_def(cols, 'isolated_liq', 'null')
|
isolated_liq = get_column_def(cols, 'isolated_liq', 'null')
|
||||||
# sqlite does not support literals for booleans
|
# sqlite does not support literals for booleans
|
||||||
is_short = get_column_def(cols, 'is_short', '0')
|
is_short = get_column_def(cols, 'is_short', '0')
|
||||||
interest_mode = get_column_def(cols, 'interest_mode', 'null')
|
|
||||||
# If ticker-interval existed use that, else null.
|
# If ticker-interval existed use that, else null.
|
||||||
if has_column(cols, 'ticker_interval'):
|
if has_column(cols, 'ticker_interval'):
|
||||||
timeframe = get_column_def(cols, 'timeframe', 'ticker_interval')
|
timeframe = get_column_def(cols, 'timeframe', 'ticker_interval')
|
||||||
@ -66,7 +65,7 @@ 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}")
|
||||||
# TODO-mg: update to exit order status
|
# TODO-lev: update to exit order status
|
||||||
sell_order_status = get_column_def(cols, 'sell_order_status', 'null')
|
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')
|
||||||
|
|
||||||
@ -92,7 +91,7 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
|||||||
stoploss_order_id, stoploss_last_update,
|
stoploss_order_id, stoploss_last_update,
|
||||||
max_rate, min_rate, sell_reason, sell_order_status, strategy, buy_tag,
|
max_rate, min_rate, sell_reason, sell_order_status, strategy, buy_tag,
|
||||||
timeframe, open_trade_value, close_profit_abs,
|
timeframe, open_trade_value, close_profit_abs,
|
||||||
leverage, interest_rate, isolated_liq, is_short, interest_mode
|
leverage, interest_rate, isolated_liq, is_short
|
||||||
)
|
)
|
||||||
select id, lower(exchange), pair,
|
select id, lower(exchange), pair,
|
||||||
is_open, {fee_open} fee_open, {fee_open_cost} fee_open_cost,
|
is_open, {fee_open} fee_open, {fee_open_cost} fee_open_cost,
|
||||||
@ -110,8 +109,7 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
|||||||
{strategy} strategy, {buy_tag} buy_tag, {timeframe} timeframe,
|
{strategy} strategy, {buy_tag} buy_tag, {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, {interest_rate} interest_rate,
|
{leverage} leverage, {interest_rate} interest_rate,
|
||||||
{isolated_liq} isolated_liq, {is_short} is_short,
|
{isolated_liq} isolated_liq, {is_short} is_short
|
||||||
{interest_mode} interest_mode
|
|
||||||
from {table_back_name}
|
from {table_back_name}
|
||||||
"""))
|
"""))
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from datetime import datetime, timezone
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from sqlalchemy import (Boolean, Column, DateTime, Enum, Float, ForeignKey, Integer, String,
|
from sqlalchemy import (Boolean, Column, DateTime, Float, ForeignKey, Integer, String,
|
||||||
create_engine, desc, func, inspect)
|
create_engine, desc, func, inspect)
|
||||||
from sqlalchemy.exc import NoSuchModuleError
|
from sqlalchemy.exc import NoSuchModuleError
|
||||||
from sqlalchemy.orm import Query, declarative_base, relationship, scoped_session, sessionmaker
|
from sqlalchemy.orm import Query, declarative_base, relationship, scoped_session, sessionmaker
|
||||||
@ -14,9 +14,9 @@ from sqlalchemy.pool import StaticPool
|
|||||||
from sqlalchemy.sql.schema import UniqueConstraint
|
from sqlalchemy.sql.schema import UniqueConstraint
|
||||||
|
|
||||||
from freqtrade.constants import DATETIME_PRINT_FORMAT
|
from freqtrade.constants import DATETIME_PRINT_FORMAT
|
||||||
from freqtrade.enums import InterestMode, SellType
|
from freqtrade.enums import SellType
|
||||||
from freqtrade.exceptions import DependencyException, OperationalException
|
from freqtrade.exceptions import DependencyException, OperationalException
|
||||||
from freqtrade.leverage import liquidation_price
|
from freqtrade.leverage import interest, liquidation_price
|
||||||
from freqtrade.misc import safe_value_fallback
|
from freqtrade.misc import safe_value_fallback
|
||||||
from freqtrade.persistence.migrations import check_migrate
|
from freqtrade.persistence.migrations import check_migrate
|
||||||
|
|
||||||
@ -265,12 +265,13 @@ class LocalTrade():
|
|||||||
buy_tag: Optional[str] = None
|
buy_tag: Optional[str] = None
|
||||||
timeframe: Optional[int] = None
|
timeframe: Optional[int] = None
|
||||||
|
|
||||||
|
# Leverage trading properties
|
||||||
|
is_short: bool = False
|
||||||
|
isolated_liq: Optional[float] = None
|
||||||
|
leverage: float = 1.0
|
||||||
|
|
||||||
# Margin trading properties
|
# Margin trading properties
|
||||||
interest_rate: float = 0.0
|
interest_rate: float = 0.0
|
||||||
isolated_liq: Optional[float] = None
|
|
||||||
is_short: bool = False
|
|
||||||
leverage: float = 1.0
|
|
||||||
interest_mode: InterestMode = InterestMode.NONE
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_no_leverage(self) -> bool:
|
def has_no_leverage(self) -> bool:
|
||||||
@ -480,12 +481,12 @@ class LocalTrade():
|
|||||||
|
|
||||||
if self.is_short:
|
if self.is_short:
|
||||||
new_loss = float(current_price * (1 + abs(stoploss)))
|
new_loss = float(current_price * (1 + abs(stoploss)))
|
||||||
# If trading on margin, don't set the stoploss below the liquidation price
|
# If trading with leverage, don't set the stoploss below the liquidation price
|
||||||
if self.isolated_liq:
|
if self.isolated_liq:
|
||||||
new_loss = min(self.isolated_liq, new_loss)
|
new_loss = min(self.isolated_liq, new_loss)
|
||||||
else:
|
else:
|
||||||
new_loss = float(current_price * (1 - abs(stoploss)))
|
new_loss = float(current_price * (1 - abs(stoploss)))
|
||||||
# If trading on margin, don't set the stoploss below the liquidation price
|
# If trading with leverage, don't set the stoploss below the liquidation price
|
||||||
if self.isolated_liq:
|
if self.isolated_liq:
|
||||||
new_loss = max(self.isolated_liq, new_loss)
|
new_loss = max(self.isolated_liq, new_loss)
|
||||||
|
|
||||||
@ -506,7 +507,8 @@ class LocalTrade():
|
|||||||
lower_stop = new_loss < self.stop_loss
|
lower_stop = new_loss < self.stop_loss
|
||||||
|
|
||||||
# stop losses only walk up, never down!,
|
# stop losses only walk up, never down!,
|
||||||
# ? But adding more to a margin account would create a lower liquidation price,
|
# TODO-lev
|
||||||
|
# ? But adding more to a leveraged trade would create a lower liquidation price,
|
||||||
# ? decreasing the minimum stoploss
|
# ? decreasing the minimum stoploss
|
||||||
if (higher_stop and not self.is_short) or (lower_stop and self.is_short):
|
if (higher_stop and not self.is_short) or (lower_stop and self.is_short):
|
||||||
logger.debug(f"{self.pair} - Adjusting stoploss...")
|
logger.debug(f"{self.pair} - Adjusting stoploss...")
|
||||||
@ -554,10 +556,11 @@ class LocalTrade():
|
|||||||
elif order_type in ('market', 'limit') and self.exit_side == order['side']:
|
elif order_type in ('market', 'limit') and self.exit_side == order['side']:
|
||||||
if self.is_open:
|
if self.is_open:
|
||||||
payment = "BUY" if self.is_short else "SELL"
|
payment = "BUY" if self.is_short else "SELL"
|
||||||
# TODO-mg: On shorts, you buy a little bit more than the amount (amount + interest)
|
# TODO-lev: On shorts, you buy a little bit more than the amount (amount + interest)
|
||||||
# This wll only print the original amount
|
# This wll only print the original amount
|
||||||
logger.info(f'{order_type.upper()}_{payment} has been fulfilled for {self}.')
|
logger.info(f'{order_type.upper()}_{payment} has been fulfilled for {self}.')
|
||||||
self.close(safe_value_fallback(order, 'average', 'price')) # TODO-mg: Double check this
|
# TODO-lev: Double check this
|
||||||
|
self.close(safe_value_fallback(order, 'average', 'price'))
|
||||||
elif order_type in ('stop_loss_limit', 'stop-loss', 'stop-loss-limit', 'stop'):
|
elif order_type in ('stop_loss_limit', 'stop-loss', 'stop-loss-limit', 'stop'):
|
||||||
self.stoploss_order_id = None
|
self.stoploss_order_id = None
|
||||||
self.close_rate_requested = self.stop_loss
|
self.close_rate_requested = self.stop_loss
|
||||||
@ -659,7 +662,7 @@ class LocalTrade():
|
|||||||
rate = Decimal(interest_rate or self.interest_rate)
|
rate = Decimal(interest_rate or self.interest_rate)
|
||||||
borrowed = Decimal(self.borrowed)
|
borrowed = Decimal(self.borrowed)
|
||||||
|
|
||||||
return self.interest_mode(borrowed=borrowed, rate=rate, hours=hours)
|
return interest(exchange_name=self.exchange, borrowed=borrowed, rate=rate, hours=hours)
|
||||||
|
|
||||||
def calc_close_trade_value(self, rate: Optional[float] = None,
|
def calc_close_trade_value(self, rate: Optional[float] = None,
|
||||||
fee: Optional[float] = None,
|
fee: Optional[float] = None,
|
||||||
@ -892,19 +895,19 @@ class Trade(_DECL_BASE, LocalTrade):
|
|||||||
max_rate = Column(Float, nullable=True, default=0.0)
|
max_rate = Column(Float, nullable=True, default=0.0)
|
||||||
# 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-mg: Change to close_reason
|
sell_reason = Column(String(100), nullable=True) # TODO-lev: Change to close_reason
|
||||||
sell_order_status = Column(String(100), nullable=True) # TODO-mg: Change to close_order_status
|
sell_order_status = Column(String(100), nullable=True) # TODO-lev: Change to close_order_status
|
||||||
strategy = Column(String(100), nullable=True)
|
strategy = Column(String(100), nullable=True)
|
||||||
buy_tag = Column(String(100), nullable=True)
|
buy_tag = Column(String(100), nullable=True)
|
||||||
timeframe = Column(Integer, nullable=True)
|
timeframe = Column(Integer, nullable=True)
|
||||||
|
|
||||||
# Margin trading properties
|
# Leverage trading properties
|
||||||
leverage = Column(Float, nullable=True, default=1.0)
|
leverage = Column(Float, nullable=True, default=1.0)
|
||||||
interest_rate = Column(Float, nullable=False, default=0.0)
|
|
||||||
isolated_liq = Column(Float, nullable=True)
|
|
||||||
is_short = Column(Boolean, nullable=False, default=False)
|
is_short = Column(Boolean, nullable=False, default=False)
|
||||||
interest_mode = Column(Enum(InterestMode), nullable=True)
|
isolated_liq = Column(Float, nullable=True)
|
||||||
# End of margin trading properties
|
|
||||||
|
# Margin Trading Properties
|
||||||
|
interest_rate = Column(Float, nullable=False, default=0.0)
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
|
|
||||||
from freqtrade.enums import InterestMode
|
|
||||||
from freqtrade.persistence.models import Order, Trade
|
from freqtrade.persistence.models import Order, Trade
|
||||||
|
|
||||||
|
|
||||||
@ -380,11 +379,10 @@ def short_trade(fee):
|
|||||||
open_order_id='dry_run_exit_short_12345',
|
open_order_id='dry_run_exit_short_12345',
|
||||||
strategy='DefaultStrategy',
|
strategy='DefaultStrategy',
|
||||||
timeframe=5,
|
timeframe=5,
|
||||||
sell_reason='sell_signal', # TODO-mg: Update to exit/close reason
|
sell_reason='sell_signal', # TODO-lev: Update to exit/close reason
|
||||||
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
|
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
|
||||||
# close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2),
|
# close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2),
|
||||||
is_short=True,
|
is_short=True
|
||||||
interest_mode=InterestMode.HOURSPERDAY
|
|
||||||
)
|
)
|
||||||
o = Order.parse_from_ccxt_object(short_order(), 'ETC/BTC', 'sell')
|
o = Order.parse_from_ccxt_object(short_order(), 'ETC/BTC', 'sell')
|
||||||
trade.orders.append(o)
|
trade.orders.append(o)
|
||||||
@ -470,11 +468,10 @@ def leverage_trade(fee):
|
|||||||
open_order_id='dry_run_leverage_buy_12368',
|
open_order_id='dry_run_leverage_buy_12368',
|
||||||
strategy='DefaultStrategy',
|
strategy='DefaultStrategy',
|
||||||
timeframe=5,
|
timeframe=5,
|
||||||
sell_reason='sell_signal', # TODO-mg: Update to exit/close reason
|
sell_reason='sell_signal', # TODO-lev: Update to exit/close reason
|
||||||
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=300),
|
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=300),
|
||||||
close_date=datetime.now(tz=timezone.utc),
|
close_date=datetime.now(tz=timezone.utc),
|
||||||
interest_rate=0.0005,
|
interest_rate=0.0005
|
||||||
interest_mode=InterestMode.HOURSPER4
|
|
||||||
)
|
)
|
||||||
o = Order.parse_from_ccxt_object(leverage_order(), 'DOGE/BTC', 'sell')
|
o = Order.parse_from_ccxt_object(leverage_order(), 'DOGE/BTC', 'sell')
|
||||||
trade.orders.append(o)
|
trade.orders.append(o)
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
# from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from math import isclose
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from freqtrade.enums import Collateral, TradingMode
|
from freqtrade.enums import Collateral, TradingMode
|
||||||
from freqtrade.leverage import liquidation_price
|
from freqtrade.leverage import interest, liquidation_price
|
||||||
|
|
||||||
|
|
||||||
# from freqtrade.exceptions import OperationalException
|
# from freqtrade.exceptions import OperationalException
|
||||||
@ -87,3 +90,34 @@ def test_liquidation_price():
|
|||||||
|
|
||||||
# liquidation_price(ftx, trading_mode=futures, collateral=isolated)
|
# liquidation_price(ftx, trading_mode=futures, collateral=isolated)
|
||||||
# assert exception thrown #TODO-lev: Check that exception is thrown
|
# assert exception thrown #TODO-lev: Check that exception is thrown
|
||||||
|
|
||||||
|
|
||||||
|
ten_mins = Decimal(1/6)
|
||||||
|
five_hours = Decimal(5.0)
|
||||||
|
twentyfive_hours = Decimal(25.0)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('exchange,interest_rate,hours,expected', [
|
||||||
|
('binance', 0.0005, ten_mins, 0.00125),
|
||||||
|
('binance', 0.00025, ten_mins, 0.000625),
|
||||||
|
('binance', 0.00025, five_hours, 0.003125),
|
||||||
|
('binance', 0.00025, twentyfive_hours, 0.015625),
|
||||||
|
# Kraken
|
||||||
|
('kraken', 0.0005, ten_mins, 0.06),
|
||||||
|
('kraken', 0.00025, ten_mins, 0.03),
|
||||||
|
('kraken', 0.00025, five_hours, 0.045),
|
||||||
|
('kraken', 0.00025, twentyfive_hours, 0.12),
|
||||||
|
# FTX
|
||||||
|
# TODO-lev: - implement FTX tests
|
||||||
|
# ('ftx', Decimal(0.0005), ten_mins, 0.06),
|
||||||
|
# ('ftx', Decimal(0.0005), five_hours, 0.045),
|
||||||
|
])
|
||||||
|
def test_interest(exchange, interest_rate, hours, expected):
|
||||||
|
borrowed = Decimal(60.0)
|
||||||
|
|
||||||
|
assert isclose(interest(
|
||||||
|
exchange_name=exchange,
|
||||||
|
borrowed=borrowed,
|
||||||
|
rate=Decimal(interest_rate),
|
||||||
|
hours=hours
|
||||||
|
), expected)
|
||||||
|
@ -11,7 +11,6 @@ import pytest
|
|||||||
from sqlalchemy import create_engine, inspect, text
|
from sqlalchemy import create_engine, inspect, text
|
||||||
|
|
||||||
from freqtrade import constants
|
from freqtrade import constants
|
||||||
from freqtrade.enums import InterestMode
|
|
||||||
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, log_has, log_has_re
|
||||||
@ -237,23 +236,22 @@ def test_interest(market_buy_order_usdt, fee):
|
|||||||
exchange='binance',
|
exchange='binance',
|
||||||
leverage=3.0,
|
leverage=3.0,
|
||||||
interest_rate=0.0005,
|
interest_rate=0.0005,
|
||||||
interest_mode=InterestMode.HOURSPERDAY
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 10min, 3x leverage
|
# 10min, 3x leverage
|
||||||
# binance
|
# binance
|
||||||
assert round(float(trade.calculate_interest()), 8) == round(0.0008333333333333334, 8)
|
assert round(float(trade.calculate_interest()), 8) == round(0.0008333333333333334, 8)
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert float(trade.calculate_interest()) == 0.040
|
assert float(trade.calculate_interest()) == 0.040
|
||||||
# Short
|
# Short
|
||||||
trade.is_short = True
|
trade.is_short = True
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# binace
|
# binace
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert float(trade.calculate_interest()) == 0.000625
|
assert float(trade.calculate_interest()) == 0.000625
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert isclose(float(trade.calculate_interest()), 0.030)
|
assert isclose(float(trade.calculate_interest()), 0.030)
|
||||||
|
|
||||||
# 5hr, long
|
# 5hr, long
|
||||||
@ -261,40 +259,40 @@ def test_interest(market_buy_order_usdt, fee):
|
|||||||
trade.is_short = False
|
trade.is_short = False
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# binance
|
# binance
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert round(float(trade.calculate_interest()), 8) == round(0.004166666666666667, 8)
|
assert round(float(trade.calculate_interest()), 8) == round(0.004166666666666667, 8)
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert float(trade.calculate_interest()) == 0.06
|
assert float(trade.calculate_interest()) == 0.06
|
||||||
# short
|
# short
|
||||||
trade.is_short = True
|
trade.is_short = True
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# binace
|
# binace
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert round(float(trade.calculate_interest()), 8) == round(0.0031249999999999997, 8)
|
assert round(float(trade.calculate_interest()), 8) == round(0.0031249999999999997, 8)
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert float(trade.calculate_interest()) == 0.045
|
assert float(trade.calculate_interest()) == 0.045
|
||||||
|
|
||||||
# 0.00025 interest, 5hr, long
|
# 0.00025 interest, 5hr, long
|
||||||
trade.is_short = False
|
trade.is_short = False
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# binance
|
# binance
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert round(float(trade.calculate_interest(interest_rate=0.00025)),
|
assert round(float(trade.calculate_interest(interest_rate=0.00025)),
|
||||||
8) == round(0.0020833333333333333, 8)
|
8) == round(0.0020833333333333333, 8)
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert isclose(float(trade.calculate_interest(interest_rate=0.00025)), 0.03)
|
assert isclose(float(trade.calculate_interest(interest_rate=0.00025)), 0.03)
|
||||||
# short
|
# short
|
||||||
trade.is_short = True
|
trade.is_short = True
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# binace
|
# binace
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert round(float(trade.calculate_interest(interest_rate=0.00025)),
|
assert round(float(trade.calculate_interest(interest_rate=0.00025)),
|
||||||
8) == round(0.0015624999999999999, 8)
|
8) == round(0.0015624999999999999, 8)
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert float(trade.calculate_interest(interest_rate=0.00025)) == 0.0225
|
assert float(trade.calculate_interest(interest_rate=0.00025)) == 0.0225
|
||||||
|
|
||||||
# 5x leverage, 0.0005 interest, 5hr, long
|
# 5x leverage, 0.0005 interest, 5hr, long
|
||||||
@ -302,19 +300,19 @@ def test_interest(market_buy_order_usdt, fee):
|
|||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
trade.leverage = 5.0
|
trade.leverage = 5.0
|
||||||
# binance
|
# binance
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert round(float(trade.calculate_interest()), 8) == 0.005
|
assert round(float(trade.calculate_interest()), 8) == 0.005
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert float(trade.calculate_interest()) == round(0.07200000000000001, 8)
|
assert float(trade.calculate_interest()) == round(0.07200000000000001, 8)
|
||||||
# short
|
# short
|
||||||
trade.is_short = True
|
trade.is_short = True
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# binace
|
# binace
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert round(float(trade.calculate_interest()), 8) == round(0.0031249999999999997, 8)
|
assert round(float(trade.calculate_interest()), 8) == round(0.0031249999999999997, 8)
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert float(trade.calculate_interest()) == 0.045
|
assert float(trade.calculate_interest()) == 0.045
|
||||||
|
|
||||||
# 1x leverage, 0.0005 interest, 5hr
|
# 1x leverage, 0.0005 interest, 5hr
|
||||||
@ -322,19 +320,19 @@ def test_interest(market_buy_order_usdt, fee):
|
|||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
trade.leverage = 1.0
|
trade.leverage = 1.0
|
||||||
# binance
|
# binance
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert float(trade.calculate_interest()) == 0.0
|
assert float(trade.calculate_interest()) == 0.0
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert float(trade.calculate_interest()) == 0.0
|
assert float(trade.calculate_interest()) == 0.0
|
||||||
# short
|
# short
|
||||||
trade.is_short = True
|
trade.is_short = True
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# binace
|
# binace
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert float(trade.calculate_interest()) == 0.003125
|
assert float(trade.calculate_interest()) == 0.003125
|
||||||
# kraken
|
# kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert float(trade.calculate_interest()) == 0.045
|
assert float(trade.calculate_interest()) == 0.045
|
||||||
|
|
||||||
|
|
||||||
@ -550,7 +548,6 @@ def test_update_limit_order(limit_buy_order_usdt, limit_sell_order_usdt, fee, ca
|
|||||||
is_short=True,
|
is_short=True,
|
||||||
leverage=3.0,
|
leverage=3.0,
|
||||||
interest_rate=0.0005,
|
interest_rate=0.0005,
|
||||||
interest_mode=InterestMode.HOURSPERDAY
|
|
||||||
)
|
)
|
||||||
trade.open_order_id = 'something'
|
trade.open_order_id = 'something'
|
||||||
trade.update(limit_sell_order_usdt)
|
trade.update(limit_sell_order_usdt)
|
||||||
@ -628,7 +625,6 @@ def test_calc_open_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt
|
|||||||
amount=30.0,
|
amount=30.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,
|
||||||
interest_mode=InterestMode.HOURSPERDAY,
|
|
||||||
fee_open=fee.return_value,
|
fee_open=fee.return_value,
|
||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
@ -644,12 +640,12 @@ def test_calc_open_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt
|
|||||||
assert trade.calc_profit_ratio() == round(0.0945137157107232, 8)
|
assert trade.calc_profit_ratio() == round(0.0945137157107232, 8)
|
||||||
# 3x leverage, binance
|
# 3x leverage, binance
|
||||||
trade.leverage = 3
|
trade.leverage = 3
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert trade._calc_open_trade_value() == 60.15
|
assert trade._calc_open_trade_value() == 60.15
|
||||||
assert round(trade.calc_close_trade_value(), 8) == 65.83416667
|
assert round(trade.calc_close_trade_value(), 8) == 65.83416667
|
||||||
assert trade.calc_profit() == round(5.684166670000003, 8)
|
assert trade.calc_profit() == round(5.684166670000003, 8)
|
||||||
assert trade.calc_profit_ratio() == round(0.2834995845386534, 8)
|
assert trade.calc_profit_ratio() == round(0.2834995845386534, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
# 3x leverage, kraken
|
# 3x leverage, kraken
|
||||||
assert trade._calc_open_trade_value() == 60.15
|
assert trade._calc_open_trade_value() == 60.15
|
||||||
assert trade.calc_close_trade_value() == 65.795
|
assert trade.calc_close_trade_value() == 65.795
|
||||||
@ -662,7 +658,7 @@ def test_calc_open_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt
|
|||||||
assert trade.calc_close_trade_value() == 66.231165
|
assert trade.calc_close_trade_value() == 66.231165
|
||||||
assert trade.calc_profit() == round(-6.381165000000003, 8)
|
assert trade.calc_profit() == round(-6.381165000000003, 8)
|
||||||
assert trade.calc_profit_ratio() == round(-0.319857894736842, 8)
|
assert trade.calc_profit_ratio() == round(-0.319857894736842, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
# 3x leverage, short, binance
|
# 3x leverage, short, binance
|
||||||
assert trade._calc_open_trade_value() == 59.85
|
assert trade._calc_open_trade_value() == 59.85
|
||||||
assert trade.calc_close_trade_value() == 66.1663784375
|
assert trade.calc_close_trade_value() == 66.1663784375
|
||||||
@ -675,7 +671,7 @@ def test_calc_open_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt
|
|||||||
assert trade.calc_profit() == round(-6.316378437500013, 8)
|
assert trade.calc_profit() == round(-6.316378437500013, 8)
|
||||||
assert trade.calc_profit_ratio() == round(-0.1055368159983292, 8)
|
assert trade.calc_profit_ratio() == round(-0.1055368159983292, 8)
|
||||||
# 1x leverage, short, kraken
|
# 1x leverage, short, kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert trade._calc_open_trade_value() == 59.850
|
assert trade._calc_open_trade_value() == 59.850
|
||||||
assert trade.calc_close_trade_value() == 66.231165
|
assert trade.calc_close_trade_value() == 66.231165
|
||||||
assert trade.calc_profit() == -6.381165
|
assert trade.calc_profit() == -6.381165
|
||||||
@ -694,7 +690,6 @@ def test_trade_close(limit_buy_order_usdt, limit_sell_order_usdt, fee):
|
|||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
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,
|
||||||
interest_mode=InterestMode.HOURSPERDAY,
|
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
)
|
)
|
||||||
assert trade.close_profit is None
|
assert trade.close_profit is None
|
||||||
@ -805,7 +800,7 @@ def test_calc_open_trade_value(limit_buy_order_usdt, fee):
|
|||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
assert trade._calc_open_trade_value() == 59.85
|
assert trade._calc_open_trade_value() == 59.85
|
||||||
trade.leverage = 3
|
trade.leverage = 3
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
trade.exchange = "binance"
|
||||||
assert trade._calc_open_trade_value() == 59.85
|
assert trade._calc_open_trade_value() == 59.85
|
||||||
trade.is_short = False
|
trade.is_short = False
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
@ -832,7 +827,6 @@ def test_calc_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt, fee
|
|||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
interest_rate=0.0005,
|
interest_rate=0.0005,
|
||||||
interest_mode=InterestMode.HOURSPERDAY
|
|
||||||
)
|
)
|
||||||
trade.open_order_id = 'close_trade'
|
trade.open_order_id = 'close_trade'
|
||||||
trade.update(limit_buy_order_usdt)
|
trade.update(limit_buy_order_usdt)
|
||||||
@ -849,7 +843,7 @@ def test_calc_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt, fee
|
|||||||
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 74.77416667
|
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 74.77416667
|
||||||
|
|
||||||
# 3x leverage kraken
|
# 3x leverage kraken
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_close_trade_value(rate=2.5) == 74.7725
|
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
|
assert trade.calc_close_trade_value(rate=2.5, fee=0.003) == 74.735
|
||||||
|
|
||||||
@ -860,7 +854,7 @@ def test_calc_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt, fee
|
|||||||
assert trade.calc_close_trade_value(rate=2.5, fee=0.003) == 75.300225
|
assert trade.calc_close_trade_value(rate=2.5, fee=0.003) == 75.300225
|
||||||
|
|
||||||
# 3x leverage binance, short
|
# 3x leverage binance, short
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY
|
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), 8) == 75.18906641
|
||||||
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 75.22656719
|
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 75.22656719
|
||||||
|
|
||||||
@ -870,7 +864,7 @@ def test_calc_close_trade_price(limit_buy_order_usdt, limit_sell_order_usdt, fee
|
|||||||
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 75.22656719
|
assert round(trade.calc_close_trade_value(rate=2.5, fee=0.003), 8) == 75.22656719
|
||||||
|
|
||||||
# 1x leverage kraken, short
|
# 1x leverage kraken, short
|
||||||
trade.interest_mode = InterestMode.HOURSPER4
|
trade.exchange = "kraken"
|
||||||
assert round(trade.calc_close_trade_value(rate=2.5), 8) == 75.2626875
|
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
|
assert trade.calc_close_trade_value(rate=2.5, fee=0.003) == 75.300225
|
||||||
|
|
||||||
@ -1013,7 +1007,6 @@ 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,
|
||||||
interest_mode=InterestMode.HOURSPERDAY,
|
|
||||||
fee_open=fee.return_value,
|
fee_open=fee.return_value,
|
||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
exchange='binance'
|
exchange='binance'
|
||||||
@ -1047,62 +1040,62 @@ def test_calc_profit(limit_buy_order_usdt, limit_sell_order_usdt, fee):
|
|||||||
# 3x leverage, long ###################################################
|
# 3x leverage, long ###################################################
|
||||||
trade.leverage = 3.0
|
trade.leverage = 3.0
|
||||||
# Higher than open rate - 2.1 quote
|
# Higher than open rate - 2.1 quote
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(rate=2.1, fee=0.0025) == 2.69166667
|
assert trade.calc_profit(rate=2.1, fee=0.0025) == 2.69166667
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(rate=2.1, fee=0.0025) == 2.6525
|
assert trade.calc_profit(rate=2.1, fee=0.0025) == 2.6525
|
||||||
|
|
||||||
# 1.9 quote
|
# 1.9 quote
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(rate=1.9, fee=0.0025) == -3.29333333
|
assert trade.calc_profit(rate=1.9, fee=0.0025) == -3.29333333
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(rate=1.9, fee=0.0025) == -3.3325
|
assert trade.calc_profit(rate=1.9, fee=0.0025) == -3.3325
|
||||||
|
|
||||||
# 2.2 quote
|
# 2.2 quote
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(fee=0.0025) == 5.68416667
|
assert trade.calc_profit(fee=0.0025) == 5.68416667
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(fee=0.0025) == 5.645
|
assert trade.calc_profit(fee=0.0025) == 5.645
|
||||||
|
|
||||||
# 3x leverage, short ###################################################
|
# 3x leverage, short ###################################################
|
||||||
trade.is_short = True
|
trade.is_short = True
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# 2.1 quote - Higher than open rate
|
# 2.1 quote - Higher than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(rate=2.1, fee=0.0025) == round(-3.308815781249997, 8)
|
assert trade.calc_profit(rate=2.1, fee=0.0025) == round(-3.308815781249997, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(rate=2.1, fee=0.0025) == -3.3706575
|
assert trade.calc_profit(rate=2.1, fee=0.0025) == -3.3706575
|
||||||
|
|
||||||
# 1.9 quote - Lower than open rate
|
# 1.9 quote - Lower than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(rate=1.9, fee=0.0025) == round(2.7063095312499996, 8)
|
assert trade.calc_profit(rate=1.9, fee=0.0025) == round(2.7063095312499996, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(rate=1.9, fee=0.0025) == 2.6503575
|
assert trade.calc_profit(rate=1.9, fee=0.0025) == 2.6503575
|
||||||
|
|
||||||
# Test when we apply a Sell order. Uses sell order used above
|
# Test when we apply a Sell order. Uses sell order used above
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(fee=0.0025) == round(-6.316378437499999, 8)
|
assert trade.calc_profit(fee=0.0025) == round(-6.316378437499999, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(fee=0.0025) == -6.381165
|
assert trade.calc_profit(fee=0.0025) == -6.381165
|
||||||
|
|
||||||
# 1x leverage, short ###################################################
|
# 1x leverage, short ###################################################
|
||||||
trade.leverage = 1.0
|
trade.leverage = 1.0
|
||||||
# 2.1 quote - Higher than open rate
|
# 2.1 quote - Higher than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(rate=2.1, fee=0.0025) == round(-3.308815781249997, 8)
|
assert trade.calc_profit(rate=2.1, fee=0.0025) == round(-3.308815781249997, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(rate=2.1, fee=0.0025) == -3.3706575
|
assert trade.calc_profit(rate=2.1, fee=0.0025) == -3.3706575
|
||||||
|
|
||||||
# 1.9 quote - Lower than open rate
|
# 1.9 quote - Lower than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(rate=1.9, fee=0.0025) == round(2.7063095312499996, 8)
|
assert trade.calc_profit(rate=1.9, fee=0.0025) == round(2.7063095312499996, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(rate=1.9, fee=0.0025) == 2.6503575
|
assert trade.calc_profit(rate=1.9, fee=0.0025) == 2.6503575
|
||||||
|
|
||||||
# Test when we apply a Sell order. Uses sell order used above
|
# Test when we apply a Sell order. Uses sell order used above
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit(fee=0.0025) == round(-6.316378437499999, 8)
|
assert trade.calc_profit(fee=0.0025) == round(-6.316378437499999, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit(fee=0.0025) == -6.381165
|
assert trade.calc_profit(fee=0.0025) == -6.381165
|
||||||
|
|
||||||
|
|
||||||
@ -1115,7 +1108,6 @@ def test_calc_profit_ratio(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,
|
||||||
interest_mode=InterestMode.HOURSPERDAY,
|
|
||||||
fee_open=fee.return_value,
|
fee_open=fee.return_value,
|
||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
exchange='binance'
|
exchange='binance'
|
||||||
@ -1150,62 +1142,62 @@ def test_calc_profit_ratio(limit_buy_order_usdt, limit_sell_order_usdt, fee):
|
|||||||
# 3x leverage, long ###################################################
|
# 3x leverage, long ###################################################
|
||||||
trade.leverage = 3.0
|
trade.leverage = 3.0
|
||||||
# 2.1 quote - Higher than open rate
|
# 2.1 quote - Higher than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit_ratio(rate=2.1) == round(0.13424771421446402, 8)
|
assert trade.calc_profit_ratio(rate=2.1) == round(0.13424771421446402, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio(rate=2.1) == round(0.13229426433915248, 8)
|
assert trade.calc_profit_ratio(rate=2.1) == round(0.13229426433915248, 8)
|
||||||
|
|
||||||
# 1.9 quote - Lower than open rate
|
# 1.9 quote - Lower than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit_ratio(rate=1.9) == round(-0.16425602643391513, 8)
|
assert trade.calc_profit_ratio(rate=1.9) == round(-0.16425602643391513, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio(rate=1.9) == round(-0.16620947630922667, 8)
|
assert trade.calc_profit_ratio(rate=1.9) == round(-0.16620947630922667, 8)
|
||||||
|
|
||||||
# Test when we apply a Sell order. Uses sell order used above
|
# Test when we apply a Sell order. Uses sell order used above
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit_ratio() == round(0.2834995845386534, 8)
|
assert trade.calc_profit_ratio() == round(0.2834995845386534, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio() == round(0.2815461346633419, 8)
|
assert trade.calc_profit_ratio() == round(0.2815461346633419, 8)
|
||||||
|
|
||||||
# 3x leverage, short ###################################################
|
# 3x leverage, short ###################################################
|
||||||
trade.is_short = True
|
trade.is_short = True
|
||||||
trade.recalc_open_trade_value()
|
trade.recalc_open_trade_value()
|
||||||
# 2.1 quote - Higher than open rate
|
# 2.1 quote - Higher than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit_ratio(rate=2.1) == round(-0.1658554276315789, 8)
|
assert trade.calc_profit_ratio(rate=2.1) == round(-0.1658554276315789, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio(rate=2.1) == round(-0.16895526315789455, 8)
|
assert trade.calc_profit_ratio(rate=2.1) == round(-0.16895526315789455, 8)
|
||||||
|
|
||||||
# 1.9 quote - Lower than open rate
|
# 1.9 quote - Lower than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit_ratio(rate=1.9) == round(0.13565461309523819, 8)
|
assert trade.calc_profit_ratio(rate=1.9) == round(0.13565461309523819, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio(rate=1.9) == round(0.13285000000000002, 8)
|
assert trade.calc_profit_ratio(rate=1.9) == round(0.13285000000000002, 8)
|
||||||
|
|
||||||
# Test when we apply a Sell order. Uses sell order used above
|
# Test when we apply a Sell order. Uses sell order used above
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit_ratio() == round(-0.3166104479949876, 8)
|
assert trade.calc_profit_ratio() == round(-0.3166104479949876, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio() == round(-0.319857894736842, 8)
|
assert trade.calc_profit_ratio() == round(-0.319857894736842, 8)
|
||||||
|
|
||||||
# 1x leverage, short ###################################################
|
# 1x leverage, short ###################################################
|
||||||
trade.leverage = 1.0
|
trade.leverage = 1.0
|
||||||
# 2.1 quote - Higher than open rate
|
# 2.1 quote - Higher than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance" # binance
|
||||||
assert trade.calc_profit_ratio(rate=2.1) == round(-0.05528514254385963, 8)
|
assert trade.calc_profit_ratio(rate=2.1) == round(-0.05528514254385963, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio(rate=2.1) == round(-0.05631842105263152, 8)
|
assert trade.calc_profit_ratio(rate=2.1) == round(-0.05631842105263152, 8)
|
||||||
|
|
||||||
# 1.9 quote - Lower than open rate
|
# 1.9 quote - Lower than open rate
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance"
|
||||||
assert trade.calc_profit_ratio(rate=1.9) == round(0.045218204365079395, 8)
|
assert trade.calc_profit_ratio(rate=1.9) == round(0.045218204365079395, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio(rate=1.9) == round(0.04428333333333334, 8)
|
assert trade.calc_profit_ratio(rate=1.9) == round(0.04428333333333334, 8)
|
||||||
|
|
||||||
# Test when we apply a Sell order. Uses sell order used above
|
# Test when we apply a Sell order. Uses sell order used above
|
||||||
trade.interest_mode = InterestMode.HOURSPERDAY # binance
|
trade.exchange = "binance"
|
||||||
assert trade.calc_profit_ratio() == round(-0.1055368159983292, 8)
|
assert trade.calc_profit_ratio() == round(-0.1055368159983292, 8)
|
||||||
trade.interest_mode = InterestMode.HOURSPER4 # kraken
|
trade.exchange = "kraken"
|
||||||
assert trade.calc_profit_ratio() == round(-0.106619298245614, 8)
|
assert trade.calc_profit_ratio() == round(-0.106619298245614, 8)
|
||||||
|
|
||||||
|
|
||||||
@ -1542,7 +1534,6 @@ def test_adjust_stop_loss_short(fee):
|
|||||||
open_rate=1,
|
open_rate=1,
|
||||||
max_rate=1,
|
max_rate=1,
|
||||||
is_short=True,
|
is_short=True,
|
||||||
interest_mode=InterestMode.HOURSPERDAY
|
|
||||||
)
|
)
|
||||||
trade.adjust_stop_loss(trade.open_rate, 0.05, True)
|
trade.adjust_stop_loss(trade.open_rate, 0.05, True)
|
||||||
assert trade.stop_loss == 1.05
|
assert trade.stop_loss == 1.05
|
||||||
@ -1859,7 +1850,6 @@ def test_stoploss_reinitialization_short(default_conf, fee):
|
|||||||
max_rate=1,
|
max_rate=1,
|
||||||
is_short=True,
|
is_short=True,
|
||||||
leverage=3.0,
|
leverage=3.0,
|
||||||
interest_mode=InterestMode.HOURSPERDAY
|
|
||||||
)
|
)
|
||||||
trade.adjust_stop_loss(trade.open_rate, -0.05, True)
|
trade.adjust_stop_loss(trade.open_rate, -0.05, True)
|
||||||
assert trade.stop_loss == 1.05
|
assert trade.stop_loss == 1.05
|
||||||
|
Loading…
Reference in New Issue
Block a user