not work NostalgiaV8
This commit is contained in:
parent
17199e9a44
commit
62b9fed359
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
# Freqtrade rules
|
||||
config*.json
|
||||
*.sqlite
|
||||
*.sqlite-shm
|
||||
*.sqlite-wal
|
||||
|
||||
59
config_examples/confg_base_hyperopt.json
Normal file
59
config_examples/confg_base_hyperopt.json
Normal file
@ -0,0 +1,59 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
84
config_examples/config.json
Normal file
84
config_examples/config.json
Normal file
@ -0,0 +1,84 @@
|
||||
{
|
||||
"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": "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",
|
||||
"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
|
||||
}
|
||||
127
config_examples/config_adsf.json
Normal file
127
config_examples/config_adsf.json
Normal file
@ -0,0 +1,127 @@
|
||||
{
|
||||
"$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"
|
||||
}
|
||||
}
|
||||
@ -30,12 +30,22 @@ services:
|
||||
# Default command used when running `docker compose up`
|
||||
|
||||
# --freqaimodel XGBoostRegressor
|
||||
command: >
|
||||
trade
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log
|
||||
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
|
||||
--freqaimodel LightGBMRegressor
|
||||
--config /freqtrade/config_examples/config_freqai.okx.json
|
||||
--strategy FreqaiExampleStrategy
|
||||
--strategy-path /freqtrade/templates
|
||||
# command: >
|
||||
# trade
|
||||
# --logfile /freqtrade/user_data/logs/freqtrade.log
|
||||
# --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
|
||||
# --freqaimodel LightGBMRegressor
|
||||
# --config /freqtrade/config_examples/config_freqai.okx.json
|
||||
# --strategy FreqaiExampleStrategy
|
||||
# --strategy-path /freqtrade/templates
|
||||
|
||||
command: >
|
||||
backtesting
|
||||
--logfile /freqtrade/user_data/logs/freqtrade.log
|
||||
--config /freqtrade/config_examples/config_adsf.json
|
||||
--strategy-path /freqtrade/templates
|
||||
--freqaimodel LightGBMRegressor
|
||||
--strategy NostalgiaForInfinityV8
|
||||
--timerange 20250401-20250415
|
||||
--fee 0.0008
|
||||
--cache none
|
||||
|
||||
7
filter.py
Normal file
7
filter.py
Normal file
@ -0,0 +1,7 @@
|
||||
with open('output.log', 'r') as input_file, open('output_filted.log', 'w') as output_file:
|
||||
for line in input_file:
|
||||
if "validation_0" in line:
|
||||
if "[99]" in line:
|
||||
output_file.write(line)
|
||||
else:
|
||||
output_file.write(line)
|
||||
248
freqtrade/templates/NostalgiaV8.py
Normal file
248
freqtrade/templates/NostalgiaV8.py
Normal file
@ -0,0 +1,248 @@
|
||||
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
|
||||
69
freqtrade/templates/Supertrend.py
Normal file
69
freqtrade/templates/Supertrend.py
Normal file
@ -0,0 +1,69 @@
|
||||
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
|
||||
85
freqtrade/templates/chat.md
Normal file
85
freqtrade/templates/chat.md
Normal file
@ -0,0 +1,85 @@
|
||||
> 请把当前策略的运行逻辑进行梳理和讲解
|
||||
|
||||
我来为您梳理和讲解这个策略的运行逻辑。这是一个基于 FreqAI 的机器学习交易策略,主要使用 RSI 指标和机器学习模型进行交易决策。以下是策略的主要逻辑:
|
||||
|
||||
### 1. 策略配置
|
||||
```python
|
||||
minimal_roi = {
|
||||
"0": 0.02,
|
||||
"7": 0.01,
|
||||
"13": 0.005,
|
||||
"60": 0
|
||||
}
|
||||
stoploss = 0.0
|
||||
trailing_stop = True
|
||||
```
|
||||
- 设置了静态的 ROI 目标
|
||||
- 启用了追踪止损
|
||||
|
||||
### 2. 特征工程
|
||||
策略通过多个方法构建特征:
|
||||
- `feature_engineering_expand_all`: 计算 RSI 和布林带宽度
|
||||
- `feature_engineering_expand_basic`: 计算价格变化百分比
|
||||
- `feature_engineering_standard`: 计算波动率和时间特征
|
||||
|
||||
### 3. 目标变量设置
|
||||
在 `set_freqai_targets` 方法中:
|
||||
- 使用未来 `label_period_candles` 周期的 RSI 值作为目标变量
|
||||
- 计算并标准化波动率特征
|
||||
|
||||
### 4. 指标计算
|
||||
`populate_indicators` 方法中计算了多个技术指标:
|
||||
- RSI
|
||||
- 波动率
|
||||
- TEMA(三重指数移动平均线)
|
||||
- 布林带下轨
|
||||
- 未来价格方向(up_or_down)
|
||||
|
||||
### 5. 机器学习模型
|
||||
使用 LightGBM 回归模型:
|
||||
```python
|
||||
freqai_info = {
|
||||
"model": "LightGBMRegressor",
|
||||
"feature_parameters": {...},
|
||||
"data_split_parameters": {...},
|
||||
"model_training_parameters": {...}
|
||||
}
|
||||
```
|
||||
- 模型预测买入和卖出的 RSI 值
|
||||
- 使用 SOL/USDT 作为相关交易对
|
||||
|
||||
### 6. 入场逻辑
|
||||
`populate_entry_trend` 方法中:
|
||||
- 当实际 RSI 上穿预测的买入 RSI 时
|
||||
- TEMA 指标向上
|
||||
- 交易量大于 0
|
||||
- 模型预测结果为 1
|
||||
- 未来价格方向为上涨
|
||||
|
||||
### 7. 出场逻辑
|
||||
`populate_exit_trend` 方法中:
|
||||
- 当实际 RSI 上穿预测的卖出 RSI 时
|
||||
- 或价格下跌超过 2%
|
||||
- 或价格跌破布林带下轨
|
||||
- 或持有时间超过 1 天
|
||||
|
||||
### 8. 交易确认
|
||||
`confirm_trade_entry` 方法:
|
||||
- 检查当前价格是否在可接受范围内
|
||||
- 记录交易确认信息
|
||||
|
||||
### 策略特点
|
||||
1. 机器学习驱动:使用 LightGBM 模型预测 RSI 值
|
||||
2. 多特征融合:结合技术指标、波动率和时间特征
|
||||
3. 风险控制:设置了 ROI 目标和追踪止损
|
||||
4. 动态调整:通过机器学习模型动态调整交易信号
|
||||
|
||||
### 运行流程
|
||||
1. 数据准备:获取历史数据,计算技术指标
|
||||
2. 特征工程:构建机器学习特征
|
||||
3. 模型训练:使用历史数据训练 LightGBM 模型
|
||||
4. 信号生成:根据模型预测结果生成交易信号
|
||||
5. 交易执行:根据入场和出场逻辑执行交易
|
||||
6. 风险控制:根据 ROI 和止损规则管理仓位
|
||||
|
||||
这个策略结合了传统技术分析和机器学习方法,通过模型预测来增强交易信号的准确性,同时保持了严格的风险控制机制。
|
||||
1
freqtrade/templates/harmonicDivergence.py
Normal file
1
freqtrade/templates/harmonicDivergence.py
Normal file
@ -0,0 +1 @@
|
||||
|
||||
0
freqtrade/templates/hyper.py
Normal file
0
freqtrade/templates/hyper.py
Normal file
130
freqtrade/templates/sma.py
Normal file
130
freqtrade/templates/sma.py
Normal file
@ -0,0 +1,130 @@
|
||||
# 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
|
||||
30
run.sh
Executable file
30
run.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm -rf user_data/models/*
|
||||
rm -rf ./freqtrade/user_data/data/backtest_results/*
|
||||
|
||||
docker-compose run --rm freqtrade >output.log 2>&1
|
||||
sed -i 's/\x1B\[[0-9;]*m//g' output.log
|
||||
python3 filter.py
|
||||
|
||||
rm ./result/* -fr
|
||||
mv ./user_data/backtest_results/* ./result/
|
||||
|
||||
cd ./result
|
||||
# 查找当前目录下的所有 zip 文件
|
||||
zip_files=(*.zip)
|
||||
|
||||
# 检查是否只有一个 zip 文件
|
||||
if [ ${#zip_files[@]} -eq 1 ]; then
|
||||
# 解压缩该 zip 文件到当前目录
|
||||
unzip "${zip_files[0]}"
|
||||
rm *.zip
|
||||
rm *.feather
|
||||
else
|
||||
echo "当前目录下没有 zip 文件或者有多个 zip 文件,无法操作。"
|
||||
fi
|
||||
|
||||
cd -
|
||||
sed -i 's/\x1B\[[0-9;]*m//g' output.log
|
||||
python3 filter.py
|
||||
cp output_filted.log result/ -f
|
||||
129
tests/config_test_comments.json
Normal file
129
tests/config_test_comments.json
Normal file
@ -0,0 +1,129 @@
|
||||
{
|
||||
/* Single-line C-style comment */
|
||||
"max_open_trades": 3,
|
||||
/*
|
||||
* Multi-line C-style comment
|
||||
*/
|
||||
"stake_currency": "BTC",
|
||||
"stake_amount": 0.05,
|
||||
"fiat_display_currency": "USD", // C++-style comment
|
||||
"amount_reserve_percent": 0.05, // And more, tabs before this comment
|
||||
"dry_run": false,
|
||||
"timeframe": "5m",
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": 0.005,
|
||||
"trailing_stop_positive_offset": 0.0051,
|
||||
"trailing_only_offset_is_reached": false,
|
||||
"minimal_roi": {
|
||||
"40": 0.0,
|
||||
"30": 0.01,
|
||||
"20": 0.02,
|
||||
"0": 0.04
|
||||
},
|
||||
"stoploss": -0.10,
|
||||
"unfilledtimeout": {
|
||||
"buy": 10,
|
||||
"sell": 30, // Trailing comma should also be accepted now
|
||||
},
|
||||
"bid_strategy": {
|
||||
"use_order_book": false,
|
||||
"ask_last_balance": 0.0,
|
||||
"order_book_top": 1,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"ask_strategy": {
|
||||
"use_order_book": false,
|
||||
"order_book_min": 1,
|
||||
"order_book_max": 9
|
||||
},
|
||||
"order_types": {
|
||||
"buy": "limit",
|
||||
"sell": "limit",
|
||||
"stoploss": "market",
|
||||
"stoploss_on_exchange": false,
|
||||
"stoploss_on_exchange_interval": 60
|
||||
},
|
||||
"order_time_in_force": {
|
||||
"buy": "gtc",
|
||||
"sell": "gtc"
|
||||
},
|
||||
"pairlist": {
|
||||
"method": "VolumePairList",
|
||||
"config": {
|
||||
"number_assets": 20,
|
||||
"sort_key": "quoteVolume",
|
||||
"precision_filter": false
|
||||
}
|
||||
},
|
||||
"exchange": {
|
||||
"name": "binance",
|
||||
"sandbox": false,
|
||||
"key": "your_exchange_key",
|
||||
"secret": "your_exchange_secret",
|
||||
"password": "",
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true
|
||||
},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": false,
|
||||
"rateLimit": 500,
|
||||
"aiohttp_trust_env": false
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"ETH/BTC",
|
||||
"LTC/BTC",
|
||||
"ETC/BTC",
|
||||
"DASH/BTC",
|
||||
"ZEC/BTC",
|
||||
"XLM/BTC",
|
||||
"NXT/BTC",
|
||||
"TRX/BTC",
|
||||
"ADA/BTC",
|
||||
"XMR/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": {
|
||||
// We can now comment out some settings
|
||||
// "enabled": true,
|
||||
"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,
|
||||
"username": "freqtrader",
|
||||
"password": "SuperSecurePassword"
|
||||
},
|
||||
"db_url": "sqlite:///tradesv3.sqlite",
|
||||
"initial_state": "running",
|
||||
"forcebuy_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5
|
||||
},
|
||||
"strategy": "DefaultStrategy",
|
||||
"strategy_path": "user_data/strategies/"
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user