Merge branch 'develop' of https://github.com/freqtrade/freqtrade into max-open-trades
# Conflicts: # freqtrade/optimize/backtesting.py
This commit is contained in:
@@ -2606,6 +2606,8 @@ def open_trade():
|
||||
ft_order_side='buy',
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=False,
|
||||
ft_amount=trade.amount,
|
||||
ft_price=trade.open_rate,
|
||||
order_id='123456789',
|
||||
status="closed",
|
||||
symbol=trade.pair,
|
||||
@@ -2642,6 +2644,8 @@ def open_trade_usdt():
|
||||
ft_order_side='buy',
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=False,
|
||||
ft_amount=trade.amount,
|
||||
ft_price=trade.open_rate,
|
||||
order_id='123456789',
|
||||
status="closed",
|
||||
symbol=trade.pair,
|
||||
@@ -2659,6 +2663,8 @@ def open_trade_usdt():
|
||||
ft_order_side='exit',
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=True,
|
||||
ft_amount=trade.amount,
|
||||
ft_price=trade.open_rate,
|
||||
order_id='123456789_exit',
|
||||
status="open",
|
||||
symbol=trade.pair,
|
||||
|
@@ -77,8 +77,8 @@ EXCHANGES = {
|
||||
'leverage_in_spot_market': True,
|
||||
},
|
||||
'huobi': {
|
||||
'pair': 'BTC/USDT',
|
||||
'stake_currency': 'USDT',
|
||||
'pair': 'ETH/BTC',
|
||||
'stake_currency': 'BTC',
|
||||
'hasQuoteVolume': True,
|
||||
'timeframe': '5m',
|
||||
'futures': False,
|
||||
|
@@ -82,7 +82,7 @@ def test_compute_distances(mocker, freqai_conf):
|
||||
freqai = make_data_dictionary(mocker, freqai_conf)
|
||||
freqai_conf['freqai']['feature_parameters'].update({"DI_threshold": 1})
|
||||
avg_mean_dist = freqai.dk.compute_distances()
|
||||
assert round(avg_mean_dist, 2) == 1.99
|
||||
assert round(avg_mean_dist, 2) == 1.98
|
||||
|
||||
|
||||
def test_use_SVM_to_remove_outliers_and_outlier_protection(mocker, freqai_conf, caplog):
|
||||
@@ -90,7 +90,7 @@ def test_use_SVM_to_remove_outliers_and_outlier_protection(mocker, freqai_conf,
|
||||
freqai_conf['freqai']['feature_parameters'].update({"outlier_protection_percentage": 0.1})
|
||||
freqai.dk.use_SVM_to_remove_outliers(predict=False)
|
||||
assert log_has_re(
|
||||
"SVM detected 7.36%",
|
||||
"SVM detected 7.83%",
|
||||
caplog,
|
||||
)
|
||||
|
||||
|
@@ -222,6 +222,9 @@ def test_start_backtesting(mocker, freqai_conf, model, num_files, strat, caplog)
|
||||
if 'test_4ac' in model:
|
||||
freqai_conf["freqaimodel_path"] = str(Path(__file__).parents[1] / "freqai" / "test_models")
|
||||
|
||||
freqai_conf.get("freqai", {}).get("feature_parameters", {}).update(
|
||||
{"indicator_periods_candles": [2]})
|
||||
|
||||
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
|
||||
exchange = get_patched_exchange(mocker, freqai_conf)
|
||||
strategy.dp = DataProvider(freqai_conf, exchange)
|
||||
@@ -232,15 +235,14 @@ def test_start_backtesting(mocker, freqai_conf, model, num_files, strat, caplog)
|
||||
timerange = TimeRange.parse_timerange("20180110-20180130")
|
||||
freqai.dd.load_all_pair_histories(timerange, freqai.dk)
|
||||
sub_timerange = TimeRange.parse_timerange("20180110-20180130")
|
||||
corr_df, base_df = freqai.dd.get_base_and_corr_dataframes(sub_timerange, "LTC/BTC", freqai.dk)
|
||||
_, base_df = freqai.dd.get_base_and_corr_dataframes(sub_timerange, "LTC/BTC", freqai.dk)
|
||||
df = base_df[freqai_conf["timeframe"]]
|
||||
|
||||
df = freqai.dk.use_strategy_to_populate_indicators(strategy, corr_df, base_df, "LTC/BTC")
|
||||
df = freqai.cache_corr_pairlist_dfs(df, freqai.dk)
|
||||
for i in range(5):
|
||||
df[f'%-constant_{i}'] = i
|
||||
|
||||
metadata = {"pair": "LTC/BTC"}
|
||||
freqai.start_backtesting(df, metadata, freqai.dk)
|
||||
freqai.start_backtesting(df, metadata, freqai.dk, strategy)
|
||||
model_folders = [x for x in freqai.dd.full_path.iterdir() if x.is_dir()]
|
||||
|
||||
assert len(model_folders) == num_files
|
||||
@@ -261,6 +263,8 @@ def test_start_backtesting_subdaily_backtest_period(mocker, freqai_conf):
|
||||
freqai_conf.update({"timerange": "20180120-20180124"})
|
||||
freqai_conf.get("freqai", {}).update({"backtest_period_days": 0.5})
|
||||
freqai_conf.get("freqai", {}).update({"save_backtest_models": True})
|
||||
freqai_conf.get("freqai", {}).get("feature_parameters", {}).update(
|
||||
{"indicator_periods_candles": [2]})
|
||||
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
|
||||
exchange = get_patched_exchange(mocker, freqai_conf)
|
||||
strategy.dp = DataProvider(freqai_conf, exchange)
|
||||
@@ -271,12 +275,11 @@ def test_start_backtesting_subdaily_backtest_period(mocker, freqai_conf):
|
||||
timerange = TimeRange.parse_timerange("20180110-20180130")
|
||||
freqai.dd.load_all_pair_histories(timerange, freqai.dk)
|
||||
sub_timerange = TimeRange.parse_timerange("20180110-20180130")
|
||||
corr_df, base_df = freqai.dd.get_base_and_corr_dataframes(sub_timerange, "LTC/BTC", freqai.dk)
|
||||
|
||||
df = freqai.dk.use_strategy_to_populate_indicators(strategy, corr_df, base_df, "LTC/BTC")
|
||||
_, base_df = freqai.dd.get_base_and_corr_dataframes(sub_timerange, "LTC/BTC", freqai.dk)
|
||||
df = base_df[freqai_conf["timeframe"]]
|
||||
|
||||
metadata = {"pair": "LTC/BTC"}
|
||||
freqai.start_backtesting(df, metadata, freqai.dk)
|
||||
freqai.start_backtesting(df, metadata, freqai.dk, strategy)
|
||||
model_folders = [x for x in freqai.dd.full_path.iterdir() if x.is_dir()]
|
||||
|
||||
assert len(model_folders) == 9
|
||||
@@ -287,6 +290,8 @@ def test_start_backtesting_subdaily_backtest_period(mocker, freqai_conf):
|
||||
def test_start_backtesting_from_existing_folder(mocker, freqai_conf, caplog):
|
||||
freqai_conf.update({"timerange": "20180120-20180130"})
|
||||
freqai_conf.get("freqai", {}).update({"save_backtest_models": True})
|
||||
freqai_conf.get("freqai", {}).get("feature_parameters", {}).update(
|
||||
{"indicator_periods_candles": [2]})
|
||||
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
|
||||
exchange = get_patched_exchange(mocker, freqai_conf)
|
||||
strategy.dp = DataProvider(freqai_conf, exchange)
|
||||
@@ -296,15 +301,14 @@ def test_start_backtesting_from_existing_folder(mocker, freqai_conf, caplog):
|
||||
freqai.dk = FreqaiDataKitchen(freqai_conf)
|
||||
timerange = TimeRange.parse_timerange("20180110-20180130")
|
||||
freqai.dd.load_all_pair_histories(timerange, freqai.dk)
|
||||
sub_timerange = TimeRange.parse_timerange("20180110-20180130")
|
||||
corr_df, base_df = freqai.dd.get_base_and_corr_dataframes(sub_timerange, "LTC/BTC", freqai.dk)
|
||||
|
||||
df = freqai.dk.use_strategy_to_populate_indicators(strategy, corr_df, base_df, "LTC/BTC")
|
||||
sub_timerange = TimeRange.parse_timerange("20180101-20180130")
|
||||
_, base_df = freqai.dd.get_base_and_corr_dataframes(sub_timerange, "LTC/BTC", freqai.dk)
|
||||
df = base_df[freqai_conf["timeframe"]]
|
||||
|
||||
pair = "ADA/BTC"
|
||||
metadata = {"pair": pair}
|
||||
freqai.dk.pair = pair
|
||||
freqai.start_backtesting(df, metadata, freqai.dk)
|
||||
freqai.start_backtesting(df, metadata, freqai.dk, strategy)
|
||||
model_folders = [x for x in freqai.dd.full_path.iterdir() if x.is_dir()]
|
||||
|
||||
assert len(model_folders) == 2
|
||||
@@ -322,14 +326,13 @@ def test_start_backtesting_from_existing_folder(mocker, freqai_conf, caplog):
|
||||
timerange = TimeRange.parse_timerange("20180110-20180130")
|
||||
freqai.dd.load_all_pair_histories(timerange, freqai.dk)
|
||||
sub_timerange = TimeRange.parse_timerange("20180110-20180130")
|
||||
corr_df, base_df = freqai.dd.get_base_and_corr_dataframes(sub_timerange, "LTC/BTC", freqai.dk)
|
||||
|
||||
df = freqai.dk.use_strategy_to_populate_indicators(strategy, corr_df, base_df, "LTC/BTC")
|
||||
_, base_df = freqai.dd.get_base_and_corr_dataframes(sub_timerange, "LTC/BTC", freqai.dk)
|
||||
df = base_df[freqai_conf["timeframe"]]
|
||||
|
||||
pair = "ADA/BTC"
|
||||
metadata = {"pair": pair}
|
||||
freqai.dk.pair = pair
|
||||
freqai.start_backtesting(df, metadata, freqai.dk)
|
||||
freqai.start_backtesting(df, metadata, freqai.dk, strategy)
|
||||
|
||||
assert log_has_re(
|
||||
"Found backtesting prediction file ",
|
||||
@@ -339,7 +342,7 @@ def test_start_backtesting_from_existing_folder(mocker, freqai_conf, caplog):
|
||||
pair = "ETH/BTC"
|
||||
metadata = {"pair": pair}
|
||||
freqai.dk.pair = pair
|
||||
freqai.start_backtesting(df, metadata, freqai.dk)
|
||||
freqai.start_backtesting(df, metadata, freqai.dk, strategy)
|
||||
|
||||
path = (freqai.dd.full_path / freqai.dk.backtest_predictions_folder)
|
||||
prediction_files = [x for x in path.iterdir() if x.is_file()]
|
||||
|
@@ -1870,11 +1870,13 @@ def test_get_exit_order_count(fee, is_short):
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_update_order_from_ccxt(caplog):
|
||||
# Most basic order return (only has orderid)
|
||||
o = Order.parse_from_ccxt_object({'id': '1234'}, 'ADA/USDT', 'buy')
|
||||
o = Order.parse_from_ccxt_object({'id': '1234'}, 'ADA/USDT', 'buy', 20.01, 1234.6)
|
||||
assert isinstance(o, Order)
|
||||
assert o.ft_pair == 'ADA/USDT'
|
||||
assert o.ft_order_side == 'buy'
|
||||
assert o.order_id == '1234'
|
||||
assert o.ft_price == 1234.6
|
||||
assert o.ft_amount == 20.01
|
||||
assert o.ft_is_open
|
||||
ccxt_order = {
|
||||
'id': '1234',
|
||||
@@ -1888,13 +1890,15 @@ def test_update_order_from_ccxt(caplog):
|
||||
'status': 'open',
|
||||
'timestamp': 1599394315123
|
||||
}
|
||||
o = Order.parse_from_ccxt_object(ccxt_order, 'ADA/USDT', 'buy')
|
||||
o = Order.parse_from_ccxt_object(ccxt_order, 'ADA/USDT', 'buy', 20.01, 1234.6)
|
||||
assert isinstance(o, Order)
|
||||
assert o.ft_pair == 'ADA/USDT'
|
||||
assert o.ft_order_side == 'buy'
|
||||
assert o.order_id == '1234'
|
||||
assert o.order_type == 'limit'
|
||||
assert o.price == 1234.5
|
||||
assert o.ft_price == 1234.6
|
||||
assert o.ft_amount == 20.01
|
||||
assert o.filled == 9
|
||||
assert o.remaining == 11
|
||||
assert o.order_date is not None
|
||||
@@ -2539,6 +2543,8 @@ def test_recalc_trade_from_orders_dca(data) -> None:
|
||||
ft_pair=trade.pair,
|
||||
order_id=f"order_{order[0]}_{idx}",
|
||||
ft_is_open=False,
|
||||
ft_amount=amount,
|
||||
ft_price=price,
|
||||
status="closed",
|
||||
symbol=trade.pair,
|
||||
order_type="market",
|
||||
|
@@ -39,6 +39,8 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool,
|
||||
order_id=f'{pair}-{trade.entry_side}-{trade.open_date}',
|
||||
ft_is_open=False,
|
||||
ft_pair=pair,
|
||||
ft_amount=trade.amount,
|
||||
ft_price=trade.open_rate,
|
||||
amount=trade.amount,
|
||||
filled=trade.amount,
|
||||
remaining=0,
|
||||
@@ -49,16 +51,19 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool,
|
||||
side=trade.entry_side,
|
||||
))
|
||||
if not is_open:
|
||||
close_price = open_rate * (2 - profit_rate if is_short else profit_rate)
|
||||
trade.orders.append(Order(
|
||||
ft_order_side=trade.exit_side,
|
||||
order_id=f'{pair}-{trade.exit_side}-{trade.close_date}',
|
||||
ft_is_open=False,
|
||||
ft_pair=pair,
|
||||
ft_amount=trade.amount,
|
||||
ft_price=trade.open_rate,
|
||||
amount=trade.amount,
|
||||
filled=trade.amount,
|
||||
remaining=0,
|
||||
price=open_rate * (2 - profit_rate if is_short else profit_rate),
|
||||
average=open_rate * (2 - profit_rate if is_short else profit_rate),
|
||||
price=close_price,
|
||||
average=close_price,
|
||||
status="closed",
|
||||
order_type="market",
|
||||
side=trade.exit_side,
|
||||
@@ -66,7 +71,7 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool,
|
||||
|
||||
trade.recalc_open_trade_value()
|
||||
if not is_open:
|
||||
trade.close(open_rate * (2 - profit_rate if is_short else profit_rate))
|
||||
trade.close(close_price)
|
||||
trade.exit_reason = exit_reason
|
||||
|
||||
Trade.query.session.add(trade)
|
||||
|
@@ -1,8 +1,6 @@
|
||||
"""
|
||||
Unit test file for rpc/api_server.py
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime, timedelta, timezone
|
||||
@@ -68,22 +66,23 @@ def botclient(default_conf, mocker):
|
||||
ApiServer.shutdown()
|
||||
|
||||
|
||||
def client_post(client, url, data={}):
|
||||
def client_post(client: TestClient, url, data={}):
|
||||
|
||||
return client.post(url,
|
||||
content=data,
|
||||
json=data,
|
||||
headers={'Authorization': _basic_auth_str(_TEST_USER, _TEST_PASS),
|
||||
'Origin': 'http://example.com',
|
||||
'content-type': 'application/json'
|
||||
})
|
||||
|
||||
|
||||
def client_get(client, url):
|
||||
def client_get(client: TestClient, url):
|
||||
# Add fake Origin to ensure CORS kicks in
|
||||
return client.get(url, headers={'Authorization': _basic_auth_str(_TEST_USER, _TEST_PASS),
|
||||
'Origin': 'http://example.com'})
|
||||
|
||||
|
||||
def client_delete(client, url):
|
||||
def client_delete(client: TestClient, url):
|
||||
# Add fake Origin to ensure CORS kicks in
|
||||
return client.delete(url, headers={'Authorization': _basic_auth_str(_TEST_USER, _TEST_PASS),
|
||||
'Origin': 'http://example.com'})
|
||||
@@ -561,7 +560,7 @@ def test_api_locks(botclient):
|
||||
assert rc.json()['lock_count'] == 1
|
||||
|
||||
rc = client_post(client, f"{BASE_URI}/locks/delete",
|
||||
data='{"pair": "XRP/BTC"}')
|
||||
data={"pair": "XRP/BTC"})
|
||||
assert_response(rc)
|
||||
assert rc.json()['lock_count'] == 0
|
||||
|
||||
@@ -1062,7 +1061,7 @@ def test_api_blacklist(botclient, mocker):
|
||||
|
||||
# Add ETH/BTC to blacklist
|
||||
rc = client_post(client, f"{BASE_URI}/blacklist",
|
||||
data='{"blacklist": ["ETH/BTC"]}')
|
||||
data={"blacklist": ["ETH/BTC"]})
|
||||
assert_response(rc)
|
||||
assert rc.json() == {"blacklist": ["DOGE/BTC", "HOT/BTC", "ETH/BTC"],
|
||||
"blacklist_expanded": ["ETH/BTC"],
|
||||
@@ -1072,7 +1071,7 @@ def test_api_blacklist(botclient, mocker):
|
||||
}
|
||||
|
||||
rc = client_post(client, f"{BASE_URI}/blacklist",
|
||||
data='{"blacklist": ["XRP/.*"]}')
|
||||
data={"blacklist": ["XRP/.*"]})
|
||||
assert_response(rc)
|
||||
assert rc.json() == {"blacklist": ["DOGE/BTC", "HOT/BTC", "ETH/BTC", "XRP/.*"],
|
||||
"blacklist_expanded": ["ETH/BTC", "XRP/BTC", "XRP/USDT"],
|
||||
@@ -1134,7 +1133,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
|
||||
ftbot, client = botclient
|
||||
|
||||
rc = client_post(client, f"{BASE_URI}/{endpoint}",
|
||||
data='{"pair": "ETH/BTC"}')
|
||||
data={"pair": "ETH/BTC"})
|
||||
assert_response(rc, 502)
|
||||
assert rc.json() == {"error": f"Error querying /api/v1/{endpoint}: Force_entry not enabled."}
|
||||
|
||||
@@ -1144,7 +1143,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
|
||||
fbuy_mock = MagicMock(return_value=None)
|
||||
mocker.patch("freqtrade.rpc.RPC._rpc_force_entry", fbuy_mock)
|
||||
rc = client_post(client, f"{BASE_URI}/{endpoint}",
|
||||
data='{"pair": "ETH/BTC"}')
|
||||
data={"pair": "ETH/BTC"})
|
||||
assert_response(rc)
|
||||
assert rc.json() == {"status": "Error entering long trade for pair ETH/BTC."}
|
||||
|
||||
@@ -1171,7 +1170,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
|
||||
mocker.patch("freqtrade.rpc.RPC._rpc_force_entry", fbuy_mock)
|
||||
|
||||
rc = client_post(client, f"{BASE_URI}/{endpoint}",
|
||||
data='{"pair": "ETH/BTC"}')
|
||||
data={"pair": "ETH/BTC"})
|
||||
assert_response(rc)
|
||||
assert rc.json() == {
|
||||
'amount': 1.0,
|
||||
@@ -1246,7 +1245,7 @@ def test_api_forceexit(botclient, mocker, ticker, fee, markets):
|
||||
patch_get_signal(ftbot)
|
||||
|
||||
rc = client_post(client, f"{BASE_URI}/forceexit",
|
||||
data='{"tradeid": "1"}')
|
||||
data={"tradeid": "1"})
|
||||
assert_response(rc, 502)
|
||||
assert rc.json() == {"error": "Error querying /api/v1/forceexit: invalid argument"}
|
||||
Trade.query.session.rollback()
|
||||
@@ -1255,7 +1254,7 @@ def test_api_forceexit(botclient, mocker, ticker, fee, markets):
|
||||
trade = Trade.get_trades([Trade.id == 5]).first()
|
||||
assert pytest.approx(trade.amount) == 123
|
||||
rc = client_post(client, f"{BASE_URI}/forceexit",
|
||||
data='{"tradeid": "5", "ordertype": "market", "amount": 23}')
|
||||
data={"tradeid": "5", "ordertype": "market", "amount": 23})
|
||||
assert_response(rc)
|
||||
assert rc.json() == {'result': 'Created sell order for trade 5.'}
|
||||
Trade.query.session.rollback()
|
||||
@@ -1265,7 +1264,7 @@ def test_api_forceexit(botclient, mocker, ticker, fee, markets):
|
||||
assert trade.is_open is True
|
||||
|
||||
rc = client_post(client, f"{BASE_URI}/forceexit",
|
||||
data='{"tradeid": "5"}')
|
||||
data={"tradeid": "5"})
|
||||
assert_response(rc)
|
||||
assert rc.json() == {'result': 'Created sell order for trade 5.'}
|
||||
Trade.query.session.rollback()
|
||||
@@ -1616,7 +1615,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
|
||||
"dry_run_wallet": 1000,
|
||||
"enable_protections": False
|
||||
}
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data))
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
|
||||
assert_response(rc)
|
||||
result = rc.json()
|
||||
|
||||
@@ -1667,7 +1666,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
|
||||
assert result['status'] == 'running'
|
||||
|
||||
# Post to backtest that's still running
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data))
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
|
||||
assert_response(rc, 502)
|
||||
result = rc.json()
|
||||
assert 'Bot Background task already running' in result['error']
|
||||
@@ -1675,7 +1674,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
|
||||
ApiServer._bgtask_running = False
|
||||
|
||||
# Rerun backtest (should get previous result)
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data))
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
|
||||
assert_response(rc)
|
||||
result = rc.json()
|
||||
assert log_has_re('Reusing result of previous backtest.*', caplog)
|
||||
@@ -1684,7 +1683,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
|
||||
|
||||
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest_one_strategy',
|
||||
side_effect=DependencyException())
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data))
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
|
||||
assert log_has("Backtesting caused an error: ", caplog)
|
||||
|
||||
# Delete backtesting to avoid leakage since the backtest-object may stick around.
|
||||
@@ -1698,7 +1697,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
|
||||
|
||||
# Disallow base64 strategies
|
||||
data['strategy'] = "xx:cHJpbnQoImhlbGxvIHdvcmxkIik="
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data))
|
||||
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
|
||||
assert_response(rc, 500)
|
||||
|
||||
|
||||
@@ -1766,7 +1765,7 @@ def test_api_ws_subscribe(botclient, mocker):
|
||||
assert sub_mock.call_count == 1
|
||||
|
||||
|
||||
def test_api_ws_requests(botclient, mocker, caplog):
|
||||
def test_api_ws_requests(botclient, caplog):
|
||||
caplog.set_level(logging.DEBUG)
|
||||
|
||||
ftbot, client = botclient
|
||||
|
@@ -253,6 +253,8 @@ def test_telegram_status_multi_entry(default_conf, update, mocker, fee) -> None:
|
||||
ft_order_side='buy',
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=False,
|
||||
ft_amount=trade.amount,
|
||||
ft_price=trade.open_rate,
|
||||
status="closed",
|
||||
symbol=trade.pair,
|
||||
order_type="market",
|
||||
|
@@ -1,11 +1,10 @@
|
||||
import logging
|
||||
from functools import reduce
|
||||
|
||||
import pandas as pd
|
||||
import talib.abstract as ta
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.strategy import IStrategy, merge_informative_pair
|
||||
from freqtrade.strategy import IStrategy
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -22,52 +21,39 @@ class freqai_rl_test_strat(IStrategy):
|
||||
process_only_new_candles = True
|
||||
stoploss = -0.05
|
||||
use_exit_signal = True
|
||||
startup_candle_count: int = 30
|
||||
startup_candle_count: int = 300
|
||||
can_short = False
|
||||
|
||||
def populate_any_indicators(
|
||||
self, pair, df, tf, informative=None, set_generalized_indicators=False
|
||||
):
|
||||
def feature_engineering_expand_all(self, dataframe, period, **kwargs):
|
||||
|
||||
if informative is None:
|
||||
informative = self.dp.get_pair_dataframe(pair, tf)
|
||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
||||
|
||||
# first loop is automatically duplicating indicators for time periods
|
||||
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
|
||||
return dataframe
|
||||
|
||||
t = int(t)
|
||||
informative[f"%-{pair}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
|
||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs):
|
||||
|
||||
# The following columns are necessary for RL models.
|
||||
informative[f"%-{pair}raw_close"] = informative["close"]
|
||||
informative[f"%-{pair}raw_open"] = informative["open"]
|
||||
informative[f"%-{pair}raw_high"] = informative["high"]
|
||||
informative[f"%-{pair}raw_low"] = informative["low"]
|
||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
||||
|
||||
indicators = [col for col in informative if col.startswith("%")]
|
||||
# This loop duplicates and shifts all indicators to add a sense of recency to data
|
||||
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
|
||||
if n == 0:
|
||||
continue
|
||||
informative_shift = informative[indicators].shift(n)
|
||||
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
|
||||
informative = pd.concat((informative, informative_shift), axis=1)
|
||||
return dataframe
|
||||
|
||||
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
|
||||
skip_columns = [
|
||||
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
|
||||
]
|
||||
df = df.drop(columns=skip_columns)
|
||||
def feature_engineering_standard(self, dataframe, **kwargs):
|
||||
|
||||
# Add generalized indicators here (because in live, it will call this
|
||||
# function to populate indicators during training). Notice how we ensure not to
|
||||
# add them multiple times
|
||||
if set_generalized_indicators:
|
||||
# For RL, there are no direct targets to set. This is filler (neutral)
|
||||
# until the agent sends an action.
|
||||
df["&-action"] = 0
|
||||
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
|
||||
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
|
||||
|
||||
return df
|
||||
dataframe["%-raw_close"] = dataframe["close"]
|
||||
dataframe["%-raw_open"] = dataframe["open"]
|
||||
dataframe["%-raw_high"] = dataframe["high"]
|
||||
dataframe["%-raw_low"] = dataframe["low"]
|
||||
|
||||
return dataframe
|
||||
|
||||
def set_freqai_targets(self, dataframe, **kwargs):
|
||||
|
||||
dataframe["&-action"] = 0
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
|
@@ -2,11 +2,10 @@ import logging
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import talib.abstract as ta
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy, merge_informative_pair
|
||||
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -57,55 +56,35 @@ class freqai_test_classifier(IStrategy):
|
||||
informative_pairs.append((pair, tf))
|
||||
return informative_pairs
|
||||
|
||||
def populate_any_indicators(
|
||||
self, pair, df, tf, informative=None, set_generalized_indicators=False
|
||||
):
|
||||
def feature_engineering_expand_all(self, dataframe, period, **kwargs):
|
||||
|
||||
coin = pair.split('/')[0]
|
||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
||||
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
|
||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||
|
||||
if informative is None:
|
||||
informative = self.dp.get_pair_dataframe(pair, tf)
|
||||
return dataframe
|
||||
|
||||
# first loop is automatically duplicating indicators for time periods
|
||||
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
|
||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs):
|
||||
|
||||
t = int(t)
|
||||
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
|
||||
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
|
||||
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
|
||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
||||
dataframe["%-raw_price"] = dataframe["close"]
|
||||
|
||||
informative[f"%-{coin}pct-change"] = informative["close"].pct_change()
|
||||
informative[f"%-{coin}raw_volume"] = informative["volume"]
|
||||
informative[f"%-{coin}raw_price"] = informative["close"]
|
||||
return dataframe
|
||||
|
||||
indicators = [col for col in informative if col.startswith("%")]
|
||||
# This loop duplicates and shifts all indicators to add a sense of recency to data
|
||||
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
|
||||
if n == 0:
|
||||
continue
|
||||
informative_shift = informative[indicators].shift(n)
|
||||
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
|
||||
informative = pd.concat((informative, informative_shift), axis=1)
|
||||
def feature_engineering_standard(self, dataframe, **kwargs):
|
||||
|
||||
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
|
||||
skip_columns = [
|
||||
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
|
||||
]
|
||||
df = df.drop(columns=skip_columns)
|
||||
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
|
||||
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
|
||||
|
||||
# Add generalized indicators here (because in live, it will call this
|
||||
# function to populate indicators during training). Notice how we ensure not to
|
||||
# add them multiple times
|
||||
if set_generalized_indicators:
|
||||
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
|
||||
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
|
||||
return dataframe
|
||||
|
||||
# user adds targets here by prepending them with &- (see convention below)
|
||||
# If user wishes to use multiple targets, a multioutput prediction model
|
||||
# needs to be used such as templates/CatboostPredictionMultiModel.py
|
||||
df['&s-up_or_down'] = np.where(df["close"].shift(-100) > df["close"], 'up', 'down')
|
||||
def set_freqai_targets(self, dataframe, **kwargs):
|
||||
|
||||
return df
|
||||
dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-100) >
|
||||
dataframe["close"], 'up', 'down')
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
|
@@ -2,11 +2,10 @@ import logging
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import talib.abstract as ta
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy, merge_informative_pair
|
||||
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -44,59 +43,38 @@ class freqai_test_multimodel_classifier_strat(IStrategy):
|
||||
)
|
||||
max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True)
|
||||
|
||||
def populate_any_indicators(
|
||||
self, pair, df, tf, informative=None, set_generalized_indicators=False
|
||||
):
|
||||
def feature_engineering_expand_all(self, dataframe, period, **kwargs):
|
||||
|
||||
coin = pair.split('/')[0]
|
||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
||||
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
|
||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||
|
||||
if informative is None:
|
||||
informative = self.dp.get_pair_dataframe(pair, tf)
|
||||
return dataframe
|
||||
|
||||
# first loop is automatically duplicating indicators for time periods
|
||||
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
|
||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs):
|
||||
|
||||
t = int(t)
|
||||
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
|
||||
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
|
||||
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
|
||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
||||
dataframe["%-raw_price"] = dataframe["close"]
|
||||
|
||||
informative[f"%-{coin}pct-change"] = informative["close"].pct_change()
|
||||
informative[f"%-{coin}raw_volume"] = informative["volume"]
|
||||
informative[f"%-{coin}raw_price"] = informative["close"]
|
||||
return dataframe
|
||||
|
||||
indicators = [col for col in informative if col.startswith("%")]
|
||||
# This loop duplicates and shifts all indicators to add a sense of recency to data
|
||||
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
|
||||
if n == 0:
|
||||
continue
|
||||
informative_shift = informative[indicators].shift(n)
|
||||
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
|
||||
informative = pd.concat((informative, informative_shift), axis=1)
|
||||
def feature_engineering_standard(self, dataframe, **kwargs):
|
||||
|
||||
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
|
||||
skip_columns = [
|
||||
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
|
||||
]
|
||||
df = df.drop(columns=skip_columns)
|
||||
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
|
||||
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
|
||||
|
||||
# Add generalized indicators here (because in live, it will call this
|
||||
# function to populate indicators during training). Notice how we ensure not to
|
||||
# add them multiple times
|
||||
if set_generalized_indicators:
|
||||
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
|
||||
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
|
||||
return dataframe
|
||||
|
||||
# user adds targets here by prepending them with &- (see convention below)
|
||||
# If user wishes to use multiple targets, a multioutput prediction model
|
||||
# needs to be used such as templates/CatboostPredictionMultiModel.py
|
||||
df['&s-up_or_down'] = np.where(df["close"].shift(-50) >
|
||||
df["close"], 'up', 'down')
|
||||
def set_freqai_targets(self, dataframe, **kwargs):
|
||||
|
||||
df['&s-up_or_down2'] = np.where(df["close"].shift(-50) >
|
||||
df["close"], 'up2', 'down2')
|
||||
dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-50) >
|
||||
dataframe["close"], 'up', 'down')
|
||||
|
||||
return df
|
||||
dataframe['&s-up_or_down2'] = np.where(dataframe["close"].shift(-50) >
|
||||
dataframe["close"], 'up2', 'down2')
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
|
@@ -1,11 +1,10 @@
|
||||
import logging
|
||||
from functools import reduce
|
||||
|
||||
import pandas as pd
|
||||
import talib.abstract as ta
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy, merge_informative_pair
|
||||
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -43,74 +42,53 @@ class freqai_test_multimodel_strat(IStrategy):
|
||||
)
|
||||
max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True)
|
||||
|
||||
def populate_any_indicators(
|
||||
self, pair, df, tf, informative=None, set_generalized_indicators=False
|
||||
):
|
||||
def feature_engineering_expand_all(self, dataframe, period, **kwargs):
|
||||
|
||||
coin = pair.split('/')[0]
|
||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
||||
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
|
||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||
|
||||
if informative is None:
|
||||
informative = self.dp.get_pair_dataframe(pair, tf)
|
||||
return dataframe
|
||||
|
||||
# first loop is automatically duplicating indicators for time periods
|
||||
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
|
||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs):
|
||||
|
||||
t = int(t)
|
||||
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
|
||||
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
|
||||
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
|
||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
||||
dataframe["%-raw_price"] = dataframe["close"]
|
||||
|
||||
informative[f"%-{coin}pct-change"] = informative["close"].pct_change()
|
||||
informative[f"%-{coin}raw_volume"] = informative["volume"]
|
||||
informative[f"%-{coin}raw_price"] = informative["close"]
|
||||
return dataframe
|
||||
|
||||
indicators = [col for col in informative if col.startswith("%")]
|
||||
# This loop duplicates and shifts all indicators to add a sense of recency to data
|
||||
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
|
||||
if n == 0:
|
||||
continue
|
||||
informative_shift = informative[indicators].shift(n)
|
||||
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
|
||||
informative = pd.concat((informative, informative_shift), axis=1)
|
||||
def feature_engineering_standard(self, dataframe, **kwargs):
|
||||
|
||||
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
|
||||
skip_columns = [
|
||||
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
|
||||
]
|
||||
df = df.drop(columns=skip_columns)
|
||||
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
|
||||
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
|
||||
|
||||
# Add generalized indicators here (because in live, it will call this
|
||||
# function to populate indicators during training). Notice how we ensure not to
|
||||
# add them multiple times
|
||||
if set_generalized_indicators:
|
||||
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
|
||||
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
|
||||
return dataframe
|
||||
|
||||
# user adds targets here by prepending them with &- (see convention below)
|
||||
# If user wishes to use multiple targets, a multioutput prediction model
|
||||
# needs to be used such as templates/CatboostPredictionMultiModel.py
|
||||
df["&-s_close"] = (
|
||||
df["close"]
|
||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.mean()
|
||||
/ df["close"]
|
||||
- 1
|
||||
def set_freqai_targets(self, dataframe, **kwargs):
|
||||
|
||||
dataframe["&-s_close"] = (
|
||||
dataframe["close"]
|
||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.mean()
|
||||
/ dataframe["close"]
|
||||
- 1
|
||||
)
|
||||
|
||||
df["&-s_range"] = (
|
||||
df["close"]
|
||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.max()
|
||||
-
|
||||
df["close"]
|
||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.min()
|
||||
)
|
||||
dataframe["&-s_range"] = (
|
||||
dataframe["close"]
|
||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.max()
|
||||
-
|
||||
dataframe["close"]
|
||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.min()
|
||||
)
|
||||
|
||||
return df
|
||||
return dataframe
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
|
@@ -1,11 +1,10 @@
|
||||
import logging
|
||||
from functools import reduce
|
||||
|
||||
import pandas as pd
|
||||
import talib.abstract as ta
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy, merge_informative_pair
|
||||
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -43,62 +42,41 @@ class freqai_test_strat(IStrategy):
|
||||
)
|
||||
max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True)
|
||||
|
||||
def populate_any_indicators(
|
||||
self, pair, df, tf, informative=None, set_generalized_indicators=False
|
||||
):
|
||||
def feature_engineering_expand_all(self, dataframe, period, **kwargs):
|
||||
|
||||
coin = pair.split('/')[0]
|
||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
||||
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
|
||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||
|
||||
if informative is None:
|
||||
informative = self.dp.get_pair_dataframe(pair, tf)
|
||||
return dataframe
|
||||
|
||||
# first loop is automatically duplicating indicators for time periods
|
||||
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
|
||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs):
|
||||
|
||||
t = int(t)
|
||||
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
|
||||
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
|
||||
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
|
||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
||||
dataframe["%-raw_price"] = dataframe["close"]
|
||||
|
||||
informative[f"%-{coin}pct-change"] = informative["close"].pct_change()
|
||||
informative[f"%-{coin}raw_volume"] = informative["volume"]
|
||||
informative[f"%-{coin}raw_price"] = informative["close"]
|
||||
return dataframe
|
||||
|
||||
indicators = [col for col in informative if col.startswith("%")]
|
||||
# This loop duplicates and shifts all indicators to add a sense of recency to data
|
||||
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
|
||||
if n == 0:
|
||||
continue
|
||||
informative_shift = informative[indicators].shift(n)
|
||||
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
|
||||
informative = pd.concat((informative, informative_shift), axis=1)
|
||||
def feature_engineering_standard(self, dataframe, **kwargs):
|
||||
|
||||
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
|
||||
skip_columns = [
|
||||
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
|
||||
]
|
||||
df = df.drop(columns=skip_columns)
|
||||
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
|
||||
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
|
||||
|
||||
# Add generalized indicators here (because in live, it will call this
|
||||
# function to populate indicators during training). Notice how we ensure not to
|
||||
# add them multiple times
|
||||
if set_generalized_indicators:
|
||||
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
|
||||
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
|
||||
return dataframe
|
||||
|
||||
# user adds targets here by prepending them with &- (see convention below)
|
||||
# If user wishes to use multiple targets, a multioutput prediction model
|
||||
# needs to be used such as templates/CatboostPredictionMultiModel.py
|
||||
df["&-s_close"] = (
|
||||
df["close"]
|
||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.mean()
|
||||
/ df["close"]
|
||||
- 1
|
||||
def set_freqai_targets(self, dataframe, **kwargs):
|
||||
|
||||
dataframe["&-s_close"] = (
|
||||
dataframe["close"]
|
||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||
.mean()
|
||||
/ dataframe["close"]
|
||||
- 1
|
||||
)
|
||||
|
||||
return df
|
||||
return dataframe
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
|
@@ -1168,6 +1168,8 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
|
||||
order_id='100',
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=True,
|
||||
ft_amount=trade.amount,
|
||||
ft_price=0.0,
|
||||
))
|
||||
assert trade
|
||||
|
||||
@@ -4615,6 +4617,7 @@ def test_get_real_amount_open_trade_usdt(default_conf_usdt, fee, mocker):
|
||||
'amount': amount,
|
||||
'status': 'open',
|
||||
'side': 'buy',
|
||||
'price': 0.245441,
|
||||
}
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
order_obj = Order.parse_from_ccxt_object(order, 'LTC/ETH', 'buy')
|
||||
|
Reference in New Issue
Block a user