Files
jesse-trading/tests/test_helpers.py
2022-02-07 08:12:06 +01:00

583 lines
17 KiB
Python

import os
import arrow
import numpy as np
import pytest
import jesse.helpers as jh
def test_app_currency():
from jesse.routes import router
from jesse.enums import exchanges, timeframes
router.initiate(
[{'exchange': exchanges.BITFINEX, 'symbol': 'ETH-USD', 'timeframe': timeframes.HOUR_3, 'strategy': 'Test19'}])
assert jh.app_currency() == 'USD'
def test_app_mode():
assert jh.app_mode() == 'backtest'
def test_arrow_to_timestamp():
arrow_time = arrow.get('2015-08-01')
assert jh.arrow_to_timestamp(arrow_time) == 1438387200000
def test_base_asset():
assert jh.base_asset('BTC-USDT') == 'BTC'
assert jh.base_asset('BTC-USD') == 'BTC'
assert jh.base_asset('DEFI-USDT') == 'DEFI'
assert jh.base_asset('DEFI-USD') == 'DEFI'
def test_binary_search():
arr = [0, 11, 22, 33, 44, 54, 55]
assert jh.binary_search(arr, 22) == 2
assert jh.binary_search(arr, 222) == -1
def test_clean_orderbook_list():
assert np.array_equal(
jh.clean_orderbook_list([
['10', '11'],
['11', '14'],
['12', '13'],
['13', '133'],
['14', '12'],
]),
[
[10, 11],
[11, 14],
[12, 13],
[13, 133],
[14, 12],
]
)
def test_color():
msg_text = 'msg'
msg_color = 'black'
assert jh.color(msg_text, msg_color) == '\x1b[30mmsg\x1b[0m'
def test_convert_number():
old_max = 119
old_min = 40
new_max = 4.0
new_min = 0.5
old_value = 41
assert jh.convert_number(old_max, old_min, new_max, new_min, old_value) == 0.5443037974683544
def test_dashless_symbol():
assert jh.dashless_symbol('BTC-USD') == 'BTCUSD'
assert jh.dashless_symbol('BTC-USDT') == 'BTCUSDT'
assert jh.dashless_symbol('1INCH-USDT') == '1INCHUSDT'
assert jh.dashless_symbol('SC-USDT') == 'SCUSDT'
# make sure that it works even if it's already dashless
assert jh.dashless_symbol('BTCUSDT') == 'BTCUSDT'
def test_dashy_symbol():
assert jh.dashy_symbol('BTCUSD') == 'BTC-USD'
assert jh.dashy_symbol('BTCUSDT') == 'BTC-USDT'
assert jh.dashy_symbol('BTC-USDT') == 'BTC-USDT'
def test_date_diff_in_days():
date_1 = arrow.get('2015-12-23 18:40:48', 'YYYY-MM-DD HH:mm:ss')
date_2 = arrow.get('2017-11-15 13:18:20', 'YYYY-MM-DD HH:mm:ss')
diff = jh.date_diff_in_days(date_1, date_2)
assert diff == 692
def test_date_to_timestamp():
assert jh.date_to_timestamp('2015-08-01') == 1438387200000
def test_dna_to_hp():
strategy_hp = [
{'name': 'hp1', 'type': float, 'min': 0.01, 'max': 1.0, 'default': 0.09},
{'name': 'hp2', 'type': int, 'min': 1, 'max': 10, 'default': 2},
]
dna = ".6"
assert jh.dna_to_hp(strategy_hp, dna) == {'hp1': 0.08518987341772151, 'hp2': 3}
def test_dump_exception():
# uses database, which is not existing during testing
pass
def test_estimate_average_price():
assert jh.estimate_average_price(100, 7200, 0, 0) == 7200
with pytest.raises(TypeError):
jh.estimate_average_price(100, 7200, 0, None)
jh.estimate_average_price(100, 7200, None, 0)
jh.estimate_average_price(100, None, 0, 0)
jh.estimate_average_price(None, 7200, 0, 0)
def test_estimate_PNL():
# profit
assert jh.estimate_PNL(2, 50, 60, 'long') == 20
assert jh.estimate_PNL(2, 60, 50, 'short') == 20
# loss
assert jh.estimate_PNL(2, 50, 60, 'short') == -20
assert jh.estimate_PNL(2, 60, 50, 'long') == -20
# profit with fee
assert jh.estimate_PNL(1, 10, 20, 'long', 0.002) == 9.94
# loss with fee
assert jh.estimate_PNL(1, 10, 20, 'short', 0.002) == -10.06
with pytest.raises(TypeError):
jh.estimate_PNL(1, 200, 220, 1)
jh.estimate_PNL(1, 200, 'invalid_input', 'short')
jh.estimate_PNL(1, 'invalid_input', 220, 'short')
jh.estimate_PNL('invalid_input', 200, 220, 'short')
def test_estimate_PNL_percentage():
# profit
assert jh.estimate_PNL_percentage(1, 200, 220, 'long') == 10
assert jh.estimate_PNL_percentage(1, 200, 180, 'short') == 10
# loss
assert jh.estimate_PNL_percentage(1, 200, 180, 'long') == -10
assert jh.estimate_PNL_percentage(1, 200, 220, 'short') == -10
with pytest.raises(TypeError):
jh.estimate_PNL_percentage(1, 200, 220, 1)
jh.estimate_PNL_percentage(1, 200, 'invalid_input', 'short')
jh.estimate_PNL_percentage(1, 'invalid_input', 220, 'short')
jh.estimate_PNL_percentage('invalid_input', 200, 220, 'short')
def test_file_exists():
assert jh.file_exists('tests/test_helpers.py') is True
def test_floor_with_precision():
assert jh.floor_with_precision(1.123) == 1
assert jh.floor_with_precision(1.123, 1) == 1.1
assert jh.floor_with_precision(1.123, 2) == 1.12
assert jh.floor_with_precision(1.123, 3) == 1.123
assert jh.floor_with_precision(1.123, 4) == 1.123
def test_format_currency():
assert jh.format_currency(100_000_000) == '100,000,000'
assert jh.format_currency(100_000_000.23) == '100,000,000.23'
def test_generate_unique_id():
assert jh.is_valid_uuid(jh.generate_unique_id()) is True
assert jh.is_valid_uuid('asdfasdfasdfasfsadfsd') is False
def test_get_candle_source():
candle = np.array(([1575547200000, 146.51, 147.03, 149.02, 146.51, 64788.46651],
[1553817660000, 4092.56783507, 4092.5, 4092.56783507, 4092.5, 9.0847059]))
close = jh.get_candle_source(candle, source_type="close")
assert close[-1] == 4092.5
high = jh.get_candle_source(candle, source_type="high")
assert high[-1] == 4092.56783507
low = jh.get_candle_source(candle, source_type="low")
assert low[-1] == 4092.5
open = jh.get_candle_source(candle, source_type="open")
assert open[-1] == 4092.56783507
volume = jh.get_candle_source(candle, source_type="volume")
assert volume[-1] == 9.0847059
hl2 = jh.get_candle_source(candle, source_type="hl2")
assert hl2[-1] == 4092.533917535
hlc3 = jh.get_candle_source(candle, source_type="hlc3")
assert hlc3[-1] == 4092.52261169
ohlc4 = jh.get_candle_source(candle, source_type="ohlc4")
assert ohlc4[-1] == 4092.533917535
def test_get_config(monkeypatch):
# assert when config does NOT exist (must return passed default)
assert jh.get_config('aaaaaaa', 2020) == 2020
# assert when config does exist
assert jh.get_config('env.logging.order_submission', 2020) is True
# assert env is took
monkeypatch.setenv("ENV_DATABASES_POSTGRES_HOST", "db")
assert jh.get_config('env.databases.postgres_host', 'default') == 'db'
monkeypatch.delenv("ENV_DATABASES_POSTGRES_HOST")
# assert env is took with space
monkeypatch.setenv("ENV_EXCHANGES_BINANCE_FUTURES_SETTLEMENT_CURRENCY", 'BUSD')
assert jh.get_config('env.exchanges.Binance Futures.settlement_currency', 'USDT') == 'BUSD'
monkeypatch.delenv("ENV_EXCHANGES_BINANCE_FUTURES_SETTLEMENT_CURRENCY")
def test_get_strategy_class():
from jesse.strategies import Strategy
assert issubclass(jh.get_strategy_class("Test01"), Strategy)
def test_insecure_hash():
assert jh.insecure_hash("test") == "098f6bcd4621d373cade4e832627b4f6"
def test_insert_list():
my_list = [0, 1, 2, 3]
assert jh.insert_list(2, 22, my_list) == [0, 1, 22, 2, 3]
assert jh.insert_list(0, 22, my_list) == [22, 0, 1, 2, 3]
assert jh.insert_list(-1, 22, my_list) == [0, 1, 2, 3, 22]
# assert list is untouched
assert my_list == [0, 1, 2, 3]
def test_is_backtesting():
assert jh.is_backtesting() is True
def test_is_collecting_data():
assert jh.is_collecting_data() is False
def test_is_debuggable():
debug_item = 'order_submission'
assert jh.is_debuggable(debug_item) is False
def test_is_debugging():
assert jh.is_debugging() is False
def test_is_importing_candles():
assert jh.is_importing_candles() is False
def test_is_live():
assert jh.is_live() is False
def test_is_livetrading():
assert jh.is_livetrading() is False
def test_is_optimizing():
assert jh.is_optimizing() is False
def test_is_paper_trading():
assert jh.is_paper_trading() is False
def test_is_test_driving():
assert jh.is_test_driving() is False
def test_is_unit_testing():
assert jh.is_unit_testing() is True
def test_key():
exchange = "Exchange"
symbol = "BTC-USD"
timeframe = "6h"
assert jh.key(exchange, symbol) == "Exchange-BTC-USD"
assert jh.key(exchange, symbol, timeframe) == "Exchange-BTC-USD-6h"
def test_max_timeframe():
assert jh.max_timeframe(['1m', '3m']) == '3m'
assert jh.max_timeframe(['3m', '5m']) == '5m'
assert jh.max_timeframe(['15m', '5m']) == '15m'
assert jh.max_timeframe(['30m', '15m']) == '30m'
assert jh.max_timeframe(['30m', '1h']) == '1h'
assert jh.max_timeframe(['1h', '2h']) == '2h'
assert jh.max_timeframe(['2h', '3h']) == '3h'
assert jh.max_timeframe(['4h', '3h']) == '4h'
assert jh.max_timeframe(['6h', '4h']) == '6h'
assert jh.max_timeframe(['8h', '4h']) == '8h'
assert jh.max_timeframe(['6h', '1D']) == '1D'
def test_normalize():
assert jh.normalize(10, 0, 20) == 0.5
assert jh.normalize(20, 0, 20) == 1
assert jh.normalize(0, 0, 20) == 0
def test_now_to_timestamp():
from jesse.store import store
assert jh.now_to_timestamp() == store.app.time
def test_np_ffill():
arr = np.array([0, 1, np.nan, np.nan])
res = jh.np_ffill(arr)
expected = np.array([0, 1, 1, 1])
np.equal(res, expected)
def test_np_shift():
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
res = jh.np_shift(arr, -3)
expected = np.array([4, 5, 6, 7, 8, 9, 0, 0, 0])
np.equal(res, expected)
def test_opposite_side():
assert jh.opposite_side('buy') == 'sell'
assert jh.opposite_side('sell') == 'buy'
def test_opposite_type():
assert jh.opposite_type('long') == 'short'
assert jh.opposite_type('short') == 'long'
def test_orderbook_insertion_index_search():
ascending_arr = [
[10, 232],
[11, 33232],
[12, 233],
[33, 21323],
[44, 23123],
[55, 2321],
[66, 23213]
]
assert jh.orderbook_insertion_index_search(ascending_arr, [7, 2]) == (False, 0)
assert jh.orderbook_insertion_index_search(ascending_arr, [2, 2]) == (False, 0)
assert jh.orderbook_insertion_index_search(ascending_arr, [32, 2]) == (False, 3)
assert jh.orderbook_insertion_index_search(ascending_arr, [34, 2]) == (False, 4)
assert jh.orderbook_insertion_index_search(ascending_arr, [1, 2]) == (False, 0)
assert jh.orderbook_insertion_index_search(ascending_arr, [66, 2]) == (True, 6)
assert jh.orderbook_insertion_index_search(ascending_arr, [77, 2]) == (False, 7)
descending_arr = [
[66, 232],
[55, 33232],
[44, 233],
[33, 21323],
[2, 23123],
]
assert jh.orderbook_insertion_index_search(descending_arr, [77, 2], ascending=False) == (False, 0)
assert jh.orderbook_insertion_index_search(descending_arr, [2, 2], ascending=False) == (True, 4)
assert jh.orderbook_insertion_index_search(descending_arr, [65, 2], ascending=False) == (False, 1)
assert jh.orderbook_insertion_index_search(descending_arr, [1, 2], ascending=False) == (False, 5)
def test_orderbook_trim_price():
# bids
assert jh.orderbook_trim_price(101.12, False, .1) == 101.1
assert jh.orderbook_trim_price(101.1, False, .1) == 101.1
assert jh.orderbook_trim_price(10.12, False, .01) == 10.12
assert jh.orderbook_trim_price(10.1, False, .01) == 10.1
assert jh.orderbook_trim_price(10.122, False, .01) == 10.12
assert jh.orderbook_trim_price(1.1223, False, .001) == 1.122
# asks
assert jh.orderbook_trim_price(101.12, True, .1) == 101.2
assert jh.orderbook_trim_price(101.1, True, .1) == 101.1
assert jh.orderbook_trim_price(10.12, True, .01) == 10.12
assert jh.orderbook_trim_price(10.122, True, .01) == 10.13
assert jh.orderbook_trim_price(1.1223, True, .001) == 1.123
def test_prepare_qty():
assert jh.prepare_qty(10, 'sell') == -10
assert jh.prepare_qty(-10, 'buy') == 10
with pytest.raises(ValueError):
jh.prepare_qty(-10, 'invalid_input')
def test_python_version():
import sys
assert jh.python_version() == sys.version_info[:2]
def test_quote_asset():
assert jh.quote_asset('BTC-USDT') == 'USDT'
assert jh.quote_asset('DEFI-USDT') == 'USDT'
assert jh.quote_asset('DEFI-EUR') == 'EUR'
def test_random_str():
assert len(jh.random_str(10)) == 10
def test_readable_duration():
assert jh.readable_duration(604312) == "6 days, 23 hours"
def test_relative_to_absolute():
from pathlib import Path
assert jh.relative_to_absolute("tests/test_helpers.py") == str(Path(__file__).absolute())
def test_round_price_for_live_mode():
np.testing.assert_equal(
jh.round_price_for_live_mode(np.array([0.0003209123456, 0.0004209123456]), 7),
np.array([0.0003209, 0.0004209])
)
def test_round_qty_for_live_mode():
np.testing.assert_equal(
jh.round_qty_for_live_mode(np.array([100.3209123456, 100.4299123456]), 2),
np.array([100.32, 100.42])
)
np.testing.assert_equal(
jh.round_qty_for_live_mode(np.array([0]), 1),
np.array([0.1])
)
np.testing.assert_equal(
jh.round_qty_for_live_mode(np.array([0]), 2),
np.array([0.01])
)
np.testing.assert_equal(
jh.round_qty_for_live_mode(np.array([0]), 3),
np.array([0.001])
)
def test_round_decimals_down():
assert jh.round_decimals_down(100.329, 2) == 100.32
def test_secure_hash():
assert jh.secure_hash('test') == "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
def test_should_execute_silently():
assert jh.should_execute_silently() is True
def test_side_to_type():
assert jh.side_to_type("buy") == "long"
assert jh.side_to_type("sell") == "short"
# make sure title case works as well
assert jh.side_to_type("Buy") == "long"
assert jh.side_to_type("Sell") == "short"
def test_string_after_character():
assert jh.string_after_character('btcusdt@bookTicker', '@') == 'bookTicker'
assert jh.string_after_character('9000|24628', '|') == '24628'
def test_style():
assert jh.style('test', 'bold') == "\x1b[1mtest\x1b[0m"
assert jh.style('test', 'u') == "\x1b[4mtest\x1b[0m"
def test_terminate_app():
# uses database, which is not existing during testing
pass
def test_timeframe_to_one_minutes():
assert jh.timeframe_to_one_minutes('1m') == 1
assert jh.timeframe_to_one_minutes('3m') == 3
assert jh.timeframe_to_one_minutes('5m') == 5
assert jh.timeframe_to_one_minutes('15m') == 15
assert jh.timeframe_to_one_minutes('30m') == 30
assert jh.timeframe_to_one_minutes('1h') == 60
assert jh.timeframe_to_one_minutes('2h') == 60 * 2
assert jh.timeframe_to_one_minutes('3h') == 60 * 3
assert jh.timeframe_to_one_minutes('4h') == 60 * 4
assert jh.timeframe_to_one_minutes('6h') == 60 * 6
assert jh.timeframe_to_one_minutes('8h') == 60 * 8
assert jh.timeframe_to_one_minutes('1D') == 60 * 24
def test_timestamp_to_arrow():
arrow_time = arrow.get('2015-08-01')
assert jh.timestamp_to_arrow(1438387200000) == arrow_time
def test_timestamp_to_date():
assert jh.timestamp_to_date(1438387200000) == "2015-08-01"
def test_timestamp_to_time():
assert jh.timestamp_to_time(1558770180000) == '2019-05-25T07:43:00+00:00'
def test_today_to_timestamp():
assert jh.today_to_timestamp() == arrow.utcnow().floor('day').int_timestamp * 1000
def test_type_to_side():
assert jh.type_to_side('long') == 'buy'
assert jh.type_to_side('short') == 'sell'
def test_unique_list():
a = [
('Binance', 'BTC', '1m'),
('Binance', 'BTC', '5m'),
('Binance', 'BTC', '15m'),
('Binance', 'BTC', '5m'),
('Binance', 'BTC', '1m'),
('Binance', 'BTC', '15m'),
]
expected = [
('Binance', 'BTC', '1m'),
('Binance', 'BTC', '5m'),
('Binance', 'BTC', '15m'),
]
assert jh.unique_list(a) == expected
def test_closing_side():
assert jh.closing_side('Long') == 'sell'
assert jh.closing_side('Short') == 'buy'
def test_merge_dicts():
client = {
'extra': {
'name': 'Saleh',
'new_key': 12
},
'age': 28
}
server = {
'extra': {
'name': 'Ocean',
'water': 100
},
}
expected_result = {'age': 28, 'extra': {'name': 'Ocean', 'water': 100, 'new_key': 12}}
assert expected_result == jh.merge_dicts(client, server)
def test_get_pid():
assert os.getpid() == jh.get_pid()
def test_convert_to_env_name():
assert jh.convert_to_env_name('Testnet Binance Futures') == 'TESTNET_BINANCE_FUTURES'
assert jh.convert_to_env_name('Testnet Binance') == 'TESTNET_BINANCE'