删掉策略和配置
This commit is contained in:
parent
a7fc495113
commit
ae7fea6dc0
@ -1,121 +0,0 @@
|
||||
diff --git a/config_examples/config_freqai.okx.json b/config_examples/config_freqai.okx.json
|
||||
index 259459e..c2693fc 100644
|
||||
--- a/config_examples/config_freqai.okx.json
|
||||
+++ b/config_examples/config_freqai.okx.json
|
||||
@@ -5,11 +5,10 @@
|
||||
"max_open_trades": 4,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
- "startup_candle_count": 30,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
- "timeframe": "5m",
|
||||
+ "timeframe": "3m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.05,
|
||||
@@ -24,21 +23,21 @@
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
- "rateLimit": 800,
|
||||
+ "rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
- "rateLimit": 800,
|
||||
+ "rateLimit": 500,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
- "OKB/USDT",
|
||||
- "DOT/USDT",
|
||||
+ "BTC/USDT",
|
||||
"SOL/USDT"
|
||||
- ]
|
||||
+ ],
|
||||
+ "pair_blacklist": []
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
@@ -65,47 +64,37 @@
|
||||
"data_kitchen": {
|
||||
"fillna": "ffill"
|
||||
},
|
||||
- "freqaimodel": "CatboostClassifier",
|
||||
- "purge_old_models": 2,
|
||||
- "identifier": "test175",
|
||||
- "train_period_days": 30,
|
||||
- "backtest_period_days": 10,
|
||||
+ "freqaimodel": "XGBoostRegressor",
|
||||
+ "model_training_parameters": {
|
||||
+ "n_estimators": 100,
|
||||
+ "learning_rate": 0.05,
|
||||
+ "max_depth": 5
|
||||
+ },
|
||||
+ "train_period_days": 180,
|
||||
+ "backtest_period_days": 60,
|
||||
"live_retrain_hours": 0,
|
||||
"feature_selection": {
|
||||
"method": "recursive_elimination"
|
||||
},
|
||||
"feature_parameters": {
|
||||
- "include_timeframes": [
|
||||
- "5m",
|
||||
- "1h"
|
||||
- ],
|
||||
- "include_corr_pairlist": [
|
||||
- "BTC/USDT",
|
||||
- "ETH/USDT"
|
||||
- ],
|
||||
- "label_period_candles": 12,
|
||||
- "include_shifted_candles": 3,
|
||||
- "DI_threshold": 0.9,
|
||||
+ "include_timeframes": ["15m"],
|
||||
+ "include_corr_pairlist": ["BTC/USDT"],
|
||||
+ "label_period_candles": 10,
|
||||
+ "include_shifted_candles": 1,
|
||||
+
|
||||
"weight_factor": 0.9,
|
||||
"principal_component_analysis": false,
|
||||
"use_SVM_to_remove_outliers": false,
|
||||
- "indicator_periods_candles": [
|
||||
- 10,
|
||||
- 20,
|
||||
- 50
|
||||
- ],
|
||||
- "plot_feature_importances": 0
|
||||
+ "indicator_periods_candles": [14],
|
||||
},
|
||||
"data_split_parameters": {
|
||||
- "test_size": 0.2,
|
||||
- "shuffle": false,
|
||||
+ "test_size": 0.2
|
||||
},
|
||||
- "model_training_parameters": {
|
||||
- "n_estimators": 100,
|
||||
- "learning_rate": 0.1,
|
||||
- "num_leaves": 15,
|
||||
- "verbose": -1
|
||||
- }
|
||||
+ "model_training_parameters": {
|
||||
+ "n_estimators": 100,
|
||||
+ "learning_rate": 0.05,
|
||||
+ "max_depth": 5
|
||||
+ }
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
@@ -123,7 +112,7 @@
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
- "process_throttle_secs": 10,
|
||||
+ "process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "DEBUG"
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
{
|
||||
"max_open_trades": 3,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"startup_candle_count": 30,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
"timeframe": "3m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.05,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15
|
||||
},
|
||||
"timeframe": "5m",
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "your_api_key",
|
||||
"secret": "your_api_secret",
|
||||
"password": "your_api_password",
|
||||
"type": "spot",
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"BTC/USDT",
|
||||
"SOL/USDT"
|
||||
],
|
||||
"pair_blacklist": []
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"strategy": "AIEnhancedStrategy",
|
||||
"freqai": {
|
||||
"enabled": true,
|
||||
"live_retrain_hours": 1,
|
||||
"data_kitchen_path": "freqai/data_kitchen/",
|
||||
"purge_old_data_seconds": 86400,
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["5m", "15m", "1h"],
|
||||
"include_corr_pairlist": ["BTC/USDT", "ETH/USDT"],
|
||||
"include_shifted_candles": 2,
|
||||
"indicator_periods_candles": [10, 20, 50],
|
||||
"plot_feature_importances": 1,
|
||||
"DI_threshold": 0.85,
|
||||
"label_period_candles": 20,
|
||||
"include_volume_data": true,
|
||||
"include_bidirectional_training_data": true
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": true,
|
||||
"random_state": 42
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 200,
|
||||
"learning_rate": 0.05,
|
||||
"max_depth": 5,
|
||||
"subsample": 0.8,
|
||||
"colsample_bytree": 0.8,
|
||||
"objective": "reg:squarederror",
|
||||
"eval_metric": "rmse",
|
||||
"early_stopping_rounds": 50,
|
||||
"verbose": 0
|
||||
}
|
||||
},
|
||||
"dry_run": true,
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": false,
|
||||
"internals": {
|
||||
"process_only_new_candles": true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
{
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "your_api_key",
|
||||
"secret": "your_api_secret",
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"defaultType": "spot",
|
||||
"rateLimit": 2000,
|
||||
"timeout": 30000
|
||||
},
|
||||
"pair_whitelist": ["OKB/USDT", "SOL/USDT"]
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"timeframe": "3m",
|
||||
"strategy": "",
|
||||
"order_types": {
|
||||
"entry": "market",
|
||||
"exit": "market",
|
||||
"stoploss": "limit",
|
||||
"stoploss_on_exchange": false
|
||||
},
|
||||
"order_time_in_force": {
|
||||
"entry": "gtc",
|
||||
"exit": "gtc"
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": false,
|
||||
"price_last_balance": 0.0
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": false
|
||||
},
|
||||
"use_exit_signal": true,
|
||||
"exit_profit_only": false,
|
||||
"ignore_roi_if_entry_signal": false,
|
||||
"stoploss": -0.05,
|
||||
"minimal_roi": {
|
||||
"0": 0.06,
|
||||
"30": 0.04,
|
||||
"60": 0.02,
|
||||
"120": 0
|
||||
},
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"max_open_trades": 4,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15,
|
||||
"unit": "minutes"
|
||||
},
|
||||
"fee": 0.0008
|
||||
}
|
||||
@ -1,127 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 4,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"startup_candle_count": 30,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
"timeframe": "3m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.05,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15
|
||||
},
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "eca767d4-fda5-4a1b-bb28-49ae18093307",
|
||||
"secret": "8CA3628A556ED137977DB298D37BC7F3",
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"OKB/USDT"
|
||||
],
|
||||
"pair_blacklist": []
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"freqai": {
|
||||
"enabled": true,
|
||||
"identifier": "test175",
|
||||
"freqaimodel": "XGBoostRegressor",
|
||||
"model_path": "/freqtrade/user_data/models",
|
||||
"save_backtesting_prediction": true,
|
||||
"purge_old_models": true,
|
||||
"load_trained_model": true,
|
||||
"train_period_days": 90,
|
||||
"backtest_period_days": 10,
|
||||
"live_retrain_hours": 0,
|
||||
"include_predictions_in_final_dataframe": true,
|
||||
"data_kitchen": {
|
||||
"fillna": "ffill",
|
||||
"feature_parameters": {
|
||||
"DI_threshold": 0.5,
|
||||
"weight_factor": 0.9
|
||||
}
|
||||
},
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["5m", "15m", "1h"],
|
||||
"include_corr_pairlist": ["BTC/USDT", "ETH/USDT"],
|
||||
"label_period_candles": 12,
|
||||
"include_shifted_candles": 3,
|
||||
"indicator_periods_candles": [10, 20, 50],
|
||||
"plot_feature_importances": 1,
|
||||
"feature_selection": {
|
||||
"method": "none"
|
||||
}
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": false,
|
||||
"random_state": 42
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 200,
|
||||
"learning_rate": 0.05,
|
||||
"max_depth": 6,
|
||||
"subsample": 0.8,
|
||||
"colsample_bytree": 0.8,
|
||||
"reg_alpha": 0.1,
|
||||
"reg_lambda": 1.0
|
||||
},
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
"listen_ip_address": "0.0.0.0",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"enable_openapi": false,
|
||||
"jwt_secret_key": "6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca",
|
||||
"ws_token": "6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ",
|
||||
"CORS_origins": [],
|
||||
"username": "freqAdmin",
|
||||
"password": "admin"
|
||||
},
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "DEBUG"
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
{
|
||||
"strategy": "MyStrategy",
|
||||
"timeframe": "5m",
|
||||
"dry_run": true,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 10.0,
|
||||
"minimal_roi": {
|
||||
"40": 0.0,
|
||||
"30": 0.01,
|
||||
"20": 0.02,
|
||||
"0": 0.04
|
||||
},
|
||||
"stoploss": -0.10,
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": 0.0,
|
||||
"trailing_stop_positive_offset": 0.0,
|
||||
"trailing_only_offset_is_reached": 0.0,
|
||||
"unfilledtimeout": {
|
||||
"buy": 300,
|
||||
"sell": 300
|
||||
},
|
||||
"exchange": {
|
||||
"name": "binance",
|
||||
"key": "",
|
||||
"secret": "",
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"BTC/USDT",
|
||||
"ETH/USDT",
|
||||
"SOL/USDT"
|
||||
],
|
||||
"pair_blacklist": []
|
||||
},
|
||||
"telegram": {
|
||||
"enabled": false,
|
||||
"token": "",
|
||||
"chat_id": ""
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": false,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"enable_openapi": false
|
||||
},
|
||||
"hyperopt": {
|
||||
"enabled": false,
|
||||
"epochs": 100,
|
||||
"spaces": [
|
||||
"buy",
|
||||
"sell",
|
||||
"roi",
|
||||
"stoploss",
|
||||
"trailing"
|
||||
],
|
||||
"hyperopt_path": "",
|
||||
"hyperopt_loss": "SharpeHyperOptLossDaily",
|
||||
"print_all": false,
|
||||
"mongodb_url": "",
|
||||
"mongodb_database": ""
|
||||
}
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"max_open_trades": 3,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 0.05,
|
||||
"tradable_balance_ratio": 0.99,
|
||||
"fiat_display_currency": "USD",
|
||||
"timeframe": "5m",
|
||||
"dry_run": true,
|
||||
"cancel_open_orders_on_exit": false,
|
||||
"unfilledtimeout": {
|
||||
"entry": 10,
|
||||
"exit": 10,
|
||||
"exit_timeout_count": 0,
|
||||
"unit": "minutes"
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"exchange": {
|
||||
"name": "binance",
|
||||
"key": "your_exchange_key",
|
||||
"secret": "your_exchange_secret",
|
||||
"ccxt_config": {},
|
||||
"ccxt_async_config": {
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"ETH/USDT",
|
||||
"XRP/USDT",
|
||||
"BTC/USDT"
|
||||
],
|
||||
"pair_blacklist": [
|
||||
"BNB/.*"
|
||||
]
|
||||
},
|
||||
"pairlists": [
|
||||
{"method": "StaticPairList"}
|
||||
],
|
||||
"telegram": {
|
||||
"enabled": false,
|
||||
"token": "your_telegram_token",
|
||||
"chat_id": "your_telegram_chat_id"
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": false,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"jwt_secret_key": "somethingrandom",
|
||||
"CORS_origins": [],
|
||||
"username": "freqtrader",
|
||||
"password": "SuperSecurePassword"
|
||||
},
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5
|
||||
}
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"max_open_trades": 3,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 0.05,
|
||||
"tradable_balance_ratio": 0.99,
|
||||
"fiat_display_currency": "USD",
|
||||
"timeframe": "5m",
|
||||
"dry_run": true,
|
||||
"cancel_open_orders_on_exit": false,
|
||||
"unfilledtimeout": {
|
||||
"entry": 10,
|
||||
"exit": 10,
|
||||
"exit_timeout_count": 0,
|
||||
"unit": "minutes"
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"exchange": {
|
||||
"name": "binance",
|
||||
"key": "your_exchange_key",
|
||||
"secret": "your_exchange_secret",
|
||||
"ccxt_config": {},
|
||||
"ccxt_async_config": {
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"ALGO/USDT",
|
||||
"ATOM/USDT",
|
||||
"BAT/USDT",
|
||||
"BCH/USDT",
|
||||
"BRD/USDT",
|
||||
"EOS/USDT",
|
||||
"ETH/USDT",
|
||||
"IOTA/USDT",
|
||||
"LINK/USDT",
|
||||
"LTC/USDT",
|
||||
"NEO/USDT",
|
||||
"NXS/USDT",
|
||||
"XMR/USDT",
|
||||
"XRP/USDT",
|
||||
"XTZ/USDT"
|
||||
],
|
||||
"pair_blacklist": [
|
||||
"BNB/.*"
|
||||
]
|
||||
},
|
||||
"pairlists": [
|
||||
{"method": "StaticPairList"}
|
||||
],
|
||||
"telegram": {
|
||||
"enabled": false,
|
||||
"token": "your_telegram_token",
|
||||
"chat_id": "your_telegram_chat_id"
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": false,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"jwt_secret_key": "somethingrandom",
|
||||
"CORS_origins": [],
|
||||
"username": "freqtrader",
|
||||
"password": "SuperSecurePassword"
|
||||
},
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5
|
||||
}
|
||||
}
|
||||
@ -1,128 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 4,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"startup_candle_count": 30,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
"timeframe": "3m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.05,
|
||||
"use_exit_signal": true,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15
|
||||
},
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "eca767d4-fda5-4a1b-bb28-49ae18093307",
|
||||
"secret": "8CA3628A556ED137977DB298D37BC7F3",
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"OKB/USDT"
|
||||
],
|
||||
"pair_blacklist": []
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"freqai": {
|
||||
"enabled": true,
|
||||
"identifier": "test175",
|
||||
"freqaimodel": "XGBoostRegressor",
|
||||
"model_path": "/freqtrade/user_data/models",
|
||||
"save_backtesting_prediction": true,
|
||||
"purge_old_models": true,
|
||||
"load_trained_model": true,
|
||||
"train_period_days": 90,
|
||||
"backtest_period_days": 10,
|
||||
"live_retrain_hours": 0,
|
||||
"include_predictions_in_final_dataframe": true,
|
||||
"data_kitchen": {
|
||||
"fillna": "ffill",
|
||||
"feature_parameters": {
|
||||
"DI_threshold": 0.5,
|
||||
"weight_factor": 0.9
|
||||
}
|
||||
},
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["5m", "15m", "1h"],
|
||||
"include_corr_pairlist": ["BTC/USDT", "ETH/USDT"],
|
||||
"label_period_candles": 12,
|
||||
"include_shifted_candles": 3,
|
||||
"indicator_periods_candles": [10, 20, 50],
|
||||
"plot_feature_importances": 1,
|
||||
"feature_selection": {
|
||||
"method": "none"
|
||||
}
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": false,
|
||||
"random_state": 42
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 200,
|
||||
"learning_rate": 0.05,
|
||||
"max_depth": 6,
|
||||
"subsample": 0.8,
|
||||
"colsample_bytree": 0.8,
|
||||
"reg_alpha": 0.1,
|
||||
"reg_lambda": 1.0
|
||||
},
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
"listen_ip_address": "0.0.0.0",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"enable_openapi": false,
|
||||
"jwt_secret_key": "6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca",
|
||||
"ws_token": "6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ",
|
||||
"CORS_origins": [],
|
||||
"username": "freqAdmin",
|
||||
"password": "admin"
|
||||
},
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "DEBUG"
|
||||
}
|
||||
}
|
||||
@ -1,212 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"max_open_trades": 3,
|
||||
"stake_currency": "BTC",
|
||||
"stake_amount": 0.05,
|
||||
"tradable_balance_ratio": 0.99,
|
||||
"fiat_display_currency": "USD",
|
||||
"amount_reserve_percent": 0.05,
|
||||
"available_capital": 1000,
|
||||
"amend_last_stake_amount": false,
|
||||
"last_stake_amount_min_ratio": 0.5,
|
||||
"dry_run": true,
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": false,
|
||||
"timeframe": "5m",
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": 0.005,
|
||||
"trailing_stop_positive_offset": 0.0051,
|
||||
"trailing_only_offset_is_reached": false,
|
||||
"use_exit_signal": true,
|
||||
"exit_profit_only": false,
|
||||
"exit_profit_offset": 0.0,
|
||||
"ignore_roi_if_entry_signal": false,
|
||||
"ignore_buying_expired_candle_after": 300,
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "",
|
||||
"minimal_roi": {
|
||||
"40": 0.0,
|
||||
"30": 0.01,
|
||||
"20": 0.02,
|
||||
"0": 0.04
|
||||
},
|
||||
"stoploss": -0.10,
|
||||
"unfilledtimeout": {
|
||||
"entry": 10,
|
||||
"exit": 10,
|
||||
"exit_timeout_count": 0,
|
||||
"unit": "minutes"
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing":{
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0
|
||||
},
|
||||
"order_types": {
|
||||
"entry": "limit",
|
||||
"exit": "limit",
|
||||
"emergency_exit": "market",
|
||||
"force_exit": "market",
|
||||
"force_entry": "market",
|
||||
"stoploss": "market",
|
||||
"stoploss_on_exchange": false,
|
||||
"stoploss_price_type": "last",
|
||||
"stoploss_on_exchange_interval": 60,
|
||||
"stoploss_on_exchange_limit_ratio": 0.99
|
||||
},
|
||||
"order_time_in_force": {
|
||||
"entry": "GTC",
|
||||
"exit": "GTC"
|
||||
},
|
||||
"pairlists": [
|
||||
{"method": "StaticPairList"},
|
||||
{"method": "FullTradesFilter"},
|
||||
{
|
||||
"method": "VolumePairList",
|
||||
"number_assets": 20,
|
||||
"sort_key": "quoteVolume",
|
||||
"refresh_period": 1800
|
||||
},
|
||||
{"method": "AgeFilter", "min_days_listed": 10},
|
||||
{"method": "PrecisionFilter"},
|
||||
{"method": "PriceFilter", "low_price_ratio": 0.01, "min_price": 0.00000010},
|
||||
{"method": "SpreadFilter", "max_spread_ratio": 0.005},
|
||||
{
|
||||
"method": "RangeStabilityFilter",
|
||||
"lookback_days": 10,
|
||||
"min_rate_of_change": 0.01,
|
||||
"refresh_period": 1440
|
||||
}
|
||||
],
|
||||
"exchange": {
|
||||
"name": "binance",
|
||||
"key": "your_exchange_key",
|
||||
"secret": "your_exchange_secret",
|
||||
"password": "",
|
||||
"log_responses": false,
|
||||
// "unknown_fee_rate": 1,
|
||||
"ccxt_config": {},
|
||||
"ccxt_async_config": {},
|
||||
"pair_whitelist": [
|
||||
"ALGO/BTC",
|
||||
"ATOM/BTC",
|
||||
"BAT/BTC",
|
||||
"BCH/BTC",
|
||||
"BRD/BTC",
|
||||
"EOS/BTC",
|
||||
"ETH/BTC",
|
||||
"IOTA/BTC",
|
||||
"LINK/BTC",
|
||||
"LTC/BTC",
|
||||
"NEO/BTC",
|
||||
"NXS/BTC",
|
||||
"XMR/BTC",
|
||||
"XRP/BTC",
|
||||
"XTZ/BTC"
|
||||
],
|
||||
"pair_blacklist": [
|
||||
"DOGE/BTC"
|
||||
],
|
||||
"outdated_offset": 5,
|
||||
"markets_refresh_interval": 60
|
||||
},
|
||||
"edge": {
|
||||
"enabled": false,
|
||||
"process_throttle_secs": 3600,
|
||||
"calculate_since_number_of_days": 7,
|
||||
"allowed_risk": 0.01,
|
||||
"stoploss_range_min": -0.01,
|
||||
"stoploss_range_max": -0.1,
|
||||
"stoploss_range_step": -0.01,
|
||||
"minimum_winrate": 0.60,
|
||||
"minimum_expectancy": 0.20,
|
||||
"min_trade_number": 10,
|
||||
"max_trade_duration_minute": 1440,
|
||||
"remove_pumps": false
|
||||
},
|
||||
"telegram": {
|
||||
"enabled": false,
|
||||
"token": "your_telegram_token",
|
||||
"chat_id": "your_telegram_chat_id",
|
||||
"notification_settings": {
|
||||
"status": "on",
|
||||
"warning": "on",
|
||||
"startup": "on",
|
||||
"entry": "on",
|
||||
"entry_fill": "on",
|
||||
"exit": {
|
||||
"roi": "off",
|
||||
"emergency_exit": "off",
|
||||
"force_exit": "off",
|
||||
"exit_signal": "off",
|
||||
"trailing_stop_loss": "off",
|
||||
"stop_loss": "off",
|
||||
"stoploss_on_exchange": "off",
|
||||
"custom_exit": "off"
|
||||
},
|
||||
"exit_fill": "on",
|
||||
"entry_cancel": "on",
|
||||
"exit_cancel": "on",
|
||||
"protection_trigger": "off",
|
||||
"protection_trigger_global": "on",
|
||||
"show_candle": "off"
|
||||
},
|
||||
"reload": true,
|
||||
"balance_dust_level": 0.01
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": false,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"enable_openapi": false,
|
||||
"jwt_secret_key": "somethingrandom",
|
||||
"CORS_origins": [],
|
||||
"username": "freqtrader",
|
||||
"password": "SuperSecurePassword",
|
||||
"ws_token": "secret_ws_t0ken."
|
||||
},
|
||||
"external_message_consumer": {
|
||||
"enabled": false,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": "127.0.0.2",
|
||||
"port": 8080,
|
||||
"ws_token": "secret_ws_t0ken."
|
||||
}
|
||||
],
|
||||
"wait_timeout": 300,
|
||||
"ping_timeout": 10,
|
||||
"sleep_time": 10,
|
||||
"remove_entry_exit_signals": false,
|
||||
"message_size_limit": 8
|
||||
},
|
||||
"bot_name": "freqtrade",
|
||||
"db_url": "sqlite:///tradesv3.sqlite",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 60
|
||||
},
|
||||
"disable_dataframe_checks": false,
|
||||
"strategy": "SampleStrategy",
|
||||
"strategy_path": "user_data/strategies/",
|
||||
"recursive_strategy_search": false,
|
||||
"add_config_files": [],
|
||||
"reduce_df_footprint": false,
|
||||
"dataformat_ohlcv": "feather",
|
||||
"dataformat_trades": "feather"
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"max_open_trades": 5,
|
||||
"stake_currency": "EUR",
|
||||
"stake_amount": 10,
|
||||
"tradable_balance_ratio": 0.99,
|
||||
"fiat_display_currency": "EUR",
|
||||
"timeframe": "5m",
|
||||
"dry_run": true,
|
||||
"cancel_open_orders_on_exit": false,
|
||||
"unfilledtimeout": {
|
||||
"entry": 10,
|
||||
"exit": 10,
|
||||
"exit_timeout_count": 0,
|
||||
"unit": "minutes"
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing":{
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"exchange": {
|
||||
"name": "kraken",
|
||||
"key": "your_exchange_key",
|
||||
"secret": "your_exchange_key",
|
||||
"ccxt_config": {},
|
||||
"ccxt_async_config": {
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"ADA/EUR",
|
||||
"ATOM/EUR",
|
||||
"BAT/EUR",
|
||||
"BCH/EUR",
|
||||
"BTC/EUR",
|
||||
"DAI/EUR",
|
||||
"DASH/EUR",
|
||||
"EOS/EUR",
|
||||
"ETC/EUR",
|
||||
"ETH/EUR",
|
||||
"LINK/EUR",
|
||||
"LTC/EUR",
|
||||
"QTUM/EUR",
|
||||
"REP/EUR",
|
||||
"WAVES/EUR",
|
||||
"XLM/EUR",
|
||||
"XMR/EUR",
|
||||
"XRP/EUR",
|
||||
"XTZ/EUR",
|
||||
"ZEC/EUR"
|
||||
],
|
||||
"pair_blacklist": [
|
||||
|
||||
]
|
||||
},
|
||||
"pairlists": [
|
||||
{"method": "StaticPairList"}
|
||||
],
|
||||
"telegram": {
|
||||
"enabled": false,
|
||||
"token": "your_telegram_token",
|
||||
"chat_id": "your_telegram_chat_id"
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": false,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"jwt_secret_key": "somethingrandom",
|
||||
"CORS_origins": [],
|
||||
"username": "freqtrader",
|
||||
"password": "SuperSecurePassword"
|
||||
},
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5
|
||||
},
|
||||
"download_trades": true
|
||||
}
|
||||
@ -1,133 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 4,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"startup_candle_count": 30,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
"identifier": "demo1",
|
||||
"timeframe": "5m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.05,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15
|
||||
},
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "eca767d4-fda5-4a1b-bb28-49ae18093307",
|
||||
"secret": "8CA3628A556ED137977DB298D37BC7F3",
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"OKB/USDT",
|
||||
"BTC/USDT",
|
||||
"SOL/USDT",
|
||||
"DOT/USDT",
|
||||
"TON/USDT",
|
||||
"ETH/USDT",
|
||||
],
|
||||
"pair_blacklist": []
|
||||
},
|
||||
"freqai": {
|
||||
"enabled": true,
|
||||
"identifier": "test175",
|
||||
"freqaimodel": "XGBoostRegressor",
|
||||
"model_path": "/freqtrade/user_data/models",
|
||||
"save_backtesting_prediction": true,
|
||||
"save_backtest_models": true,
|
||||
"backtest_period_days": 30,
|
||||
"purge_old_models": true,
|
||||
"load_trained_model": true,
|
||||
"train_period_days": 90,
|
||||
"backtest_period_days": 10,
|
||||
"live_retrain_hours": 0,
|
||||
"include_predictions_in_final_dataframe": true,
|
||||
"data_kitchen": {
|
||||
"fillna": "ffill",
|
||||
"feature_parameters": {
|
||||
"DI_threshold": 0.5,
|
||||
"weight_factor": 0.9
|
||||
}
|
||||
},
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["5m", "15m", "1h"],
|
||||
"include_corr_pairlist": ["BTC/USDT", "ETH/USDT"],
|
||||
"label_period_candles": 12,
|
||||
"include_shifted_candles": 3,
|
||||
"indicator_periods_candles": [10, 20, 50],
|
||||
"plot_feature_importances": 1,
|
||||
"feature_selection": {
|
||||
"method": "none"
|
||||
}
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": false
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 200,
|
||||
"learning_rate": 0.05,
|
||||
"max_depth": 6,
|
||||
"subsample": 0.8,
|
||||
"colsample_bytree": 0.8
|
||||
},
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
"listen_ip_address": "0.0.0.0",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"enable_openapi": false,
|
||||
"jwt_secret_key": "6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca",
|
||||
"ws_token": "6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ",
|
||||
"CORS_origins": [],
|
||||
"username": "freqAdmin",
|
||||
"password": "admin"
|
||||
},
|
||||
"use_exit_signal": true,
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "DEBUG"
|
||||
}
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 4,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
"timeframe": "3m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.05,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15
|
||||
},
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "eca767d4-fda5-4a1b-bb28-49ae18093307",
|
||||
"secret": "8CA3628A556ED137977DB298D37BC7F3",
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"BTC/USDT",
|
||||
"ETH/USDT",
|
||||
"TON/USDT",
|
||||
"OKB/USDT",
|
||||
"DOT/USDT",
|
||||
"SOL/USDT"
|
||||
],
|
||||
"pair_blacklist": []
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"freqai": {
|
||||
"enabled": true,
|
||||
"data_kitchen": {
|
||||
"fillna": "ffill"
|
||||
},
|
||||
"freqaimodel": "CatboostClassifier",
|
||||
"purge_old_models": 2,
|
||||
"train_period_days": 15,
|
||||
"identifier": "test58",
|
||||
"train_period_days": 30,
|
||||
"backtest_period_days": 10,
|
||||
"live_retrain_hours": 0,
|
||||
"feature_selection": {
|
||||
"method": "recursive_elimination"
|
||||
},
|
||||
"feature_parameters": {
|
||||
"include_timeframes": [
|
||||
"3m",
|
||||
"15m",
|
||||
"1h"
|
||||
],
|
||||
"include_corr_pairlist": [
|
||||
"BTC/USDT",
|
||||
"SOL/USDT"
|
||||
],
|
||||
"label_period_candles": 20,
|
||||
"include_shifted_candles": 2,
|
||||
"DI_threshold": 0.9,
|
||||
"weight_factor": 0.9,
|
||||
"principal_component_analysis": false,
|
||||
"use_SVM_to_remove_outliers": false,
|
||||
"indicator_periods_candles": [
|
||||
10,
|
||||
20,
|
||||
50
|
||||
],
|
||||
"plot_feature_importances": 0
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 100,
|
||||
"learning_rate": 0.05,
|
||||
"max_depth": 5,
|
||||
"num_leaves": 31
|
||||
}
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
"listen_ip_address": "0.0.0.0",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"enable_openapi": false,
|
||||
"jwt_secret_key": "6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca",
|
||||
"ws_token": "6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ",
|
||||
"CORS_origins": [],
|
||||
"username": "freqAdmin",
|
||||
"password": "admin"
|
||||
},
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "DEBUG"
|
||||
}
|
||||
}
|
||||
@ -1,127 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 4,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"startup_candle_count": 30,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
"timeframe": "3m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.05,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15
|
||||
},
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "eca767d4-fda5-4a1b-bb28-49ae18093307",
|
||||
"secret": "8CA3628A556ED137977DB298D37BC7F3",
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"BTC/USDT",
|
||||
"SOL/USDT"
|
||||
],
|
||||
"pair_blacklist": []
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"freqai": {
|
||||
"enabled": true,
|
||||
"data_kitchen": {
|
||||
"fillna": "ffill",
|
||||
"feature_parameters": {
|
||||
"DI_threshold": 0.9,
|
||||
"weight_factor": 0.9
|
||||
}
|
||||
},
|
||||
"freqaimodel": "XGBoostRegressor",
|
||||
"purge_old_models": 2,
|
||||
"identifier": "test175",
|
||||
"train_period_days": 30,
|
||||
"backtest_period_days": 10,
|
||||
"live_retrain_hours": 0,
|
||||
"feature_selection": {
|
||||
"method": "recursive_elimination",
|
||||
"threshold": 0.01
|
||||
},
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["3m", "5m", "1h"],
|
||||
"include_corr_pairlist": ["BTC/USDT", "ETH/USDT"],
|
||||
"label_period_candles": 12,
|
||||
"include_shifted_candles": 3,
|
||||
"indicator_periods_candles": [10, 20, 50],
|
||||
"plot_feature_importances": 1
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": true,
|
||||
"random_state": 42
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 200,
|
||||
"learning_rate": 0.05,
|
||||
"max_depth": 5,
|
||||
"subsample": 0.8,
|
||||
"colsample_bytree": 0.8,
|
||||
"objective": "reg:squarederror",
|
||||
"eval_metric": "rmse",
|
||||
"early_stopping_rounds": 50,
|
||||
"verbose": 0
|
||||
}
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
"listen_ip_address": "0.0.0.0",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"enable_openapi": false,
|
||||
"jwt_secret_key": "6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca",
|
||||
"ws_token": "6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ",
|
||||
"CORS_origins": [],
|
||||
"username": "freqAdmin",
|
||||
"password": "admin"
|
||||
},
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "DEBUG"
|
||||
}
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
{
|
||||
"strategy": "TheForceFreqaiStrategy",
|
||||
"timeframe": "5m",
|
||||
"timerange": "20240701-20250115",
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"options": {"defaultType": "spot"},
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"OKB/USDT"
|
||||
],
|
||||
"fee": 0.0008
|
||||
},
|
||||
"pair_whitelist": ["OKB/USDT"],
|
||||
"dataformat_ohlcv": "feather",
|
||||
"download_data": {
|
||||
"timeframes": ["5m"],
|
||||
"timerange": "20240701-20250115"
|
||||
},
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"stoploss": -0.15,
|
||||
"minimal_roi": {
|
||||
"0": 0.05,
|
||||
"60": 0.03,
|
||||
"120": 0.01
|
||||
},
|
||||
"startup_candle_count": 200,
|
||||
"max_open_trades": 4,
|
||||
"use_exit_signal": true,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15,
|
||||
"unit": "minutes"
|
||||
},
|
||||
"export": "trades",
|
||||
"cache": "none",
|
||||
"loglevel": "DEBUG",
|
||||
"verbosity": 2,
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1,
|
||||
"price_last_balance": 0.0,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"freqai": {
|
||||
"enabled": true,
|
||||
"identifier": "theforce_model",
|
||||
"save_backtest_models": true,
|
||||
"live_retrain": true,
|
||||
"purge_old_models": true,
|
||||
"fit_live_predictions_candles": 50,
|
||||
"force_train": true,
|
||||
"verbose": 2,
|
||||
"train_period_days": 7,
|
||||
"backtest_period_days": 2,
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["5m"],
|
||||
"include_corr_pairlist": [],
|
||||
"label_period_candles": 5,
|
||||
"include_shifted_candles": 2,
|
||||
"DI_threshold": 1.5,
|
||||
"indicator_periods_candles": [10, 20, 50],
|
||||
"include_default_features": ["open", "high", "low", "close", "volume"],
|
||||
"use_SVM_to_remove_outliers": false
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"random_state": 42
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 100,
|
||||
"max_depth": 7,
|
||||
"verbose": -1
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,96 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 3,
|
||||
"stake_amount": 300,
|
||||
"unfilledtimeout": {
|
||||
"entry": 10,
|
||||
"exit": 20
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"stake_currency": "USDT",
|
||||
"trailing_stop": false,
|
||||
"use_custom_stoploss": true,
|
||||
"startup_candle_count": 200,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
"identifier": "demo1",
|
||||
"timeframe": "5m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.061,
|
||||
"roi": {},
|
||||
"trailing": {
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": null,
|
||||
"trailing_stop_positive_offset": 0.0,
|
||||
"trailing_only_offset_is_reached": false
|
||||
},
|
||||
"max_open_trades": 3,
|
||||
"buy": {
|
||||
"adx_buy": 25,
|
||||
"atr_ratio": 0.005
|
||||
},
|
||||
"sell": {
|
||||
"ema_fast_period": 7,
|
||||
"rsi_sell": 60
|
||||
},
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "REDACTED",
|
||||
"secret": "REDACTED",
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 3000,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": ["BTC/USDT", "ETH/USDT", "SOL/USDT", "DOT/USDT"],
|
||||
"pair_blacklist": []
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
"listen_ip_address": "0.0.0.0",
|
||||
"listen_port": 8080,
|
||||
"verbosity": "error",
|
||||
"enable_openapi": false,
|
||||
"jwt_secret_key": "6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca",
|
||||
"ws_token": "6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ",
|
||||
"CORS_origins": [],
|
||||
"username": "freqAdmin",
|
||||
"password": "REDACTED"
|
||||
},
|
||||
"use_exit_signal": true,
|
||||
"bot_name": "freqtrade",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "INFO"
|
||||
},
|
||||
"config_files": ["config_examples/theforcev7.json"]
|
||||
}
|
||||
@ -1,122 +0,0 @@
|
||||
diff --git a/config_examples/config_freqai.okx.json b/config_examples/config_freqai.okx.json
|
||||
index 259459e..c8f04af 100644
|
||||
--- a/config_examples/config_freqai.okx.json
|
||||
+++ b/config_examples/config_freqai.okx.json
|
||||
@@ -5,11 +5,10 @@
|
||||
"max_open_trades": 4,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
- "startup_candle_count": 30,
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
- "timeframe": "5m",
|
||||
+ "timeframe": "3m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.05,
|
||||
@@ -24,21 +23,21 @@
|
||||
"enable_ws": false,
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
- "rateLimit": 800,
|
||||
+ "rateLimit": 500,
|
||||
"options": {
|
||||
"defaultType": "spot"
|
||||
}
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": true,
|
||||
- "rateLimit": 800,
|
||||
+ "rateLimit": 500,
|
||||
"timeout": 20000
|
||||
},
|
||||
"pair_whitelist": [
|
||||
- "OKB/USDT",
|
||||
- "DOT/USDT",
|
||||
+ "BTC/USDT",
|
||||
"SOL/USDT"
|
||||
- ]
|
||||
+ ],
|
||||
+ "pair_blacklist": []
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
@@ -65,47 +64,38 @@
|
||||
"data_kitchen": {
|
||||
"fillna": "ffill"
|
||||
},
|
||||
- "freqaimodel": "CatboostClassifier",
|
||||
- "purge_old_models": 2,
|
||||
- "identifier": "test175",
|
||||
- "train_period_days": 30,
|
||||
- "backtest_period_days": 10,
|
||||
+ "freqaimodel": "XGBoostRegressor",
|
||||
+ "model_training_parameters": {
|
||||
+ "n_estimators": 100,
|
||||
+ "learning_rate": 0.05,
|
||||
+ "max_depth": 5
|
||||
+ },
|
||||
+ "train_period_days": 15,
|
||||
+ "train_period_days": 180,
|
||||
+ "backtest_period_days": 60,
|
||||
"live_retrain_hours": 0,
|
||||
"feature_selection": {
|
||||
"method": "recursive_elimination"
|
||||
},
|
||||
"feature_parameters": {
|
||||
- "include_timeframes": [
|
||||
- "5m",
|
||||
- "1h"
|
||||
- ],
|
||||
- "include_corr_pairlist": [
|
||||
- "BTC/USDT",
|
||||
- "ETH/USDT"
|
||||
- ],
|
||||
- "label_period_candles": 12,
|
||||
- "include_shifted_candles": 3,
|
||||
- "DI_threshold": 0.9,
|
||||
+ "include_timeframes": ["15m"],
|
||||
+ "include_corr_pairlist": ["BTC/USDT"],
|
||||
+ "label_period_candles": 10,
|
||||
+ "include_shifted_candles": 1,
|
||||
+
|
||||
"weight_factor": 0.9,
|
||||
"principal_component_analysis": false,
|
||||
"use_SVM_to_remove_outliers": false,
|
||||
- "indicator_periods_candles": [
|
||||
- 10,
|
||||
- 20,
|
||||
- 50
|
||||
- ],
|
||||
- "plot_feature_importances": 0
|
||||
+ "indicator_periods_candles": [14],
|
||||
},
|
||||
"data_split_parameters": {
|
||||
- "test_size": 0.2,
|
||||
- "shuffle": false,
|
||||
+ "test_size": 0.2
|
||||
},
|
||||
- "model_training_parameters": {
|
||||
- "n_estimators": 100,
|
||||
- "learning_rate": 0.1,
|
||||
- "num_leaves": 15,
|
||||
- "verbose": -1
|
||||
- }
|
||||
+ "model_training_parameters": {
|
||||
+ "n_estimators": 100,
|
||||
+ "learning_rate": 0.05,
|
||||
+ "max_depth": 5
|
||||
+ }
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
@@ -123,7 +113,7 @@
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
- "process_throttle_secs": 10,
|
||||
+ "process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "DEBUG"
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
{
|
||||
"strategy_name": "FreqaiExampleStrategy",
|
||||
"params": {
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 4
|
||||
},
|
||||
"buy": {
|
||||
"buy_rsi": 39.92672300850069
|
||||
},
|
||||
"sell": {
|
||||
"sell_rsi": 69.92672300850069
|
||||
},
|
||||
"protection": {},
|
||||
"roi": {
|
||||
"0": 0.163,
|
||||
"8": 0.049,
|
||||
"16": 0.007,
|
||||
"66": 0
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -0.251
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.055,
|
||||
"trailing_stop_positive_offset": 0.11699999999999999,
|
||||
"trailing_only_offset_is_reached": true
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-05-17 10:15:19.962889+00:00"
|
||||
}
|
||||
@ -1,277 +0,0 @@
|
||||
import logging
|
||||
import numpy as np
|
||||
from functools import reduce
|
||||
import talib.abstract as ta
|
||||
from pandas import DataFrame
|
||||
from technical import qtpylib
|
||||
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class FreqaiExampleStrategy(IStrategy):
|
||||
minimal_roi = {
|
||||
0: 0.135,
|
||||
9: 0.052,
|
||||
15: 0.007,
|
||||
60: 0
|
||||
}
|
||||
stoploss = -0.263
|
||||
trailing_stop = True
|
||||
trailing_stop_positive = 0.324
|
||||
trailing_stop_positive_offset = 0.411
|
||||
trailing_only_offset_is_reached = False
|
||||
max_open_trades = 4
|
||||
process_only_new_candles = True
|
||||
use_exit_signal = True
|
||||
startup_candle_count: int = 40
|
||||
can_short = False
|
||||
|
||||
buy_rsi = IntParameter(low=10, high=50, default=30, space="buy", optimize=False, load=True)
|
||||
sell_rsi = IntParameter(low=50, high=90, default=70, space="sell", optimize=False, load=True)
|
||||
roi_0 = DecimalParameter(low=0.01, high=0.2, default=0.135, space="roi", optimize=True, load=True)
|
||||
roi_15 = DecimalParameter(low=0.005, high=0.1, default=0.052, space="roi", optimize=True, load=True)
|
||||
roi_30 = DecimalParameter(low=0.001, high=0.05, default=0.007, space="roi", optimize=True, load=True)
|
||||
stoploss_param = DecimalParameter(low=-0.35, high=-0.1, default=-0.263, space="stoploss", optimize=True, load=True)
|
||||
trailing_stop_positive_param = DecimalParameter(low=0.1, high=0.5, default=0.324, space="trailing", optimize=True, load=True)
|
||||
trailing_stop_positive_offset_param = DecimalParameter(low=0.2, high=0.6, default=0.411, space="trailing", optimize=True, load=True)
|
||||
|
||||
freqai_info = {
|
||||
"model": "LightGBMRegressor",
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["5m", "15m", "1h"],
|
||||
"include_corr_pairlist": [],
|
||||
"label_period_candles": 12,
|
||||
"include_shifted_candles": 3,
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": False,
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 200,
|
||||
"learning_rate": 0.05,
|
||||
"num_leaves": 31,
|
||||
"verbose": -1,
|
||||
},
|
||||
}
|
||||
|
||||
plot_config = {
|
||||
"main_plot": {},
|
||||
"subplots": {
|
||||
"&-buy_rsi": {"&-buy_rsi": {"color": "green"}},
|
||||
"&-sell_rsi": {"&-sell_rsi": {"color": "red"}},
|
||||
"&-stoploss": {"&-stoploss": {"color": "purple"}},
|
||||
"&-roi_0": {"&-roi_0": {"color": "orange"}},
|
||||
"do_predict": {"do_predict": {"color": "brown"}},
|
||||
},
|
||||
}
|
||||
|
||||
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
|
||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
||||
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
|
||||
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
|
||||
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
|
||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=period, stds=2.2)
|
||||
dataframe["bb_lowerband-period"] = bollinger["lower"]
|
||||
dataframe["bb_middleband-period"] = bollinger["mid"]
|
||||
dataframe["bb_upperband-period"] = bollinger["upper"]
|
||||
dataframe["%-bb_width-period"] = (
|
||||
dataframe["bb_upperband-period"] - dataframe["bb_lowerband-period"]
|
||||
) / dataframe["bb_middleband-period"]
|
||||
dataframe["%-close-bb_lower-period"] = dataframe["close"] / dataframe["bb_lowerband-period"]
|
||||
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
|
||||
dataframe["%-relative_volume-period"] = (
|
||||
dataframe["volume"] / dataframe["volume"].rolling(period).mean()
|
||||
)
|
||||
dataframe = dataframe.replace([np.inf, -np.inf], 0)
|
||||
dataframe = dataframe.ffill()
|
||||
dataframe = dataframe.fillna(0)
|
||||
return dataframe
|
||||
|
||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
|
||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
||||
dataframe["%-raw_price"] = dataframe["close"]
|
||||
dataframe = dataframe.replace([np.inf, -np.inf], 0)
|
||||
dataframe = dataframe.ffill()
|
||||
dataframe = dataframe.fillna(0)
|
||||
return dataframe
|
||||
|
||||
def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
|
||||
if len(dataframe["close"]) < 20:
|
||||
logger.warning(f"数据不足 {len(dataframe)} 根 K 线,%-volatility 可能不完整")
|
||||
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
|
||||
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
|
||||
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
|
||||
return dataframe
|
||||
|
||||
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
|
||||
logger.info(f"设置 FreqAI 目标,交易对:{metadata['pair']}")
|
||||
if "close" not in dataframe.columns:
|
||||
logger.error("数据框缺少必要的 'close' 列")
|
||||
raise ValueError("数据框缺少必要的 'close' 列")
|
||||
|
||||
try:
|
||||
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
|
||||
if "%-volatility" not in dataframe.columns:
|
||||
logger.warning("缺少 %-volatility 列,强制重新生成")
|
||||
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
|
||||
|
||||
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14)
|
||||
dataframe["&-buy_rsi"] = dataframe["&-buy_rsi"].shift(-label_period).ffill().bfill()
|
||||
|
||||
for col in ["&-buy_rsi", "%-volatility"]:
|
||||
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
|
||||
dataframe[col] = dataframe[col].ffill()
|
||||
dataframe[col] = dataframe[col].fillna(0)
|
||||
if dataframe[col].isna().any():
|
||||
logger.warning(f"目标列 {col} 仍包含 NaN,数据预览:\n{dataframe[col].tail(10)}")
|
||||
except Exception as e:
|
||||
logger.error(f"创建 FreqAI 目标失败:{str(e)}")
|
||||
raise
|
||||
|
||||
logger.info(f"目标列预览:\n{dataframe[['&-buy_rsi']].head().to_string()}")
|
||||
return dataframe
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
logger.info(f"处理交易对:{metadata['pair']}")
|
||||
logger.debug(f"输入特征列:{list(dataframe.columns)}")
|
||||
dataframe = self.freqai.start(dataframe, metadata, self)
|
||||
logger.debug(f"FreqAI 输出特征列:{list(dataframe.columns)}")
|
||||
|
||||
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
|
||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
||||
dataframe["bb_lowerband"] = bollinger["lower"]
|
||||
dataframe["bb_middleband"] = bollinger["mid"]
|
||||
dataframe["bb_upperband"] = bollinger["upper"]
|
||||
dataframe["tema"] = ta.TEMA(dataframe, timeperiod=9)
|
||||
|
||||
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
|
||||
dataframe["up_or_down"] = np.where(
|
||||
dataframe["close"].shift(-label_period) > dataframe["close"], 1, 0
|
||||
)
|
||||
|
||||
if "&-buy_rsi" in dataframe.columns:
|
||||
if "%-volatility" not in dataframe.columns:
|
||||
logger.warning("缺少 %-volatility 列,强制重新生成")
|
||||
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
|
||||
|
||||
dataframe["&-sell_rsi"] = dataframe["&-buy_rsi"] + 30
|
||||
dataframe["&-stoploss"] = self.stoploss - (dataframe["%-volatility"] * 5).clip(-0.05, 0.05)
|
||||
dataframe["&-roi_0"] = (dataframe["close"].shift(-label_period) / dataframe["close"] - 1).clip(0, 0.2)
|
||||
|
||||
for col in ["&-buy_rsi", "&-sell_rsi", "&-stoploss", "&-roi_0"]:
|
||||
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
|
||||
dataframe[col] = dataframe[col].ffill()
|
||||
dataframe[col] = dataframe[col].fillna(0)
|
||||
|
||||
dataframe["buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(5).mean().clip(10, 50)
|
||||
dataframe["sell_rsi_pred"] = dataframe["&-sell_rsi"].rolling(5).mean().clip(50, 90)
|
||||
dataframe["stoploss_pred"] = dataframe["&-stoploss"].clip(-0.35, -0.1)
|
||||
dataframe["roi_0_pred"] = dataframe["&-roi_0"].clip(0.01, 0.2)
|
||||
|
||||
for col in ["buy_rsi_pred", "sell_rsi_pred", "stoploss_pred", "roi_0_pred"]:
|
||||
if dataframe[col].isna().any():
|
||||
logger.warning(f"列 {col} 包含 NaN,填充为默认值")
|
||||
dataframe[col] = dataframe[col].ffill()
|
||||
dataframe[col] = dataframe[col].fillna(dataframe[col].mean())
|
||||
|
||||
dataframe["trailing_stop_positive"] = (dataframe["roi_0_pred"] * 0.5).clip(0.01, 0.3)
|
||||
dataframe["trailing_stop_positive_offset"] = (dataframe["roi_0_pred"] * 0.75).clip(0.02, 0.4)
|
||||
|
||||
self.buy_rsi.value = float(dataframe["buy_rsi_pred"].iloc[-1])
|
||||
self.sell_rsi.value = float(dataframe["sell_rsi_pred"].iloc[-1])
|
||||
self.stoploss = float(self.stoploss_param.value)
|
||||
self.minimal_roi = {
|
||||
0: float(self.roi_0.value),
|
||||
15: float(self.roi_15.value),
|
||||
30: float(self.roi_30.value),
|
||||
60: 0
|
||||
}
|
||||
self.trailing_stop_positive = float(self.trailing_stop_positive_param.value)
|
||||
self.trailing_stop_positive_offset = float(self.trailing_stop_positive_offset_param.value)
|
||||
|
||||
logger.info(f"动态参数:buy_rsi={self.buy_rsi.value}, sell_rsi={self.sell_rsi.value}, "
|
||||
f"stoploss={self.stoploss}, trailing_stop_positive={self.trailing_stop_positive}")
|
||||
else:
|
||||
logger.warning(f"&-buy_rsi 列缺失,跳过 FreqAI 预测逻辑,检查 freqai.start 输出")
|
||||
|
||||
dataframe = dataframe.replace([np.inf, -np.inf], 0)
|
||||
dataframe = dataframe.ffill()
|
||||
dataframe = dataframe.fillna(0)
|
||||
|
||||
logger.info(f"up_or_down 值统计:\n{dataframe['up_or_down'].value_counts().to_string()}")
|
||||
logger.info(f"do_predict 值统计:\n{dataframe['do_predict'].value_counts().to_string()}")
|
||||
logger.debug(f"最终特征列:{list(dataframe.columns)}")
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||
enter_long_conditions = [
|
||||
qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"]),
|
||||
df["tema"] > df["tema"].shift(1),
|
||||
df["volume"] > 0,
|
||||
df["do_predict"] == 1,
|
||||
df["up_or_down"] == 1
|
||||
]
|
||||
if enter_long_conditions:
|
||||
df.loc[
|
||||
reduce(lambda x, y: x & y, enter_long_conditions),
|
||||
["enter_long", "enter_tag"]
|
||||
] = (1, "long")
|
||||
return df
|
||||
|
||||
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||
exit_long_conditions = [
|
||||
qtpylib.crossed_above(df["rsi"], df["sell_rsi_pred"]),
|
||||
(df["close"] < df["close"].shift(1) * 0.97),
|
||||
df["volume"] > 0,
|
||||
df["do_predict"] == 1,
|
||||
df["up_or_down"] == 0
|
||||
]
|
||||
if exit_long_conditions:
|
||||
df.loc[
|
||||
reduce(lambda x, y: x & y, exit_long_conditions),
|
||||
"exit_long"
|
||||
] = 1
|
||||
return df
|
||||
|
||||
def confirm_trade_entry(
|
||||
self, pair: str, order_type: str, amount: float, rate: float,
|
||||
time_in_force: str, current_time, entry_tag, side: str, **kwargs
|
||||
) -> bool:
|
||||
try:
|
||||
df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
if df is None or df.empty:
|
||||
logger.warning(f"无法获取 {pair} 的分析数据,拒绝交易")
|
||||
return False
|
||||
|
||||
last_candle = df.iloc[-1].squeeze()
|
||||
if "close" not in last_candle or np.isnan(last_candle["close"]):
|
||||
logger.warning(f"{pair} 的最新 K 线缺少有效 close 价格,拒绝交易")
|
||||
return False
|
||||
|
||||
if side == "long":
|
||||
max_rate = last_candle["close"] * (1 + 0.0025) # 0.25% 滑点阈值
|
||||
if rate > max_rate:
|
||||
logger.debug(f"拒绝 {pair} 的买入,价格 {rate} 超过最大允许价格 {max_rate}")
|
||||
return False
|
||||
elif side == "short":
|
||||
logger.warning(f"{pair} 尝试做空,但策略不支持做空 (can_short={self.can_short})")
|
||||
return False
|
||||
|
||||
logger.debug(f"确认 {pair} 的交易:side={side}, rate={rate}, close={last_candle['close']}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"确认 {pair} 交易时出错:{str(e)}")
|
||||
return False
|
||||
@ -1,248 +0,0 @@
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
pd.options.mode.chained_assignment = None
|
||||
from pandas import DataFrame
|
||||
from freqtrade.strategy import IStrategy
|
||||
from freqtrade.strategy import IntParameter
|
||||
import logging
|
||||
from functools import reduce
|
||||
import datetime
|
||||
|
||||
import talib.abstract as ta
|
||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class NostalgiaForInfinityV8(IStrategy):
|
||||
INTERFACE_VERSION = 3
|
||||
|
||||
minimal_roi = {
|
||||
"0": 0.06,
|
||||
"30": 0.04,
|
||||
"60": 0.02,
|
||||
"120": 0
|
||||
}
|
||||
|
||||
stoploss = -0.05
|
||||
use_custom_stoploss = True
|
||||
trailing_stop = False
|
||||
timeframe = '15m'
|
||||
process_only_new_candles = True
|
||||
use_exit_signal = True
|
||||
exit_profit_only = False
|
||||
ignore_roi_if_entry_signal = False
|
||||
startup_candle_count: int = 146
|
||||
|
||||
can_short = False
|
||||
|
||||
order_types = {
|
||||
'entry': 'market',
|
||||
'exit': 'market',
|
||||
'stoploss': 'limit',
|
||||
'stoploss_on_exchange': False
|
||||
}
|
||||
|
||||
order_time_in_force = {
|
||||
'entry': 'gtc',
|
||||
'exit': 'gtc'
|
||||
}
|
||||
|
||||
buy_rsi = IntParameter(low=20, high=60, default=50, space="buy", optimize=True)
|
||||
sell_rsi = IntParameter(low=50, high=80, default=55, space="sell", optimize=True)
|
||||
buy_volume_factor = IntParameter(low=1, high=5, default=2, space="buy", optimize=True)
|
||||
|
||||
freqai_info = {
|
||||
"model": "XGBoostRegressor",
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["15m"],
|
||||
"include_corr_pairlist": ["OKB/USDT", "SOL/USDT"],
|
||||
"label_period_candles": 4,
|
||||
"include_shifted_candles": 0,
|
||||
"indicator_periods_candles": [5, 10, 20],
|
||||
"include_default_features": ["close", "open", "high", "low", "volume", "rsi", "ema", "sma"]
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": False
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 100,
|
||||
"learning_rate": 0.1,
|
||||
"num_leaves": 15,
|
||||
"n_jobs": 4,
|
||||
"verbosity": -1
|
||||
}
|
||||
}
|
||||
|
||||
plot_config = {
|
||||
'main_plot': {
|
||||
'ema6': {'color': 'blue'},
|
||||
'ema24': {'color': 'red'},
|
||||
'sma32': {'color': 'green'},
|
||||
'sma64': {'color': 'purple'},
|
||||
},
|
||||
'subplots': {
|
||||
"RSI": {'rsi': {'color': 'blue'}, 'buy_rsi_pred': {'color': 'orange'}}
|
||||
}
|
||||
}
|
||||
|
||||
def detect_pivot_low(self, series: pd.Series, left: int, right: int) -> pd.Series:
|
||||
pivots = pd.Series(False, index=series.index)
|
||||
for i in range(left, len(series) - right):
|
||||
if (series[i] < series[i - left:i]).all() and (series[i] < series[i + 1:i + right + 1]).all():
|
||||
pivots.iloc[i] = True
|
||||
return pivots
|
||||
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
if dataframe.empty:
|
||||
logger.warning(f"Empty dataframe for {metadata['pair']}, skipping indicators")
|
||||
return dataframe
|
||||
|
||||
informative = dataframe.copy()
|
||||
|
||||
# Momentum Indicators
|
||||
informative['rsi'] = ta.RSI(informative, timeperiod=14)
|
||||
|
||||
# EMA and SMA
|
||||
informative['ema6'] = ta.EMA(informative, timeperiod=6)
|
||||
informative['ema24'] = ta.EMA(informative, timeperiod=24)
|
||||
informative['sma32'] = ta.SMA(informative, timeperiod=32)
|
||||
informative['sma64'] = ta.SMA(informative, timeperiod=64)
|
||||
|
||||
# ATR for dynamic stoploss
|
||||
informative['atr'] = ta.ATR(informative, timeperiod=14)
|
||||
|
||||
# Volume
|
||||
informative['volume_mean'] = informative['volume'].rolling(20).mean()
|
||||
|
||||
# RSI Divergence using custom pivot detection
|
||||
informative['price_pivot_low'] = self.detect_pivot_low(informative['close'], left=3, right=3)
|
||||
informative['rsi_pivot_low'] = self.detect_pivot_low(informative['rsi'], left=3, right=3)
|
||||
informative['bullish_divergence'] = (informative['price_pivot_low'] == True) & (informative['rsi_pivot_low'] != True)
|
||||
|
||||
# 设置 FreqAI 标签
|
||||
informative = self.set_freqai_targets(informative)
|
||||
|
||||
# 启动 FreqAI
|
||||
try:
|
||||
informative = self.freqai.start(informative, metadata, self)
|
||||
logger.info(f"FreqAI features for {metadata['pair']}: {informative.columns.tolist()}")
|
||||
except Exception as e:
|
||||
logger.error(f"FreqAI failed for {metadata['pair']}: {str(e)}")
|
||||
informative['buy_rsi_pred'] = informative['rsi']
|
||||
informative['do_predict'] = 0
|
||||
|
||||
logger.info(f"Indicators for {metadata['pair']} at {informative['date'].iloc[-1]}: "
|
||||
f"RSI={informative['rsi'].iloc[-1]:.2f}, "
|
||||
f"buy_rsi_pred={informative['buy_rsi_pred'].iloc[-1] if 'buy_rsi_pred' in informative else 'N/A'}, "
|
||||
f"do_predict={informative['do_predict'].iloc[-1]}, "
|
||||
f"EMA6={informative['ema6'].iloc[-1]:.2f}, "
|
||||
f"EMA24={informative['ema24'].iloc[-1]:.2f}, "
|
||||
f"Bullish_Divergence={informative['bullish_divergence'].iloc[-1]}")
|
||||
|
||||
return informative
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
if dataframe.empty:
|
||||
logger.warning(f"Empty dataframe for {metadata['pair']}, skipping indicators")
|
||||
return dataframe
|
||||
|
||||
informative = dataframe.copy()
|
||||
|
||||
# Momentum Indicators
|
||||
informative['rsi'] = ta.RSI(informative, timeperiod=14)
|
||||
|
||||
# EMA and SMA
|
||||
informative['ema6'] = ta.EMA(informative, timeperiod=6)
|
||||
informative['ema24'] = ta.EMA(informative, timeperiod=24)
|
||||
informative['sma32'] = ta.SMA(informative, timeperiod=32)
|
||||
informative['sma64'] = ta.SMA(informative, timeperiod=64)
|
||||
|
||||
# ATR for dynamic stoploss
|
||||
informative['atr'] = ta.ATR(informative, timeperiod=14)
|
||||
|
||||
# Volume
|
||||
informative['volume_mean'] = informative['volume'].rolling(20).mean()
|
||||
|
||||
# RSI Divergence using custom pivot detection
|
||||
informative['price_pivot_low'] = self.detect_pivot_low(informative['close'], left=3, right=3)
|
||||
informative['rsi_pivot_low'] = self.detect_pivot_low(informative['rsi'], left=3, right=3)
|
||||
informative['bullish_divergence'] = (informative['price_pivot_low'] == True) & (informative['rsi_pivot_low'] != True)
|
||||
|
||||
# 设置 FreqAI 标签(✅ 已修复:删除了非法标记)
|
||||
informative = self.set_freqai_targets(informative, metadata)
|
||||
|
||||
# 启动 FreqAI
|
||||
try:
|
||||
informative = self.freqai.start(informative, metadata, self)
|
||||
logger.info(f"FreqAI features for {metadata['pair']}: {informative.columns.tolist()}")
|
||||
except Exception as e:
|
||||
logger.error(f"FreqAI failed for {metadata['pair']}: {str(e)}")
|
||||
informative['buy_rsi_pred'] = informative['rsi']
|
||||
informative['do_predict'] = 0
|
||||
|
||||
logger.info(f"Indicators for {metadata['pair']} at {informative['date'].iloc[-1]}: "
|
||||
f"RSI={informative['rsi'].iloc[-1]:.2f}, "
|
||||
f"buy_rsi_pred={informative['buy_rsi_pred'].iloc[-1] if 'buy_rsi_pred' in informative else 'N/A'}, "
|
||||
f"do_predict={informative['do_predict'].iloc[-1]}, "
|
||||
f"EMA6={informative['ema6'].iloc[-1]:.2f}, "
|
||||
f"EMA24={informative['ema24'].iloc[-1]:.2f}, "
|
||||
f"Bullish_Divergence={informative['bullish_divergence'].iloc[-1]}")
|
||||
|
||||
return informative
|
||||
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
|
||||
dataframe['label'] = (
|
||||
(dataframe['close'].shift(-label_period) / dataframe['close']) - 1
|
||||
) * 100 # 百分比变化
|
||||
return dataframe
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
if dataframe.empty:
|
||||
logger.warning(f"Empty dataframe for {metadata['pair']}, skipping exit trend")
|
||||
return dataframe
|
||||
|
||||
exit_long_conditions = [
|
||||
dataframe['rsi'] > self.sell_rsi.value,
|
||||
dataframe['ema6'] < dataframe['ema24'],
|
||||
dataframe['volume'] > 0
|
||||
]
|
||||
|
||||
dataframe.loc[
|
||||
reduce(lambda x, y: x & y, exit_long_conditions),
|
||||
'exit_long'
|
||||
] = 1
|
||||
return dataframe
|
||||
|
||||
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
|
||||
current_rate: float, current_profit: float, **kwargs) -> float:
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
if dataframe.empty:
|
||||
logger.warning(f"Empty dataframe for {pair} in custom_stoploss")
|
||||
return self.stoploss
|
||||
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
atr_stoploss = last_candle['close'] - 1.5 * last_candle['atr']
|
||||
if atr_stoploss < current_rate:
|
||||
return (atr_stoploss / current_rate) - 1
|
||||
return self.stoploss
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
if dataframe.empty:
|
||||
logger.warning(f"Empty dataframe for {metadata['pair']}, skipping entry trend")
|
||||
return dataframe
|
||||
|
||||
# 示例买入条件:
|
||||
conditions = [
|
||||
dataframe['rsi'] < self.buy_rsi.value,
|
||||
dataframe['ema6'] > dataframe['ema24'],
|
||||
dataframe['volume'] > 0,
|
||||
dataframe['bullish_divergence'] == True,
|
||||
dataframe['do_predict'] == 1,
|
||||
dataframe['rsi'] < dataframe['buy_rsi_pred']
|
||||
]
|
||||
|
||||
dataframe.loc[
|
||||
reduce(lambda x, y: x & y, conditions),
|
||||
'enter_long'
|
||||
] = 1
|
||||
|
||||
return dataframe
|
||||
@ -1,69 +0,0 @@
|
||||
from functools import reduce
|
||||
from pandas import DataFrame
|
||||
from freqtrade.strategy import IStrategy
|
||||
|
||||
import talib.abstract as ta
|
||||
|
||||
from freqtrade.strategy.interface import IStrategy
|
||||
|
||||
class TrendFollowingStrategy(IStrategy):
|
||||
|
||||
INTERFACE_VERSION: int = 3
|
||||
# ROI table:
|
||||
minimal_roi = {"0": 0.15, "30": 0.1, "60": 0.05}
|
||||
# minimal_roi = {"0": 1}
|
||||
|
||||
# Stoploss:
|
||||
stoploss = -0.265
|
||||
|
||||
# Trailing stop:
|
||||
trailing_stop = True
|
||||
trailing_stop_positive = 0.05
|
||||
trailing_stop_positive_offset = 0.1
|
||||
trailing_only_offset_is_reached = False
|
||||
can_short=False
|
||||
|
||||
timeframe = "5m"
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# Calculate OBV
|
||||
dataframe['obv'] = ta.OBV(dataframe['close'], dataframe['volume'])
|
||||
|
||||
# Add your trend following indicators here
|
||||
dataframe['trend'] = dataframe['close'].ewm(span=20, adjust=False).mean()
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# Add your trend following buy signals here
|
||||
dataframe.loc[
|
||||
(dataframe['close'] > dataframe['trend']) &
|
||||
(dataframe['close'].shift(1) <= dataframe['trend'].shift(1)) &
|
||||
(dataframe['obv'] > dataframe['obv'].shift(1)),
|
||||
'enter_long'] = 1
|
||||
|
||||
# Add your trend following sell signals here
|
||||
dataframe.loc[
|
||||
(dataframe['close'] < dataframe['trend']) &
|
||||
(dataframe['close'].shift(1) >= dataframe['trend'].shift(1)) &
|
||||
(dataframe['obv'] < dataframe['obv'].shift(1)),
|
||||
'enter_short'] = 1
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# Add your trend following exit signals for long positions here
|
||||
dataframe.loc[
|
||||
(dataframe['close'] < dataframe['trend']) &
|
||||
(dataframe['close'].shift(1) >= dataframe['trend'].shift(1)) &
|
||||
(dataframe['obv'] > dataframe['obv'].shift(1)),
|
||||
'exit_long'] = 1
|
||||
|
||||
# Add your trend following exit signals for short positions here
|
||||
dataframe.loc[
|
||||
(dataframe['close'] > dataframe['trend']) &
|
||||
(dataframe['close'].shift(1) <= dataframe['trend'].shift(1)) &
|
||||
(dataframe['obv'] < dataframe['obv'].shift(1)),
|
||||
'exit_short'] = 1
|
||||
|
||||
return dataframe
|
||||
@ -1,34 +0,0 @@
|
||||
{
|
||||
"strategy_name": "TheForceV7",
|
||||
"params": {
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 3
|
||||
},
|
||||
"buy": {
|
||||
"adx_buy": 25,
|
||||
"atr_ratio": 0.005
|
||||
},
|
||||
"sell": {
|
||||
"ema_fast_period": 7,
|
||||
"rsi_sell": 60
|
||||
},
|
||||
"protection": {},
|
||||
"roi": {
|
||||
"0": 0.23399999999999999,
|
||||
"32": 0.06,
|
||||
"91": 0.026,
|
||||
"195": 0
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -0.108
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.054,
|
||||
"trailing_stop_positive_offset": 0.12,
|
||||
"trailing_only_offset_is_reached": false
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-05-17 17:07:27.574446+00:00"
|
||||
}
|
||||
@ -1,193 +0,0 @@
|
||||
from freqtrade.strategy import IStrategy
|
||||
from pandas import DataFrame
|
||||
import talib.abstract as ta
|
||||
from typing import Dict, List, Optional, Union
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.strategy import CategoricalParameter, DecimalParameter, IntParameter
|
||||
from datetime import datetime
|
||||
|
||||
class TheForceV7(IStrategy):
|
||||
# 基础参数
|
||||
timeframe = '5m'
|
||||
use_exit_signal = True
|
||||
exit_profit_only = False
|
||||
ignore_roi_if_entry_signal = False
|
||||
|
||||
# # Hyperopt 参数
|
||||
# stoploss = DecimalParameter(
|
||||
# low=-0.3, high=-0.1, default=-0.233, decimals=3, space='`stoploss'
|
||||
# )
|
||||
# profit_threshold_multiplier = DecimalParameter(
|
||||
# low=0.1, high=1.0, default=0.5, decimals=3, space='stoploss'
|
||||
# )
|
||||
# trailing_stop_multiplier = DecimalParameter(
|
||||
# low=0.5, high=3.0, default=1.5, decimals=3, space='stoploss'
|
||||
# )
|
||||
|
||||
# Hyperopt 参数
|
||||
stoploss = DecimalParameter(low=-0.3, high=-0.1, default=-0.233, decimals=3, space='stoploss')
|
||||
profit_threshold_multiplier = DecimalParameter(low=0.2, high=1.0, default=0.5, decimals=3, space='stoploss') # 扩大范围
|
||||
trailing_stop_multiplier = DecimalParameter(low=0.8, high=3.0, default=1.5, decimals=3, space='stoploss') # 扩大范围
|
||||
|
||||
# Hyperopt 参数
|
||||
stoploss = DecimalParameter(-0.3, -0.05, default=-0.15, decimals=3, space='stoploss')
|
||||
profit_threshold_multiplier = DecimalParameter(0.8, 3.0, default=1.5, decimals=3, space='stoploss')
|
||||
trailing_stop_multiplier = DecimalParameter(1.5, 6.0, default=3.0, decimals=3, space='stoploss')
|
||||
adx_buy = DecimalParameter(15, 35, default=25, decimals=0, space='buy')
|
||||
atr_ratio = DecimalParameter(0.002, 0.01, default=0.005, decimals=3, space='buy')
|
||||
rsi_sell = DecimalParameter(50, 70, default=60, decimals=0, space='sell')
|
||||
ema_fast_period = IntParameter(3, 10, default=7, space='sell')
|
||||
|
||||
|
||||
@property
|
||||
def protections(self):
|
||||
return [
|
||||
{
|
||||
"method": "CooldownPeriod",
|
||||
"stop_duration_candles": 5 # 卖出后禁止再次买入的K线数
|
||||
},
|
||||
{
|
||||
"method": "MaxDrawdown",
|
||||
"lookback_period_candles": 48,
|
||||
"trade_limit": 20,
|
||||
"stop_duration_candles": 4,
|
||||
"max_allowed_drawdown": 0.2 # 最大允许回撤 20%
|
||||
},
|
||||
{
|
||||
"method": "StoplossGuard",
|
||||
"lookback_period_candles": 24,
|
||||
"trade_limit": 4, # 在 lookback 内最多触发几次止损
|
||||
"stop_duration_candles": 2, # 锁定多少根 K 线
|
||||
"only_per_pair": False # 是否按币种统计
|
||||
},
|
||||
{
|
||||
"method": "LowProfitPairs",
|
||||
"lookback_period_candles": 6,
|
||||
"trade_limit": 2,
|
||||
"stop_duration_candles": 60,
|
||||
"required_profit": 0.02
|
||||
},
|
||||
{
|
||||
"method": "LowProfitPairs",
|
||||
"lookback_period_candles": 24,
|
||||
"trade_limit": 4,
|
||||
"stop_duration_candles": 2,
|
||||
"required_profit": 0.01
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# Calculate ATR (14-period, consistent with your code)
|
||||
|
||||
# Store the latest ATR in metadata for the pair
|
||||
|
||||
dataframe['ema200c'] = ta.EMA(dataframe['close'], timeperiod=200)
|
||||
dataframe['ema50c'] = ta.EMA(dataframe['close'], timeperiod=50)
|
||||
dataframe['ema20c'] = ta.EMA(dataframe['close'], timeperiod=20)
|
||||
dataframe['rsi7'] = ta.RSI(dataframe['close'], timeperiod=7)
|
||||
macd = ta.MACD(dataframe['close'])
|
||||
dataframe['macd'] = macd[0]
|
||||
dataframe['macdsignal'] = macd[1]
|
||||
stoch = ta.STOCH(dataframe['high'], dataframe['low'], dataframe['close'], fastk_period=14, slowk_period=3, slowd_period=3)
|
||||
dataframe['slowk'] = stoch[0]
|
||||
dataframe['slowd'] = stoch[1]
|
||||
dataframe['volvar'] = dataframe['volume'].rolling(window=20).mean()
|
||||
|
||||
dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
|
||||
dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
|
||||
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
|
||||
for period in [self.ema_fast_period.value, 21, 50]:
|
||||
dataframe[f'ema_{period}'] = ta.EMA(dataframe, timeperiod=period)
|
||||
metadata['latest_atr'] = dataframe['atr'].iloc[-1]
|
||||
metadata['latest_adx'] = dataframe['adx'].iloc[-1]
|
||||
|
||||
return dataframe
|
||||
|
||||
def crossover(self, series1: DataFrame, series2: DataFrame) -> DataFrame:
|
||||
"""Detects when series1 crosses above series2."""
|
||||
return (series1 > series2) & (series1.shift(1) <= series2.shift(1))
|
||||
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
dataframe.loc[
|
||||
(dataframe['close'] > dataframe['ema200c']) & # Relaxed trend
|
||||
(dataframe['close'] > dataframe['ema50c']) & # Short-term trend
|
||||
(dataframe['rsi7'] < 50) & # Relaxed RSI
|
||||
(dataframe['macd'] > 0) & # Relaxed MACD
|
||||
(dataframe['volume'] > dataframe['volvar'] * 0.5) & # Relaxed volume
|
||||
(dataframe['adx'] > 21), # Trend strength
|
||||
'enter_long'
|
||||
] = 1
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
dataframe.loc[
|
||||
(
|
||||
(dataframe['slowk'] > 65) | (dataframe['slowd'] > 65) | # Relaxed STOCH
|
||||
(dataframe['rsi7'] > 70) # Overbought
|
||||
) &
|
||||
(dataframe['close'] < dataframe['ema20c']) & # Trend reversal
|
||||
(self.crossover(dataframe['macdsignal'], dataframe['macd'])) & # Custom crossover
|
||||
(dataframe['macd'] < 0), # Downtrend
|
||||
'exit_long'
|
||||
] = 1
|
||||
|
||||
return dataframe
|
||||
|
||||
def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, after_fill: bool, **kwargs) -> Optional[float]:
|
||||
atr = kwargs.get('metadata', {}).get('latest_atr', 0.01 * current_rate)
|
||||
adx = kwargs.get('metadata', {}).get('latest_adx', 0)
|
||||
atr_percent = atr / current_rate
|
||||
profit_threshold = float(self.profit_threshold_multiplier.value) * atr_percent
|
||||
trailing_stop_distance = float(self.trailing_stop_multiplier.value) * atr_percent
|
||||
trade_duration = (current_time - trade.open_date).total_seconds() / 3600
|
||||
|
||||
# 动态调整
|
||||
if trade_duration < 3: # 3小时内放宽
|
||||
profit_threshold *= 1.5 # 提高触发门槛
|
||||
trailing_stop_distance *= 1.5 # 放宽止损距离
|
||||
if adx > 35: # 强趋势
|
||||
trailing_stop_distance *= 0.5 # 紧跟趋势
|
||||
elif adx < 20: # 震荡市场
|
||||
trailing_stop_distance *= 2.0 # 放宽止损
|
||||
|
||||
# ATR 追踪止损
|
||||
if adx > 35 and after_fill and current_profit > profit_threshold:
|
||||
return -trailing_stop_distance
|
||||
# 固定止损
|
||||
elif trade_duration > 1.5 or adx < 20 or current_profit < -0.015: # 1.5小时,震荡,亏损>1.5%
|
||||
return float(self.stoploss)
|
||||
return -0.05 # 默认止损收紧
|
||||
|
||||
@staticmethod
|
||||
def hyperopt_loss_function(results: DataFrame, trade_count: int, min_date: datetime, max_date: datetime, config: Dict, processed: Dict[str, DataFrame], *args, **kwargs) -> float:
|
||||
total_profit = results['profit_abs'].sum()
|
||||
win_rate = len(results[results['profit_abs'] > 0]) / trade_count if trade_count > 0 else 0
|
||||
avg_duration = results['trade_duration'].mean() / 60 # 分钟
|
||||
loss = -total_profit * win_rate * (1 / (avg_duration + 1))
|
||||
return loss
|
||||
|
||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
||||
proposed_stake: float, min_stake: float, max_stake: float,
|
||||
leverage: float, entry_tag: Optional[str], side: str,
|
||||
**kwargs) -> float:
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
if dataframe.empty:
|
||||
return proposed_stake
|
||||
|
||||
atr = ta.ATR(dataframe, timeperiod=28).iloc[-1]
|
||||
price_std = dataframe['close'].std()
|
||||
combined_volatility = atr + price_std
|
||||
|
||||
base_stake = self.wallets.get_total_stake_amount() * 0.0333 # 3.33% risk
|
||||
base_stake = min(base_stake, 50.0) # Cap at 50 USDT
|
||||
|
||||
risk_factor = 1.0
|
||||
if combined_volatility > current_rate * 0.03: # High volatility
|
||||
risk_factor = 0.3 if pair in ['SOL/USDT', 'OKB/USDT'] else 0.5
|
||||
elif combined_volatility < current_rate * 0.01: # Low volatility
|
||||
risk_factor = 1.2 if pair in ['BTC/USDT', 'ETH/USDT'] else 1.0
|
||||
|
||||
return base_stake * risk_factor
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
{
|
||||
"strategy_name": "FreqaiPrimer",
|
||||
"params": {
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 4
|
||||
},
|
||||
"buy": {
|
||||
"buy_rsi": 45.2500884290867
|
||||
},
|
||||
"sell": {
|
||||
"sell_rsi": 75.2500884290867
|
||||
},
|
||||
"protection": {},
|
||||
"roi": {
|
||||
"0": 0.20400000000000001,
|
||||
"18": 0.07100000000000001,
|
||||
"47": 0.03,
|
||||
"102": 0
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -0.07
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.237,
|
||||
"trailing_stop_positive_offset": 0.267,
|
||||
"trailing_only_offset_is_reached": false
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-05-17 11:42:41.193338+00:00"
|
||||
}
|
||||
@ -1,279 +0,0 @@
|
||||
import logging
|
||||
import numpy as np
|
||||
from functools import reduce
|
||||
import talib.abstract as ta
|
||||
from pandas import DataFrame
|
||||
from technical import qtpylib
|
||||
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class FreqaiPrimer(IStrategy):
|
||||
minimal_roi = {
|
||||
0: 0.135,
|
||||
9: 0.052,
|
||||
15: 0.007,
|
||||
60: 0
|
||||
}
|
||||
stoploss = -0.263
|
||||
trailing_stop = True
|
||||
trailing_stop_positive = 0.324
|
||||
trailing_stop_positive_offset = 0.411
|
||||
trailing_only_offset_is_reached = False
|
||||
max_open_trades = 4
|
||||
process_only_new_candles = True
|
||||
use_exit_signal = True
|
||||
startup_candle_count: int = 40
|
||||
can_short = False
|
||||
|
||||
buy_rsi = IntParameter(low=10, high=50, default=30, space="buy", optimize=False, load=True)
|
||||
sell_rsi = IntParameter(low=50, high=90, default=70, space="sell", optimize=False, load=True)
|
||||
roi_0 = DecimalParameter(low=0.01, high=0.2, default=0.135, space="roi", optimize=True, load=True)
|
||||
roi_15 = DecimalParameter(low=0.005, high=0.1, default=0.052, space="roi", optimize=True, load=True)
|
||||
roi_30 = DecimalParameter(low=0.001, high=0.05, default=0.007, space="roi", optimize=True, load=True)
|
||||
stoploss_param = DecimalParameter(low=-0.35, high=-0.1, default=-0.263, space="stoploss", optimize=True, load=True)
|
||||
trailing_stop_positive_param = DecimalParameter(low=0.1, high=0.5, default=0.324, space="trailing", optimize=True, load=True)
|
||||
trailing_stop_positive_offset_param = DecimalParameter(low=0.2, high=0.6, default=0.411, space="trailing", optimize=True, load=True)
|
||||
|
||||
freqai_info = {
|
||||
"model": "LightGBMRegressor",
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["5m", "15m", "1h"],
|
||||
"include_corr_pairlist": [],
|
||||
"label_period_candles": 12,
|
||||
"include_shifted_candles": 3,
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": False,
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 200,
|
||||
"learning_rate": 0.05,
|
||||
"num_leaves": 31,
|
||||
"verbose": -1,
|
||||
},
|
||||
}
|
||||
|
||||
plot_config = {
|
||||
"main_plot": {},
|
||||
"subplots": {
|
||||
"&-buy_rsi": {"&-buy_rsi": {"color": "green"}},
|
||||
"&-sell_rsi": {"&-sell_rsi": {"color": "red"}},
|
||||
"&-stoploss": {"&-stoploss": {"color": "purple"}},
|
||||
"&-roi_0": {"&-roi_0": {"color": "orange"}},
|
||||
"do_predict": {"do_predict": {"color": "brown"}},
|
||||
},
|
||||
}
|
||||
|
||||
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
|
||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
||||
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
|
||||
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
|
||||
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
|
||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=period, stds=2.2)
|
||||
dataframe["bb_lowerband-period"] = bollinger["lower"]
|
||||
dataframe["bb_middleband-period"] = bollinger["mid"]
|
||||
dataframe["bb_upperband-period"] = bollinger["upper"]
|
||||
dataframe["%-bb_width-period"] = (
|
||||
dataframe["bb_upperband-period"] - dataframe["bb_lowerband-period"]
|
||||
) / dataframe["bb_middleband-period"]
|
||||
dataframe["%-close-bb_lower-period"] = dataframe["close"] / dataframe["bb_lowerband-period"]
|
||||
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
|
||||
dataframe["%-relative_volume-period"] = (
|
||||
dataframe["volume"] / dataframe["volume"].rolling(period).mean()
|
||||
)
|
||||
dataframe = dataframe.replace([np.inf, -np.inf], 0)
|
||||
dataframe = dataframe.ffill()
|
||||
dataframe = dataframe.fillna(0)
|
||||
return dataframe
|
||||
|
||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
|
||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
||||
dataframe["%-raw_price"] = dataframe["close"]
|
||||
dataframe = dataframe.replace([np.inf, -np.inf], 0)
|
||||
dataframe = dataframe.ffill()
|
||||
dataframe = dataframe.fillna(0)
|
||||
return dataframe
|
||||
|
||||
def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
|
||||
if len(dataframe["close"]) < 20:
|
||||
logger.warning(f"数据不足 {len(dataframe)} 根 K 线,%-volatility 可能不完整")
|
||||
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
|
||||
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
|
||||
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
|
||||
return dataframe
|
||||
|
||||
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
|
||||
logger.info(f"设置 FreqAI 目标,交易对:{metadata['pair']}")
|
||||
if "close" not in dataframe.columns:
|
||||
logger.error("数据框缺少必要的 'close' 列")
|
||||
raise ValueError("数据框缺少必要的 'close' 列")
|
||||
|
||||
try:
|
||||
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
|
||||
if "%-volatility" not in dataframe.columns:
|
||||
logger.warning("缺少 %-volatility 列,强制重新生成")
|
||||
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
|
||||
|
||||
# 移除 shift(-label_period),改为使用当前及过去的数据
|
||||
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14)
|
||||
dataframe["&-buy_rsi"] = dataframe["&-buy_rsi"].rolling(window=label_period).mean().ffill().bfill()
|
||||
|
||||
for col in ["&-buy_rsi", "%-volatility"]:
|
||||
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
|
||||
dataframe[col] = dataframe[col].ffill()
|
||||
dataframe[col] = dataframe[col].fillna(0)
|
||||
if dataframe[col].isna().any():
|
||||
logger.warning(f"目标列 {col} 仍包含 NaN,数据预览:\n{dataframe[col].tail(10)}")
|
||||
except Exception as e:
|
||||
logger.error(f"创建 FreqAI 目标失败:{str(e)}")
|
||||
raise
|
||||
|
||||
logger.info(f"目标列预览:\n{dataframe[['&-buy_rsi']].head().to_string()}")
|
||||
return dataframe
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
logger.info(f"处理交易对:{metadata['pair']}")
|
||||
logger.debug(f"输入特征列:{list(dataframe.columns)}")
|
||||
dataframe = self.freqai.start(dataframe, metadata, self)
|
||||
logger.debug(f"FreqAI 输出特征列:{list(dataframe.columns)}")
|
||||
|
||||
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
|
||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
||||
dataframe["bb_lowerband"] = bollinger["lower"]
|
||||
dataframe["bb_middleband"] = bollinger["mid"]
|
||||
dataframe["bb_upperband"] = bollinger["upper"]
|
||||
dataframe["tema"] = ta.TEMA(dataframe, timeperiod=9)
|
||||
|
||||
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
|
||||
# 使用滚动窗口而非未来函数来生成 up_or_down 列
|
||||
dataframe["up_or_down"] = np.where(
|
||||
dataframe["close"].rolling(window=label_period).mean() > dataframe["close"], 1, 0
|
||||
)
|
||||
|
||||
if "&-buy_rsi" in dataframe.columns:
|
||||
if "%-volatility" not in dataframe.columns:
|
||||
logger.warning("缺少 %-volatility 列,强制重新生成")
|
||||
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
|
||||
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
|
||||
|
||||
dataframe["&-sell_rsi"] = dataframe["&-buy_rsi"] + 30
|
||||
dataframe["&-stoploss"] = self.stoploss - (dataframe["%-volatility"] * 5).clip(-0.05, 0.05)
|
||||
dataframe["&-roi_0"] = (dataframe["close"].rolling(window=label_period).mean() / dataframe["close"] - 1).clip(0, 0.2)
|
||||
|
||||
for col in ["&-buy_rsi", "&-sell_rsi", "&-stoploss", "&-roi_0"]:
|
||||
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
|
||||
dataframe[col] = dataframe[col].ffill()
|
||||
dataframe[col] = dataframe[col].fillna(0)
|
||||
|
||||
dataframe["buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(5).mean().clip(10, 50)
|
||||
dataframe["sell_rsi_pred"] = dataframe["&-sell_rsi"].rolling(5).mean().clip(50, 90)
|
||||
dataframe["stoploss_pred"] = dataframe["&-stoploss"].clip(-0.35, -0.1)
|
||||
dataframe["roi_0_pred"] = dataframe["&-roi_0"].clip(0.01, 0.2)
|
||||
|
||||
for col in ["buy_rsi_pred", "sell_rsi_pred", "stoploss_pred", "roi_0_pred"]:
|
||||
if dataframe[col].isna().any():
|
||||
logger.warning(f"列 {col} 包含 NaN,填充为默认值")
|
||||
dataframe[col] = dataframe[col].ffill()
|
||||
dataframe[col] = dataframe[col].fillna(dataframe[col].mean())
|
||||
|
||||
dataframe["trailing_stop_positive"] = (dataframe["roi_0_pred"] * 0.5).clip(0.01, 0.3)
|
||||
dataframe["trailing_stop_positive_offset"] = (dataframe["roi_0_pred"] * 0.75).clip(0.02, 0.4)
|
||||
|
||||
self.buy_rsi.value = float(dataframe["buy_rsi_pred"].iloc[-1])
|
||||
self.sell_rsi.value = float(dataframe["sell_rsi_pred"].iloc[-1])
|
||||
self.stoploss = float(self.stoploss_param.value)
|
||||
self.minimal_roi = {
|
||||
0: float(self.roi_0.value),
|
||||
15: float(self.roi_15.value),
|
||||
30: float(self.roi_30.value),
|
||||
60: 0
|
||||
}
|
||||
self.trailing_stop_positive = float(self.trailing_stop_positive_param.value)
|
||||
self.trailing_stop_positive_offset = float(self.trailing_stop_positive_offset_param.value)
|
||||
|
||||
logger.info(f"动态参数:buy_rsi={self.buy_rsi.value}, sell_rsi={self.sell_rsi.value}, "
|
||||
f"stoploss={self.stoploss}, trailing_stop_positive={self.trailing_stop_positive}")
|
||||
else:
|
||||
logger.warning(f"&-buy_rsi 列缺失,跳过 FreqAI 预测逻辑,检查 freqai.start 输出")
|
||||
|
||||
dataframe = dataframe.replace([np.inf, -np.inf], 0)
|
||||
dataframe = dataframe.ffill()
|
||||
dataframe = dataframe.fillna(0)
|
||||
|
||||
logger.info(f"up_or_down 值统计:\n{dataframe['up_or_down'].value_counts().to_string()}")
|
||||
logger.info(f"do_predict 值统计:\n{dataframe['do_predict'].value_counts().to_string()}")
|
||||
logger.debug(f"最终特征列:{list(dataframe.columns)}")
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||
enter_long_conditions = [
|
||||
qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"]),
|
||||
df["tema"] > df["tema"].shift(1),
|
||||
df["volume"] > 0,
|
||||
df["do_predict"] == 1,
|
||||
df["up_or_down"] == 1
|
||||
]
|
||||
if enter_long_conditions:
|
||||
df.loc[
|
||||
reduce(lambda x, y: x & y, enter_long_conditions),
|
||||
["enter_long", "enter_tag"]
|
||||
] = (1, "long")
|
||||
return df
|
||||
|
||||
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||
exit_long_conditions = [
|
||||
qtpylib.crossed_above(df["rsi"], df["sell_rsi_pred"]),
|
||||
(df["close"] < df["close"].shift(1) * 0.97),
|
||||
df["volume"] > 0,
|
||||
df["do_predict"] == 1,
|
||||
df["up_or_down"] == 0
|
||||
]
|
||||
if exit_long_conditions:
|
||||
df.loc[
|
||||
reduce(lambda x, y: x & y, exit_long_conditions),
|
||||
"exit_long"
|
||||
] = 1
|
||||
return df
|
||||
|
||||
def confirm_trade_entry(
|
||||
self, pair: str, order_type: str, amount: float, rate: float,
|
||||
time_in_force: str, current_time, entry_tag, side: str, **kwargs
|
||||
) -> bool:
|
||||
try:
|
||||
df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
if df is None or df.empty:
|
||||
logger.warning(f"无法获取 {pair} 的分析数据,拒绝交易")
|
||||
return False
|
||||
|
||||
last_candle = df.iloc[-1].squeeze()
|
||||
if "close" not in last_candle or np.isnan(last_candle["close"]):
|
||||
logger.warning(f"{pair} 的最新 K 线缺少有效 close 价格,拒绝交易")
|
||||
return False
|
||||
|
||||
if side == "long":
|
||||
max_rate = last_candle["close"] * (1 + 0.0025) # 0.25% 滑点阈值
|
||||
if rate > max_rate:
|
||||
logger.debug(f"拒绝 {pair} 的买入,价格 {rate} 超过最大允许价格 {max_rate}")
|
||||
return False
|
||||
elif side == "short":
|
||||
logger.warning(f"{pair} 尝试做空,但策略不支持做空 (can_short={self.can_short})")
|
||||
return False
|
||||
|
||||
logger.debug(f"确认 {pair} 的交易:side={side}, rate={rate}, close={last_candle['close']}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"确认 {pair} 交易时出错:{str(e)}")
|
||||
return False
|
||||
@ -1 +0,0 @@
|
||||
|
||||
@ -1,130 +0,0 @@
|
||||
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
||||
# flake8: noqa: F401
|
||||
# isort: skip_file
|
||||
# --- Do not remove these libs ---
|
||||
from functools import reduce
|
||||
import numpy as np # noqa
|
||||
import pandas as pd # noqa
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.strategy import (
|
||||
BooleanParameter,
|
||||
CategoricalParameter,
|
||||
DecimalParameter,
|
||||
IStrategy,
|
||||
IntParameter,
|
||||
)
|
||||
|
||||
# --------------------------------
|
||||
# Add your lib to import here
|
||||
import talib.abstract as ta
|
||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
||||
|
||||
|
||||
# This class is a sample. Feel free to customize it.
|
||||
class FAdxSmaStrategy(IStrategy):
|
||||
|
||||
INTERFACE_VERSION = 3
|
||||
timeframe = "1h"
|
||||
# Minimal ROI designed for the strategy.
|
||||
# This attribute will be overridden if the config file contains "minimal_roi".
|
||||
minimal_roi = {"60": 0.075, "30": 0.1, "0": 0.05}
|
||||
# minimal_roi = {"0": 1}
|
||||
|
||||
stoploss = -0.05
|
||||
can_short = False
|
||||
|
||||
# Trailing stoploss
|
||||
trailing_stop = False
|
||||
# trailing_only_offset_is_reached = False
|
||||
# trailing_stop_positive = 0.01
|
||||
# trailing_stop_positive_offset = 0.0 # Disabled / not configured
|
||||
|
||||
# Run "populate_indicators()" only for new candle.
|
||||
process_only_new_candles = True
|
||||
|
||||
# Number of candles the strategy requires before producing valid signals
|
||||
startup_candle_count: int = 14
|
||||
|
||||
# Hyperoptable parameters
|
||||
|
||||
# Define the guards spaces
|
||||
pos_entry_adx = DecimalParameter(15, 40, decimals=1, default=30.0, space="buy")
|
||||
pos_exit_adx = DecimalParameter(15, 40, decimals=1, default=30.0, space="sell")
|
||||
|
||||
# Define the parameter spaces
|
||||
adx_period = IntParameter(4, 24, default=14)
|
||||
sma_short_period = IntParameter(4, 24, default=12)
|
||||
sma_long_period = IntParameter(12, 175, default=48)
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
# Calculate all adx values
|
||||
for val in self.adx_period.range:
|
||||
dataframe[f"adx_{val}"] = ta.ADX(dataframe, timeperiod=val)
|
||||
|
||||
# Calculate all sma_short values
|
||||
for val in self.sma_short_period.range:
|
||||
dataframe[f"sma_short_{val}"] = ta.SMA(dataframe, timeperiod=val)
|
||||
|
||||
# Calculate all sma_long values
|
||||
for val in self.sma_long_period.range:
|
||||
dataframe[f"sma_long_{val}"] = ta.SMA(dataframe, timeperiod=val)
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
conditions_long = []
|
||||
conditions_short = []
|
||||
|
||||
# GUARDS AND TRIGGERS
|
||||
conditions_long.append(
|
||||
dataframe[f"adx_{self.adx_period.value}"] > self.pos_entry_adx.value
|
||||
)
|
||||
conditions_short.append(
|
||||
dataframe[f"adx_{self.adx_period.value}"] > self.pos_entry_adx.value
|
||||
)
|
||||
|
||||
conditions_long.append(
|
||||
qtpylib.crossed_above(
|
||||
dataframe[f"sma_short_{self.sma_short_period.value}"],
|
||||
dataframe[f"sma_long_{self.sma_long_period.value}"],
|
||||
)
|
||||
)
|
||||
conditions_short.append(
|
||||
qtpylib.crossed_below(
|
||||
dataframe[f"sma_short_{self.sma_short_period.value}"],
|
||||
dataframe[f"sma_long_{self.sma_long_period.value}"],
|
||||
)
|
||||
)
|
||||
|
||||
dataframe.loc[
|
||||
reduce(lambda x, y: x & y, conditions_long),
|
||||
"enter_long",
|
||||
] = 1
|
||||
|
||||
dataframe.loc[
|
||||
reduce(lambda x, y: x & y, conditions_short),
|
||||
"enter_short",
|
||||
] = 1
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
conditions_close = []
|
||||
conditions_close.append(
|
||||
dataframe[f"adx_{self.adx_period.value}"] < self.pos_entry_adx.value
|
||||
)
|
||||
|
||||
dataframe.loc[
|
||||
reduce(lambda x, y: x & y, conditions_close),
|
||||
"exit_long",
|
||||
] = 1
|
||||
|
||||
dataframe.loc[
|
||||
reduce(lambda x, y: x & y, conditions_close),
|
||||
"exit_short",
|
||||
] = 1
|
||||
|
||||
return dataframe
|
||||
Loading…
x
Reference in New Issue
Block a user