2021-07-02 08:48:30 +00:00
import logging
from datetime import datetime , timedelta , timezone
from pathlib import Path
from types import FunctionType
from unittest . mock import MagicMock
import arrow
import pytest
from math import isclose
from sqlalchemy import create_engine , inspect , text
from freqtrade import constants
2021-07-06 03:48:56 +00:00
from freqtrade . enums import InterestMode
2021-07-02 08:48:30 +00:00
from freqtrade . exceptions import DependencyException , OperationalException
from freqtrade . persistence import LocalTrade , Order , Trade , clean_dry_run_db , init_db
from tests . conftest import create_mock_trades_with_leverage , log_has , log_has_re
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_interest_kraken_lev ( market_leveraged_buy_order , fee ) :
2021-07-02 08:48:30 +00:00
"""
2021-07-04 06:11:59 +00:00
Market trade on Kraken at 3 x and 5 x leverage
Short trade
interest_rate : 0.05 % , 0.25 % per 4 hrs
open_rate : 0.00004099 base
close_rate : 0.00004173 base
stake_amount : 0.0037707443218227
borrowed : 0.0075414886436454
amount :
275.97543219 crypto
459.95905365 crypto
borrowed :
0.0075414886436454 base
0.0150829772872908 base
time - periods : 10 minutes ( rounds up to 1 time - period of 4 hrs )
5 hours = 5 / 4
2021-07-02 08:48:30 +00:00
2021-07-04 06:11:59 +00:00
interest : borrowed * interest_rate * time - periods
= 0.0075414886436454 * 0.0005 * 1 = 3.7707443218227e-06 base
= 0.0075414886436454 * 0.00025 * 5 / 4 = 2.3567152011391876e-06 base
= 0.0150829772872908 * 0.0005 * 5 / 4 = 9.42686080455675e-06 base
= 0.0150829772872908 * 0.00025 * 1 = 3.7707443218227e-06 base
"""
trade = Trade (
pair = ' ETH/BTC ' ,
stake_amount = 0.0037707443218227 ,
amount = 275.97543219 ,
open_rate = 0.00001099 ,
open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 ) ,
fee_open = fee . return_value ,
fee_close = fee . return_value ,
exchange = ' kraken ' ,
leverage = 3.0 ,
2021-07-06 03:48:56 +00:00
interest_rate = 0.0005 ,
interest_mode = InterestMode . HOURSPER4
2021-07-04 06:11:59 +00:00
)
# The trades that last 10 minutes do not need to be rounded because they round up to 4 hours on kraken so we can predict the correct value
assert float ( trade . calculate_interest ( ) ) == 3.7707443218227e-06
trade . open_date = datetime . utcnow ( ) - timedelta ( hours = 5 , minutes = 0 )
# The trades that last for 5 hours have to be rounded because the length of time that the test takes will vary every time it runs, so we can't predict the exact value
assert float ( round ( trade . calculate_interest ( interest_rate = 0.00025 ) , 11 )
) == round ( 2.3567152011391876e-06 , 11 )
trade = Trade (
pair = ' ETH/BTC ' ,
stake_amount = 0.0037707443218227 ,
amount = 459.95905365 ,
open_rate = 0.00001099 ,
open_date = datetime . utcnow ( ) - timedelta ( hours = 5 , minutes = 0 ) ,
fee_open = fee . return_value ,
fee_close = fee . return_value ,
exchange = ' kraken ' ,
leverage = 5.0 ,
2021-07-06 03:48:56 +00:00
interest_rate = 0.0005 ,
interest_mode = InterestMode . HOURSPER4
2021-07-04 06:11:59 +00:00
)
assert float ( round ( trade . calculate_interest ( ) , 11 )
) == round ( 9.42686080455675e-06 , 11 )
trade . open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 )
assert float ( trade . calculate_interest ( interest_rate = 0.00025 ) ) == 3.7707443218227e-06
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_interest_binance_lev ( market_leveraged_buy_order , fee ) :
2021-07-04 06:11:59 +00:00
"""
Market trade on Kraken at 3 x and 5 x leverage
Short trade
interest_rate : 0.05 % , 0.25 % per 4 hrs
2021-07-02 08:48:30 +00:00
open_rate : 0.00001099 base
close_rate : 0.00001173 base
2021-07-04 06:11:59 +00:00
stake_amount : 0.0009999999999226999
borrowed : 0.0019999999998453998
amount :
90.99181073 * leverage ( 3 ) = 272.97543219 crypto
90.99181073 * leverage ( 5 ) = 454.95905365 crypto
borrowed :
0.0019999999998453998 base
0.0039999999996907995 base
time - periods : 10 minutes ( rounds up to 1 / 24 time - period of 24 hrs )
5 hours = 5 / 24
2021-07-02 08:48:30 +00:00
2021-07-04 06:11:59 +00:00
interest : borrowed * interest_rate * time - periods
= 0.0019999999998453998 * 0.00050 * 1 / 24 = 4.166666666344583e-08 base
= 0.0019999999998453998 * 0.00025 * 5 / 24 = 1.0416666665861459e-07 base
= 0.0039999999996907995 * 0.00050 * 5 / 24 = 4.1666666663445834e-07 base
= 0.0039999999996907995 * 0.00025 * 1 / 24 = 4.166666666344583e-08 base
2021-07-02 08:48:30 +00:00
"""
2021-07-04 06:11:59 +00:00
2021-07-02 08:48:30 +00:00
trade = Trade (
pair = ' ETH/BTC ' ,
stake_amount = 0.0009999999999226999 ,
2021-07-04 06:11:59 +00:00
amount = 272.97543219 ,
open_rate = 0.00001099 ,
open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 ) ,
2021-07-02 08:48:30 +00:00
fee_open = fee . return_value ,
fee_close = fee . return_value ,
2021-07-04 06:11:59 +00:00
exchange = ' binance ' ,
leverage = 3.0 ,
2021-07-06 03:48:56 +00:00
interest_rate = 0.0005 ,
interest_mode = InterestMode . HOURSPERDAY
2021-07-04 06:11:59 +00:00
)
# The trades that last 10 minutes do not always need to be rounded because they round up to 4 hours on kraken so we can predict the correct value
assert round ( float ( trade . calculate_interest ( ) ) , 22 ) == round ( 4.166666666344583e-08 , 22 )
trade . open_date = datetime . utcnow ( ) - timedelta ( hours = 5 , minutes = 0 )
# The trades that last for 5 hours have to be rounded because the length of time that the test takes will vary every time it runs, so we can't predict the exact value
assert float ( round ( trade . calculate_interest ( interest_rate = 0.00025 ) , 14 )
) == round ( 1.0416666665861459e-07 , 14 )
trade = Trade (
pair = ' ETH/BTC ' ,
stake_amount = 0.0009999999999226999 ,
amount = 459.95905365 ,
open_rate = 0.00001099 ,
open_date = datetime . utcnow ( ) - timedelta ( hours = 5 , minutes = 0 ) ,
fee_open = fee . return_value ,
fee_close = fee . return_value ,
exchange = ' binance ' ,
leverage = 5.0 ,
2021-07-06 03:48:56 +00:00
interest_rate = 0.0005 ,
interest_mode = InterestMode . HOURSPERDAY
2021-07-04 06:11:59 +00:00
)
assert float ( round ( trade . calculate_interest ( ) , 14 ) ) == round ( 4.1666666663445834e-07 , 14 )
trade . open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 )
assert float ( round ( trade . calculate_interest ( interest_rate = 0.00025 ) , 22 )
) == round ( 4.166666666344583e-08 , 22 )
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_update_open_order_lev ( limit_leveraged_buy_order ) :
2021-07-04 06:11:59 +00:00
trade = Trade (
pair = ' ETH/BTC ' ,
stake_amount = 1.00 ,
open_rate = 0.01 ,
amount = 5 ,
fee_open = 0.1 ,
fee_close = 0.1 ,
2021-07-02 08:48:30 +00:00
interest_rate = 0.0005 ,
2021-07-04 06:11:59 +00:00
exchange = ' binance ' ,
2021-07-06 03:48:56 +00:00
interest_mode = InterestMode . HOURSPERDAY
2021-07-02 08:48:30 +00:00
)
2021-07-04 06:11:59 +00:00
assert trade . open_order_id is None
2021-07-02 08:48:30 +00:00
assert trade . close_profit is None
assert trade . close_date is None
2021-07-04 06:11:59 +00:00
limit_leveraged_buy_order [ ' status ' ] = ' open '
2021-07-02 08:48:30 +00:00
trade . update ( limit_leveraged_buy_order )
2021-07-04 06:11:59 +00:00
assert trade . open_order_id is None
2021-07-02 08:48:30 +00:00
assert trade . close_profit is None
assert trade . close_date is None
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_calc_open_trade_value_lev ( market_leveraged_buy_order , fee ) :
2021-07-02 08:48:30 +00:00
"""
10 minute leveraged market trade on Kraken at 3 x leverage
Short trade
fee : 0.25 % base
interest_rate : 0.05 % per 4 hrs
open_rate : 0.00004099 base
close_rate : 0.00004173 base
amount : 91.99181073 * leverage ( 3 ) = 275.97543219 crypto
stake_amount : 0.0037707443218227
borrowed : 0.0075414886436454 base
time - periods : 10 minutes ( rounds up to 1 time - period of 4 hrs )
interest : borrowed * interest_rate * time - periods
2021-07-04 06:11:59 +00:00
= 0.0075414886436454 * 0.0005 * 1 = 3.7707443218227e-06 crypto
2021-07-02 08:48:30 +00:00
open_value : ( amount * open_rate ) + ( amount * open_rate * fee )
= ( 275.97543219 * 0.00004099 ) + ( 275.97543219 * 0.00004099 * 0.0025 )
= 0.01134051354788177
"""
trade = Trade (
pair = ' ETH/BTC ' ,
2021-07-04 06:11:59 +00:00
stake_amount = 0.001 ,
2021-07-02 08:48:30 +00:00
amount = 5 ,
2021-07-04 06:11:59 +00:00
open_rate = 0.00004099 ,
open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 ) ,
2021-07-02 08:48:30 +00:00
fee_open = fee . return_value ,
fee_close = fee . return_value ,
interest_rate = 0.0005 ,
2021-07-04 06:11:59 +00:00
exchange = ' kraken ' ,
2021-07-06 03:48:56 +00:00
leverage = 3 ,
interest_mode = InterestMode . HOURSPER4
2021-07-02 08:48:30 +00:00
)
2021-07-04 06:11:59 +00:00
trade . open_order_id = ' open_trade '
trade . update ( market_leveraged_buy_order ) # Buy @ 0.00001099
# Get the open rate price with the standard fee rate
assert trade . _calc_open_trade_value ( ) == 0.01134051354788177
trade . fee_open = 0.003
# Get the open rate price with a custom fee rate
assert trade . _calc_open_trade_value ( ) == 0.011346169664364504
2021-07-02 08:48:30 +00:00
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_calc_open_close_trade_price_lev ( limit_leveraged_buy_order , limit_leveraged_sell_order , fee ) :
2021-07-02 08:48:30 +00:00
"""
5 hour leveraged trade on Binance
fee : 0.25 % base
interest_rate : 0.05 % per day
open_rate : 0.00001099 base
close_rate : 0.00001173 base
amount : 272.97543219 crypto
stake_amount : 0.0009999999999226999 base
borrowed : 0.0019999999998453998 base
time - periods : 5 hours ( rounds up to 5 / 24 time - period of 1 day )
interest : borrowed * interest_rate * time - periods
= 0.0019999999998453998 * 0.0005 * 5 / 24 = 2.0833333331722917e-07 base
open_value : ( amount * open_rate ) + ( amount * open_rate * fee )
= ( 272.97543219 * 0.00001099 ) + ( 272.97543219 * 0.00001099 * 0.0025 )
= 0.0030074999997675204
2021-07-04 06:11:59 +00:00
close_value : ( ( amount_closed * close_rate ) - ( amount_closed * close_rate * fee ) ) - interest
= ( 272.97543219 * 0.00001173 ) - ( 272.97543219 * 0.00001173 * 0.0025 ) - 2.0833333331722917e-07
= 0.003193788481706411
total_profit = close_value - open_value
= 0.003193788481706411 - 0.0030074999997675204
= 0.00018628848193889044
2021-07-02 08:48:30 +00:00
total_profit_percentage = total_profit / stake_amount
= 0.00018628848193889054 / 0.0009999999999226999
= 0.18628848195329067
"""
trade = Trade (
pair = ' ETH/BTC ' ,
stake_amount = 0.0009999999999226999 ,
open_rate = 0.01 ,
amount = 5 ,
2021-07-04 06:11:59 +00:00
open_date = datetime . utcnow ( ) - timedelta ( hours = 5 , minutes = 0 ) ,
2021-07-02 08:48:30 +00:00
fee_open = fee . return_value ,
fee_close = fee . return_value ,
exchange = ' binance ' ,
2021-07-06 03:48:56 +00:00
interest_rate = 0.0005 ,
interest_mode = InterestMode . HOURSPERDAY
2021-07-02 08:48:30 +00:00
)
trade . open_order_id = ' something '
trade . update ( limit_leveraged_buy_order )
2021-07-04 06:11:59 +00:00
assert trade . _calc_open_trade_value ( ) == 0.00300749999976752
2021-07-02 08:48:30 +00:00
trade . update ( limit_leveraged_sell_order )
# Will be slightly different due to slight changes in compilation time, and the fact that interest depends on time
2021-07-04 06:11:59 +00:00
assert round ( trade . calc_close_trade_value ( ) , 11 ) == round ( 0.003193788481706411 , 11 )
2021-07-02 08:48:30 +00:00
# Profit in BTC
2021-07-04 06:11:59 +00:00
assert round ( trade . calc_profit ( ) , 8 ) == round ( 0.00018628848193889054 , 8 )
2021-07-02 08:48:30 +00:00
# Profit in percent
2021-07-04 06:11:59 +00:00
assert round ( trade . calc_profit_ratio ( ) , 8 ) == round ( 0.18628848195329067 , 8 )
2021-07-02 08:48:30 +00:00
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_trade_close_lev ( fee ) :
2021-07-02 08:48:30 +00:00
"""
5 hour leveraged market trade on Kraken at 3 x leverage
fee : 0.25 % base
interest_rate : 0.05 % per 4 hrs
open_rate : 0.1 base
close_rate : 0.2 base
amount : 5 * leverage ( 3 ) = 15 crypto
stake_amount : 0.5
borrowed : 1 base
time - periods : 5 / 4 periods of 4 hrs
interest : borrowed * interest_rate * time - periods
= 1 * 0.0005 * 5 / 4 = 0.000625 crypto
open_value : ( amount * open_rate ) + ( amount * open_rate * fee )
= ( 15 * 0.1 ) + ( 15 * 0.1 * 0.0025 )
= 1.50375
2021-07-04 06:11:59 +00:00
close_value : ( amount_closed * close_rate ) + ( amount_closed * close_rate * fee ) - interest
= ( 15 * 0.2 ) - ( 15 * 0.2 * 0.0025 ) - 0.000625
= 2.9918750000000003
total_profit = close_value - open_value
= 2.9918750000000003 - 1.50375
2021-07-02 08:48:30 +00:00
= 1.4881250000000001
total_profit_percentage = total_profit / stake_amount
= 1.4881250000000001 / 0.5
= 2.9762500000000003
"""
trade = Trade (
pair = ' ETH/BTC ' ,
2021-07-04 06:11:59 +00:00
stake_amount = 0.5 ,
open_rate = 0.1 ,
amount = 15 ,
2021-07-02 08:48:30 +00:00
is_open = True ,
fee_open = fee . return_value ,
fee_close = fee . return_value ,
2021-07-04 06:11:59 +00:00
open_date = datetime . utcnow ( ) - timedelta ( hours = 5 , minutes = 0 ) ,
2021-07-02 08:48:30 +00:00
exchange = ' kraken ' ,
leverage = 3.0 ,
2021-07-06 03:48:56 +00:00
interest_rate = 0.0005 ,
interest_mode = InterestMode . HOURSPER4
2021-07-02 08:48:30 +00:00
)
assert trade . close_profit is None
assert trade . close_date is None
assert trade . is_open is True
2021-07-04 06:11:59 +00:00
trade . close ( 0.2 )
2021-07-02 08:48:30 +00:00
assert trade . is_open is False
assert trade . close_profit == round ( 2.9762500000000003 , 8 )
assert trade . close_date is not None
# TODO-mg: Remove these comments probably
# new_date = arrow.Arrow(2020, 2, 2, 15, 6, 1).datetime,
# assert trade.close_date != new_date
# # Close should NOT update close_date if the trade has been closed already
# assert trade.is_open is False
# trade.close_date = new_date
# trade.close(0.02)
# assert trade.close_date == new_date
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_calc_close_trade_price_lev ( market_leveraged_buy_order , market_leveraged_sell_order , fee ) :
2021-07-04 06:11:59 +00:00
"""
10 minute leveraged market trade on Kraken at 3 x leverage
Short trade
fee : 0.25 % base
interest_rate : 0.05 % per 4 hrs
open_rate : 0.00004099 base
close_rate : 0.00004173 base
amount : 91.99181073 * leverage ( 3 ) = 275.97543219 crypto
stake_amount : 0.0037707443218227
borrowed : 0.0075414886436454 base
time - periods : 10 minutes ( rounds up to 1 time - period of 4 hrs )
interest : borrowed * interest_rate * time - periods
= 0.0075414886436454 * 0.0005 * 1 = 3.7707443218227e-06 crypto
open_value : ( amount * open_rate ) + ( amount * open_rate * fee )
= ( 275.97543219 * 0.00004099 ) + ( 275.97543219 * 0.00004099 * 0.0025 )
= 0.01134051354788177
close_value : ( amount_closed * close_rate ) - ( amount_closed * close_rate * fee ) - interest
= ( 275.97543219 * 0.00001234 ) - ( 275.97543219 * 0.00001234 * 0.0025 ) - 3.7707443218227e-06 = 0.003393252246819716
= ( 275.97543219 * 0.00001234 ) - ( 275.97543219 * 0.00001234 * 0.003 ) - 3.7707443218227e-06 = 0.003391549478403104
= ( 275.97543219 * 0.00004173 ) - ( 275.97543219 * 0.00004173 * 0.005 ) - 3.7707443218227e-06 = 0.011455101767040435
"""
2021-07-02 08:48:30 +00:00
trade = Trade (
pair = ' ETH/BTC ' ,
2021-07-04 06:11:59 +00:00
stake_amount = 0.0037707443218227 ,
2021-07-02 08:48:30 +00:00
amount = 5 ,
2021-07-04 06:11:59 +00:00
open_rate = 0.00004099 ,
2021-07-02 08:48:30 +00:00
fee_open = fee . return_value ,
fee_close = fee . return_value ,
2021-07-04 06:11:59 +00:00
open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 ) ,
2021-07-02 08:48:30 +00:00
interest_rate = 0.0005 ,
2021-07-04 06:11:59 +00:00
leverage = 3.0 ,
exchange = ' kraken ' ,
2021-07-06 03:48:56 +00:00
interest_mode = InterestMode . HOURSPER4
2021-07-02 08:48:30 +00:00
)
2021-07-04 06:11:59 +00:00
trade . open_order_id = ' close_trade '
trade . update ( market_leveraged_buy_order ) # Buy @ 0.00001099
# Get the close rate price with a custom close rate and a regular fee rate
assert isclose ( trade . calc_close_trade_value ( rate = 0.00001234 ) , 0.003393252246819716 )
# Get the close rate price with a custom close rate and a custom fee rate
assert isclose ( trade . calc_close_trade_value ( rate = 0.00001234 , fee = 0.003 ) , 0.003391549478403104 )
# Test when we apply a Sell order, and ask price with a custom fee rate
trade . update ( market_leveraged_sell_order )
assert isclose ( trade . calc_close_trade_value ( fee = 0.005 ) , 0.011455101767040435 )
2021-07-02 08:48:30 +00:00
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_update_limit_order_lev ( limit_leveraged_buy_order , limit_leveraged_sell_order , fee , caplog ) :
2021-07-04 06:11:59 +00:00
"""
10 minute leveraged limit trade on binance at 3 x leverage
Leveraged trade
fee : 0.25 % base
interest_rate : 0.05 % per day
open_rate : 0.00001099 base
close_rate : 0.00001173 base
amount : 272.97543219 crypto
stake_amount : 0.0009999999999226999 base
borrowed : 0.0019999999998453998 base
time - periods : 10 minutes ( rounds up to 1 / 24 time - period of 1 day )
interest : borrowed * interest_rate * time - periods
= 0.0019999999998453998 * 0.0005 * 1 / 24 = 4.166666666344583e-08 base
open_value : ( amount * open_rate ) + ( amount * open_rate * fee )
= ( 272.97543219 * 0.00001099 ) + ( 272.97543219 * 0.00001099 * 0.0025 )
= 0.0030074999997675204
close_value : ( amount_closed * close_rate ) - ( amount_closed * close_rate * fee )
= ( 272.97543219 * 0.00001173 ) - ( 272.97543219 * 0.00001173 * 0.0025 )
= 0.003193996815039728
total_profit = close_value - open_value - interest
= 0.003193996815039728 - 0.0030074999997675204 - 4.166666666344583e-08
= 0.00018645514860554435
total_profit_percentage = total_profit / stake_amount
= 0.00018645514860554435 / 0.0009999999999226999
= 0.18645514861995735
"""
2021-07-02 08:48:30 +00:00
trade = Trade (
2021-07-04 06:11:59 +00:00
id = 2 ,
2021-07-02 08:48:30 +00:00
pair = ' ETH/BTC ' ,
2021-07-04 06:11:59 +00:00
stake_amount = 0.0009999999999226999 ,
2021-07-02 08:48:30 +00:00
open_rate = 0.01 ,
amount = 5 ,
2021-07-04 06:11:59 +00:00
is_open = True ,
open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 ) ,
fee_open = fee . return_value ,
fee_close = fee . return_value ,
2021-07-02 08:48:30 +00:00
interest_rate = 0.0005 ,
2021-07-06 03:48:56 +00:00
exchange = ' binance ' ,
interest_mode = InterestMode . HOURSPERDAY
2021-07-02 08:48:30 +00:00
)
2021-07-04 06:11:59 +00:00
# assert trade.open_order_id is None
2021-07-02 08:48:30 +00:00
assert trade . close_profit is None
assert trade . close_date is None
2021-07-04 06:11:59 +00:00
# trade.open_order_id = 'something'
2021-07-02 08:48:30 +00:00
trade . update ( limit_leveraged_buy_order )
2021-07-04 06:11:59 +00:00
# assert trade.open_order_id is None
assert trade . open_rate == 0.00001099
2021-07-02 08:48:30 +00:00
assert trade . close_profit is None
assert trade . close_date is None
2021-07-04 06:11:59 +00:00
assert trade . borrowed == 0.0019999999998453998
assert log_has_re ( r " LIMIT_BUY has been fulfilled for Trade \ (id=2, "
r " pair=ETH/BTC, amount=272.97543219, open_rate=0.00001099, open_since=.* \ ). " ,
caplog )
caplog . clear ( )
# trade.open_order_id = 'something'
trade . update ( limit_leveraged_sell_order )
# assert trade.open_order_id is None
assert trade . close_rate == 0.00001173
assert trade . close_profit == round ( 0.18645514861995735 , 8 )
assert trade . close_date is not None
assert log_has_re ( r " LIMIT_SELL has been fulfilled for Trade \ (id=2, "
r " pair=ETH/BTC, amount=272.97543219, open_rate=0.00001099, open_since=.* \ ). " ,
caplog )
2021-07-02 08:48:30 +00:00
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_update_market_order_lev ( market_leveraged_buy_order , market_leveraged_sell_order , fee , caplog ) :
2021-07-02 08:48:30 +00:00
"""
10 minute leveraged market trade on Kraken at 3 x leverage
Short trade
fee : 0.25 % base
interest_rate : 0.05 % per 4 hrs
open_rate : 0.00004099 base
close_rate : 0.00004173 base
2021-07-04 06:11:59 +00:00
amount : = 275.97543219 crypto
2021-07-02 08:48:30 +00:00
stake_amount : 0.0037707443218227
borrowed : 0.0075414886436454 base
time - periods : 10 minutes ( rounds up to 1 time - period of 4 hrs )
interest : borrowed * interest_rate * time - periods
2021-07-04 06:11:59 +00:00
= 0.0075414886436454 * 0.0005 * 1 = 3.7707443218227e-06 crypto
2021-07-02 08:48:30 +00:00
open_value : ( amount * open_rate ) + ( amount * open_rate * fee )
= ( 275.97543219 * 0.00004099 ) + ( 275.97543219 * 0.00004099 * 0.0025 )
= 0.01134051354788177
2021-07-04 06:11:59 +00:00
close_value : ( amount_closed * close_rate ) - ( amount_closed * close_rate * fee )
= ( 275.97543219 * 0.00004173 ) - ( 275.97543219 * 0.00004173 * 0.0025 )
= 0.011487663648325479
total_profit = close_value - open_value - interest
= 0.011487663648325479 - 0.01134051354788177 - 3.7707443218227e-06
= 0.0001433793561218866
total_profit_percentage = total_profit / stake_amount
= 0.0001433793561218866 / 0.0037707443218227
= 0.03802415223225211
2021-07-02 08:48:30 +00:00
"""
trade = Trade (
2021-07-04 06:11:59 +00:00
id = 1 ,
2021-07-02 08:48:30 +00:00
pair = ' ETH/BTC ' ,
2021-07-04 06:11:59 +00:00
stake_amount = 0.0037707443218227 ,
2021-07-02 08:48:30 +00:00
amount = 5 ,
open_rate = 0.00004099 ,
2021-07-04 06:11:59 +00:00
is_open = True ,
2021-07-02 08:48:30 +00:00
fee_open = fee . return_value ,
fee_close = fee . return_value ,
2021-07-04 06:11:59 +00:00
open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 ) ,
2021-07-02 08:48:30 +00:00
interest_rate = 0.0005 ,
2021-07-06 03:48:56 +00:00
exchange = ' kraken ' ,
interest_mode = InterestMode . HOURSPER4
2021-07-02 08:48:30 +00:00
)
2021-07-04 06:11:59 +00:00
trade . open_order_id = ' something '
trade . update ( market_leveraged_buy_order )
assert trade . leverage == 3.0
assert trade . open_order_id is None
assert trade . open_rate == 0.00004099
assert trade . close_profit is None
assert trade . close_date is None
assert trade . interest_rate == 0.0005
# TODO: Uncomment the next assert and make it work.
# The logger also has the exact same but there's some spacing in there
assert log_has_re ( r " MARKET_BUY has been fulfilled for Trade \ (id=1, "
r " pair=ETH/BTC, amount=275.97543219, open_rate=0.00004099, open_since=.* \ ). " ,
caplog )
caplog . clear ( )
trade . is_open = True
trade . open_order_id = ' something '
trade . update ( market_leveraged_sell_order )
assert trade . open_order_id is None
assert trade . close_rate == 0.00004173
assert trade . close_profit == round ( 0.03802415223225211 , 8 )
assert trade . close_date is not None
# TODO: The amount should maybe be the opening amount + the interest
# TODO: Uncomment the next assert and make it work.
# The logger also has the exact same but there's some spacing in there
assert log_has_re ( r " MARKET_SELL has been fulfilled for Trade \ (id=1, "
r " pair=ETH/BTC, amount=275.97543219, open_rate=0.00004099, open_since=.* \ ). " ,
caplog )
2021-07-02 08:48:30 +00:00
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_calc_close_trade_price_exception_lev ( limit_leveraged_buy_order , fee ) :
2021-07-02 08:48:30 +00:00
trade = Trade (
pair = ' ETH/BTC ' ,
stake_amount = 0.001 ,
2021-07-04 06:11:59 +00:00
open_rate = 0.1 ,
2021-07-02 08:48:30 +00:00
amount = 5 ,
fee_open = fee . return_value ,
fee_close = fee . return_value ,
2021-07-04 06:11:59 +00:00
exchange = ' binance ' ,
2021-07-02 08:48:30 +00:00
interest_rate = 0.0005 ,
2021-07-06 03:48:56 +00:00
leverage = 3.0 ,
interest_mode = InterestMode . HOURSPERDAY
2021-07-02 08:48:30 +00:00
)
2021-07-04 06:11:59 +00:00
trade . open_order_id = ' something '
trade . update ( limit_leveraged_buy_order )
assert trade . calc_close_trade_value ( ) == 0.0
2021-07-02 08:48:30 +00:00
@pytest.mark.usefixtures ( " init_persistence " )
2021-07-06 04:01:46 +00:00
def test_calc_profit_lev ( market_leveraged_buy_order , market_leveraged_sell_order , fee ) :
2021-07-02 08:48:30 +00:00
"""
# TODO: Update this one
Leveraged trade on Kraken at 3 x leverage
fee : 0.25 % base or 0.3 %
interest_rate : 0.05 % , 0.25 % per 4 hrs
open_rate : 0.00004099 base
close_rate : 0.00004173 base
stake_amount : 0.0037707443218227
amount : 91.99181073 * leverage ( 3 ) = 275.97543219 crypto
borrowed : 0.0075414886436454 base
time - periods : 10 minutes ( rounds up to 1 time - period of 4 hrs )
5 hours = 5 / 4
interest : borrowed * interest_rate * time - periods
2021-07-04 06:11:59 +00:00
= 0.0075414886436454 * 0.0005 * 1 = 3.7707443218227e-06 crypto
2021-07-02 08:48:30 +00:00
= 0.0075414886436454 * 0.00025 * 5 / 4 = 2.3567152011391876e-06 crypto
2021-07-04 06:11:59 +00:00
= 0.0075414886436454 * 0.0005 * 5 / 4 = 4.713430402278375e-06 crypto
= 0.0075414886436454 * 0.00025 * 1 = 1.88537216091135e-06 crypto
2021-07-02 08:48:30 +00:00
open_value : ( amount * open_rate ) + ( amount * open_rate * fee )
= ( 275.97543219 * 0.00004099 ) + ( 275.97543219 * 0.00004099 * 0.0025 ) = 0.01134051354788177
2021-07-04 06:11:59 +00:00
close_value : ( amount_closed * close_rate ) - ( amount_closed * close_rate * fee ) - interest
( 275.97543219 * 0.00005374 ) - ( 275.97543219 * 0.00005374 * 0.0025 ) - 3.7707443218227e-06 = 0.01479007168225405
( 275.97543219 * 0.00000437 ) - ( 275.97543219 * 0.00000437 * 0.0025 ) - 2.3567152011391876e-06 = 0.001200640891872485
( 275.97543219 * 0.00005374 ) - ( 275.97543219 * 0.00005374 * 0.003 ) - 4.713430402278375e-06 = 0.014781713536310649
( 275.97543219 * 0.00000437 ) - ( 275.97543219 * 0.00000437 * 0.003 ) - 1.88537216091135e-06 = 0.0012005092285933775
2021-07-02 08:48:30 +00:00
total_profit = close_value - open_value
2021-07-04 06:11:59 +00:00
= 0.01479007168225405 - 0.01134051354788177 = 0.003449558134372281
= 0.001200640891872485 - 0.01134051354788177 = - 0.010139872656009285
= 0.014781713536310649 - 0.01134051354788177 = 0.0034411999884288794
= 0.0012005092285933775 - 0.01134051354788177 = - 0.010140004319288392
2021-07-02 08:48:30 +00:00
total_profit_percentage = total_profit / stake_amount
2021-07-04 06:11:59 +00:00
0.003449558134372281 / 0.0037707443218227 = 0.9148215418394732
- 0.010139872656009285 / 0.0037707443218227 = - 2.6890904793852157
0.0034411999884288794 / 0.0037707443218227 = 0.9126049646255184
- 0.010140004319288392 / 0.0037707443218227 = - 2.6891253964381554
2021-07-02 08:48:30 +00:00
"""
trade = Trade (
pair = ' ETH/BTC ' ,
2021-07-04 06:11:59 +00:00
stake_amount = 0.0037707443218227 ,
2021-07-02 08:48:30 +00:00
amount = 5 ,
open_rate = 0.00004099 ,
2021-07-04 06:11:59 +00:00
open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 ) ,
2021-07-02 08:48:30 +00:00
fee_open = fee . return_value ,
fee_close = fee . return_value ,
exchange = ' kraken ' ,
leverage = 3.0 ,
2021-07-06 03:48:56 +00:00
interest_rate = 0.0005 ,
interest_mode = InterestMode . HOURSPER4
2021-07-02 08:48:30 +00:00
)
trade . open_order_id = ' something '
trade . update ( market_leveraged_buy_order ) # Buy @ 0.00001099
# Custom closing rate and regular fee rate
# Higher than open rate
2021-07-04 06:11:59 +00:00
assert trade . calc_profit ( rate = 0.00005374 , interest_rate = 0.0005 ) == round (
0.003449558134372281 , 8 )
2021-07-02 08:48:30 +00:00
assert trade . calc_profit_ratio (
2021-07-04 06:11:59 +00:00
rate = 0.00005374 , interest_rate = 0.0005 ) == round ( 0.9148215418394732 , 8 )
2021-07-02 08:48:30 +00:00
# Lower than open rate
2021-07-04 06:11:59 +00:00
trade . open_date = datetime . utcnow ( ) - timedelta ( hours = 5 , minutes = 0 )
2021-07-02 08:48:30 +00:00
assert trade . calc_profit (
2021-07-04 06:11:59 +00:00
rate = 0.00000437 , interest_rate = 0.00025 ) == round ( - 0.010139872656009285 , 8 )
2021-07-02 08:48:30 +00:00
assert trade . calc_profit_ratio (
2021-07-04 06:11:59 +00:00
rate = 0.00000437 , interest_rate = 0.00025 ) == round ( - 2.6890904793852157 , 8 )
2021-07-02 08:48:30 +00:00
# Custom closing rate and custom fee rate
# Higher than open rate
2021-07-04 06:11:59 +00:00
assert trade . calc_profit ( rate = 0.00005374 , fee = 0.003 ,
interest_rate = 0.0005 ) == round ( 0.0034411999884288794 , 8 )
assert trade . calc_profit_ratio ( rate = 0.00005374 , fee = 0.003 ,
interest_rate = 0.0005 ) == round ( 0.9126049646255184 , 8 )
2021-07-02 08:48:30 +00:00
# Lower than open rate
2021-07-04 06:11:59 +00:00
trade . open_date = datetime . utcnow ( ) - timedelta ( hours = 0 , minutes = 10 )
2021-07-02 08:48:30 +00:00
assert trade . calc_profit ( rate = 0.00000437 , fee = 0.003 ,
2021-07-04 06:11:59 +00:00
interest_rate = 0.00025 ) == round ( - 0.010140004319288392 , 8 )
2021-07-02 08:48:30 +00:00
assert trade . calc_profit_ratio ( rate = 0.00000437 , fee = 0.003 ,
2021-07-04 06:11:59 +00:00
interest_rate = 0.00025 ) == round ( - 2.6891253964381554 , 8 )
2021-07-02 08:48:30 +00:00
# Test when we apply a Sell order. Sell higher than open rate @ 0.00001173
trade . update ( market_leveraged_sell_order )
assert trade . calc_profit ( ) == round ( 0.0001433793561218866 , 8 )
assert trade . calc_profit_ratio ( ) == round ( 0.03802415223225211 , 8 )
# Test with a custom fee rate on the close trade
# assert trade.calc_profit(fee=0.003) == 0.00006163
# assert trade.calc_profit_ratio(fee=0.003) == 0.06147824