这个分支貌似没有太大优化空间, 或者回头换grok
This commit is contained in:
parent
021c0ab8db
commit
3b5e518d7d
8302
ccxt/async_support/okx.py
Normal file
8302
ccxt/async_support/okx.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -60,49 +60,6 @@
|
||||
"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": ["5m", "1h"],
|
||||
"include_corr_pairlist": ["BTC/USDT"],
|
||||
"label_period_candles": 10,
|
||||
"use_SVM_to_remove_outliers": true,
|
||||
"principal_component_analysis": true
|
||||
},
|
||||
"model": "XGBoostRegressor",
|
||||
"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
|
||||
}
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": true,
|
||||
"listen_ip_address": "0.0.0.0",
|
||||
|
||||
@ -11,38 +11,9 @@
|
||||
},
|
||||
"pair_whitelist": ["OKB/USDT", "SOL/USDT"]
|
||||
},
|
||||
"pairlists": [
|
||||
{
|
||||
"method": "StaticPairList"
|
||||
}
|
||||
],
|
||||
|
||||
"timeframe": "15m",
|
||||
"strategy": "NostalgiaForInfinityV8",
|
||||
"freqai": {
|
||||
"enabled": true,
|
||||
"freqaimodel": "LightGBMRegressor",
|
||||
"train_period_days": 7,
|
||||
"backtest_period_days": 0.2,
|
||||
"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"],
|
||||
"DI_threshold": 0.3
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2,
|
||||
"shuffle": false
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 100,
|
||||
"learning_rate": 0.1,
|
||||
"num_leaves": 15,
|
||||
"verbose": -1
|
||||
}
|
||||
},
|
||||
"order_types": {
|
||||
"entry": "market",
|
||||
"exit": "market",
|
||||
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
"tradable_balance_ratio": 1,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": true,
|
||||
"timeframe": "3m",
|
||||
"timeframe": "5m",
|
||||
"dry_run_wallet": 1000,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"stoploss": -0.085,
|
||||
@ -87,7 +87,7 @@
|
||||
},
|
||||
"feature_parameters": {
|
||||
"include_timeframes": [
|
||||
"3m",
|
||||
"5m",
|
||||
"15m",
|
||||
"1h"
|
||||
],
|
||||
@ -99,7 +99,7 @@
|
||||
"include_shifted_candles": 5,
|
||||
"DI_threshold": 0.7,
|
||||
"weight_factor": 0.9,
|
||||
"principal_component_analysis": false,
|
||||
"principal_component_analysis": true,
|
||||
"use_SVM_to_remove_outliers": true,
|
||||
"plot_feature_importances": 10,
|
||||
"indicator_periods_candles": [
|
||||
@ -109,13 +109,15 @@
|
||||
]
|
||||
},
|
||||
"data_split_parameters": {
|
||||
"test_size": 0.2
|
||||
"test_size": 0.2,
|
||||
"shuffle": false,
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 100,
|
||||
"learning_rate": 0.05,
|
||||
"num_leaves": 31,
|
||||
"max_depth": 5,
|
||||
"num_leaves": 31
|
||||
"verbose": 1
|
||||
}
|
||||
},
|
||||
"api_server": {
|
||||
|
||||
@ -1,121 +0,0 @@
|
||||
{
|
||||
"strategy": "TheForceFreqaiStrategy",
|
||||
"timeframe": "3m",
|
||||
"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"],
|
||||
"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": "TheForceV7_FreqAI",
|
||||
"save_backtest_models": true,
|
||||
"live_retrain": false,
|
||||
"purge_old_models": true,
|
||||
"fit_live_predictions_candles": 50,
|
||||
"force_train": true,
|
||||
"verbose": 2,
|
||||
"train_period_days": 60,
|
||||
"backtest_period_days": 14,
|
||||
"feature_parameters": {
|
||||
"include_timeframes": ["3m", "15m"],
|
||||
"label_period_candles": 12,
|
||||
"include_shifted_candles": 2,
|
||||
"include_corr_pairlist": [],
|
||||
"include_shifted_candles": 5,
|
||||
"DI_threshold": 1.5,
|
||||
"indicator_periods_candles": [10, 20, 50],
|
||||
"include_default_features": [
|
||||
"open", "high", "low", "close", "volume",
|
||||
"sma", "ema", "rsi", "macd", "bollinger_bands"
|
||||
],
|
||||
"use_SVM_to_remove_outliers": true,
|
||||
"plot_feature_importances": 10,
|
||||
"feature_selection": {
|
||||
"method": "variance_threshold",
|
||||
"threshold": 0.01
|
||||
}
|
||||
},
|
||||
"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
|
||||
}
|
||||
},
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": 150,
|
||||
"stoploss": -0.15,
|
||||
"minimal_roi": {
|
||||
"0": 0.05,
|
||||
"60": 0.03,
|
||||
"120": 0.01
|
||||
},
|
||||
"startup_candle_count": 100,
|
||||
|
||||
"max_open_trades": 4,
|
||||
"use_exit_signal": true,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15,
|
||||
"unit": "minutes"
|
||||
},
|
||||
"export": "trades",
|
||||
"cache": "none",
|
||||
"loglevel": "DEBUG",
|
||||
"verbosity": 2
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
{
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 3,
|
||||
"stake_amount": 15,
|
||||
"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": 0.25,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": false,
|
||||
"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": "314e75b0-1113-47e8-ad01-1fca7e3c0496",
|
||||
"secret": "9C8B170390F46EA6FB87592AD46F5A34",
|
||||
"password": "nekFoylf:Om0",
|
||||
"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", "OKB/USDT", "TON/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": "admin"
|
||||
},
|
||||
"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"]
|
||||
}
|
||||
@ -23,6 +23,7 @@ services:
|
||||
- "./config_examples:/freqtrade/config_examples"
|
||||
- "./freqtrade/templates:/freqtrade/templates"
|
||||
- "./freqtrade/exchange/:/freqtrade/exchange"
|
||||
- "./ccxt/async_support/okx.py:/home/ftuser/.local/lib/python3.12/site-packages/ccxt/async_support/okx.py"
|
||||
# Expose api on port 8080 (localhost only)
|
||||
# Please read the https://www.freqtrade.io/en/stable/rest-api/ documentation
|
||||
# for more information.
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
{
|
||||
"strategy_name": "TheForceV7",
|
||||
"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,200 +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, timezone
|
||||
|
||||
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
|
||||
# Ensure both datetimes are timezone-aware
|
||||
if trade.open_date.tzinfo is None:
|
||||
trade_open_date = trade.open_date.replace(tzinfo=timezone.utc)
|
||||
else:
|
||||
trade_open_date = trade.open_date
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ class FreqaiPrimer(IStrategy):
|
||||
15: 0.007,
|
||||
60: 0
|
||||
}
|
||||
stoploss = -0.263
|
||||
stoploss = -0.085
|
||||
trailing_stop = True
|
||||
trailing_stop_positive = 0.324
|
||||
trailing_stop_positive_offset = 0.411
|
||||
@ -31,7 +31,7 @@ class FreqaiPrimer(IStrategy):
|
||||
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)
|
||||
stoploss_param = DecimalParameter(low=-0.15, high=-0.05, default=-0.075, 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)
|
||||
|
||||
@ -64,7 +64,26 @@ class FreqaiPrimer(IStrategy):
|
||||
"&-roi_0": {"&-roi_0": {"color": "orange"}},
|
||||
"do_predict": {"do_predict": {"color": "brown"}},
|
||||
},
|
||||
}
|
||||
},
|
||||
protections = [
|
||||
{
|
||||
"name": "CooldownPeriod",
|
||||
"stop_duration": 60, # 单位:分钟
|
||||
"trade_limit": 1,
|
||||
"only_per_pair": False
|
||||
},
|
||||
{
|
||||
"name": "StoplossGuard",
|
||||
"lookback_period": 60, # 查看过去 60 分钟内
|
||||
"trade_limit": 2, # 最多允许触发 2 次止损
|
||||
"stop_duration": 30 # 如果超过限制,暂停交易 30 分钟
|
||||
},
|
||||
{
|
||||
"name": "LowProfit",
|
||||
"lookback_period": 20,
|
||||
"required_profit": 0.01 # 要求至少盈利 1%
|
||||
}
|
||||
]
|
||||
|
||||
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
|
||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
||||
@ -277,3 +296,12 @@ class FreqaiPrimer(IStrategy):
|
||||
except Exception as e:
|
||||
logger.error(f"确认 {pair} 交易时出错:{str(e)}")
|
||||
return False
|
||||
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, **kwargs) -> float:
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1]
|
||||
|
||||
# 如果市场波动率高,收紧止损
|
||||
if last_candle["%-volatility"] > 0.05:
|
||||
return -0.05 # 更严格止损
|
||||
|
||||
return -0.08 # 默认止损
|
||||
|
||||
@ -37,7 +37,8 @@ hyperopt_config="${STRATEGY_NAME%.py}.json"
|
||||
|
||||
echo "docker-compose run --rm freqtrade backtesting \
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log \
|
||||
--freqaimodel LightGBMRegressor \
|
||||
--freqaimodel LightGBMRegressorMultiTarget \
|
||||
--enable-protections \
|
||||
--config /freqtrade/config_examples/$CONFIG_FILE \
|
||||
--strategy-path /freqtrade/templates \
|
||||
--strategy $STRATEGY_NAME \
|
||||
@ -47,7 +48,8 @@ echo "docker-compose run --rm freqtrade backtesting \
|
||||
|
||||
docker-compose run --rm freqtrade backtesting \
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log \
|
||||
--freqaimodel LightGBMRegressor \
|
||||
--freqaimodel LightGBMRegressorMultiTarget \
|
||||
--enable-protections \
|
||||
--config /freqtrade/config_examples/$CONFIG_FILE \
|
||||
--strategy-path /freqtrade/templates \
|
||||
--strategy $STRATEGY_NAME \
|
||||
|
||||
@ -73,7 +73,7 @@ GIT_COMMIT_SHORT=$(git rev-parse HEAD | cut -c 1-8)
|
||||
echo "docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log \
|
||||
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \
|
||||
--freqaimodel LightGBMRegressor \
|
||||
--freqaimodel LightGBMRegressorMultiTarget \
|
||||
--config /freqtrade/config_examples/$CONFIG_FILE \
|
||||
--strategy $STRATEGY_NAME \
|
||||
--fee 0.0008 \
|
||||
@ -82,7 +82,7 @@ echo "docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p
|
||||
docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log \
|
||||
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \
|
||||
--freqaimodel LightGBMRegressor \
|
||||
--freqaimodel LightGBMRegressorMultiTarget \
|
||||
--config /freqtrade/config_examples/$CONFIG_FILE \
|
||||
--strategy $STRATEGY_NAME \
|
||||
--fee 0.0008 \
|
||||
|
||||
@ -34,7 +34,8 @@ rm -fr ./user_data/dryrun_results/*
|
||||
#docker-compose -f docker-compose_backtest.yml run --rm freqtrade >output.log 2>&1
|
||||
echo "docker-compose run --rm freqtrade hyperopt \
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log \
|
||||
--freqaimodel LightGBMRegressor \
|
||||
--freqaimodel LightGBMRegressorMultiTarget \
|
||||
--enable-protections \
|
||||
--strategy $STRATEGY_NAME \
|
||||
--config /freqtrade/config_examples/$CONFIG_FILE \
|
||||
--strategy-path /freqtrade/templates \
|
||||
@ -45,7 +46,8 @@ echo "docker-compose run --rm freqtrade hyperopt \
|
||||
--fee 0.0016"
|
||||
docker-compose run --rm freqtrade hyperopt \
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log \
|
||||
--freqaimodel LightGBMRegressor \
|
||||
--freqaimodel LightoGBMRegressorMultiTarget \
|
||||
--enable-protections \
|
||||
--strategy $STRATEGY_NAME \
|
||||
--config /freqtrade/config_examples/$CONFIG_FILE \
|
||||
--strategy-path /freqtrade/templates \
|
||||
|
||||
@ -73,7 +73,7 @@ GIT_COMMIT_SHORT=$(git rev-parse HEAD | cut -c 1-8)
|
||||
echo "docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log \
|
||||
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \
|
||||
--freqaimodel LightGBMRegressor \
|
||||
--freqaimodel LightGBMRegressorMultiTarget \
|
||||
--fee 0.0008
|
||||
--config /freqtrade/config_examples/$CONFIG_FILE \
|
||||
--strategy $STRATEGY_NAME \
|
||||
@ -82,7 +82,7 @@ echo "docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p
|
||||
docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log \
|
||||
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \
|
||||
--freqaimodel LightGBMRegressor \
|
||||
--freqaimodel LightGBMRegressorMultiTarget \
|
||||
--fee 0.0008 \
|
||||
--config /freqtrade/config_examples/$CONFIG_FILE \
|
||||
--strategy $STRATEGY_NAME \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user