NFI策略回测指导
Creado el: 14 de noviembre de 2024
Respondido usando O1 Preview por Chat01
Creado el: 14 de noviembre de 2024
Respondido usando O1 Preview por Chat01
您是Freqtrade加密货币交易系统专家,现在请你:
1、详细分析NostalgiaForInfinity策略的运行逻辑和功能
2、我用的是WIN10系统,已安装了Docker、VSCode,现在请你详细指导我将NostalgiaForInfinity策略能过Docder安装,通过创建VSCode的开发容器来运行回测该策略
3、请写出回测该策略的详细步骤,谢谢
概述
NostalgiaForInfinity(以下简称 NFI)是一个为 Freqtrade 量身打造的复杂且高性能的加密货币交易策略。该策略以其出色的回测和实时交易表现而闻名,广泛应用于加密货币自动化交易中。NFI 策略综合运用了多种技术指标和交易技巧,旨在在不同的市场条件下获取最佳收益。
核心组件
技术指标:NFI 策略使用了多种技术指标,包括但不限于:
信号生成:通过对这些指标的综合分析,策略生成买入和卖出信号。
风险管理:
运行逻辑
功能特点
前提条件
步骤如下:
打开 VSCode。
安装 Remote - Containers 扩展:
Ctrl+Shift+X
。Remote - Containers
,选择由 Microsoft 发布的扩展并点击安装。安装 Docker 扩展(可选,但推荐):
Docker
,安装由 Microsoft 发布的扩展。打开终端:
克隆仓库:
bashgit clone https://github.com/freqtrade/freqtrade.git
进入项目目录:
bashcd freqtrade
在 VSCode 中打开项目文件夹:
文件
> 打开文件夹
,选择刚才克隆的 freqtrade
文件夹。使用开发容器重新打开项目:
F1
调出命令面板,输入 Remote-Containers: Reopen in Container
,选择该选项。.devcontainer
配置构建并启动开发容器。下载策略文件:
nostalgiaforinfinity.py
文件。将策略文件复制到策略目录:
user_data/strategies
文件夹。nostalgiaforinfinity.py
文件复制到该文件夹中。安装策略依赖:
在 VSCode 的终端中,执行以下命令安装策略所需的 Python 包:
bashpip install -r requirements.txt
如果策略有额外的依赖(如特定的技术指标库),需要单独安装,例如:
bashpip install pandas_ta ta-lib
创建配置文件:
在终端中,运行以下命令生成默认配置文件:
bashfreqtrade new-config --config user_data/config.json
编辑配置文件:
打开 user_data/config.json
,根据需要修改配置,例如:
json{ "max_open_trades": 10, "stake_currency": "USDT", "stake_amount": "unlimited", "dry_run": true, "timeframe": "5m", "strategy": "NostalgiaForInfinity", "exchange": { "name": "binance", "key": "", "secret": "", "ccxt_config": {}, "ccxt_async_config": {}, "pair_whitelist": ["BTC/USDT", "ETH/USDT"], "pair_blacklist": ["USD/USDT"] } }
运行数据下载命令:
bashfreqtrade download-data --exchange binance --basecurrencies USDT --timeframes 5m
执行回测命令:
bashfreqtrade backtesting --config user_data/config.json --strategy NostalgiaForInfinity
查看回测结果:
backtest_results
文件夹中。步骤 1:确保环境准备就绪
user_data/strategies
目录中。步骤 2:配置策略和参数
nostalgiaforinfinity.py
,根据需要调整策略参数,如指标周期、阈值等。config.json
中的设置与策略要求一致。步骤 3:下载历史数据
根据策略的时间框架下载数据,例如:
bashfreqtrade download-data --exchange binance --basecurrencies USDT --timeframes 5m 15m 1h
步骤 4:运行回测
在终端中执行回测命令,指定时间范围:
bashfreqtrade backtesting --config user_data/config.json --strategy NostalgiaForInfinity --timerange=20210101-20211231
--timerange
参数指定回测的日期范围(格式:YYYYMMDD-YYYYMMDD)。步骤 5:分析回测结果
backtest_results
文件夹中,查看详细的回测报告和交易记录。步骤 6:生成交易图表(可选)
运行以下命令生成交易图表,便于可视化分析:
bashfreqtrade plot-dataframe --strategy NostalgiaForInfinity --timerange=20210101-20211231
user_data/plot
文件夹中。步骤 7:优化策略(可选)
使用 Hyperopt 功能优化策略参数:
bashfreqtrade hyperopt --strategy NostalgiaForInfinity --hyperopt-loss SharpeHyperOptLoss --timeframe 5m --timerange=20210101-20211231
根据优化结果,调整策略参数并重新回测。
步骤 8:重复测试
提示
希望以上指导能够帮助您成功安装和回测 NostalgiaForInfinity 策略。如有任何疑问,请随时提问。祝您交易顺利!
from logging import FATAL
from freqtrade.strategy.interface import IStrategy
from typing import Dict, List
from functools import reduce
from pandas import DataFrame
import talib.abstract as ta
import numpy as np
import freqtrade.vendor.qtpylib.indicators as qtpylib
import datetime
from technical.util import resample_to_interval, resampled_merge
from datetime import datetime, timedelta
from freqtrade.persistence import Trade
from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, CategoricalParameter
import technical.indicators as ftt
buy_params = {
"base_nb_candles_buy": 8,
"ewo_high": 2.403,
"ewo_high_2": -5.585,
"ewo_low": -14.378,
"lookback_candles": 3,
"low_offset": 0.984,
"low_offset_2": 0.942,
"profit_threshold": 1.008,
"rsi_buy": 72
}
sell_params = {
"base_nb_candles_sell": 16,
"high_offset": 1.084,
"high_offset_2": 1.401,
"pHSL": -0.15,
"pPF_1": 0.016,
"pPF_2": 0.024,
"pSL_1": 0.014,
"pSL_2": 0.022
}
def EWO(dataframe, ema_length=5, ema2_length=35):
df = dataframe.copy()
ema1 = ta.EMA(df, timeperiod=ema_length)
ema2 = ta.EMA(df, timeperiod=ema2_length)
emadif = (ema1 - ema2) / df['low'] * 100
return emadif
class NASOSv4(IStrategy):
INTERFACE_VERSION = 2
text# ROI table: minimal_roi = { # "0": 0.283, # "40": 0.086, # "99": 0.036, "0": 10 } # Stoploss: stoploss = -0.15 # SMAOffset base_nb_candles_buy = IntParameter( 2, 20, default=buy_params['base_nb_candles_buy'], space='buy', optimize=True) base_nb_candles_sell = IntParameter( 2, 25, default=sell_params['base_nb_candles_sell'], space='sell', optimize=True) low_offset = DecimalParameter( 0.9, 0.99, default=buy_params['low_offset'], space='buy', optimize=False) low_offset_2 = DecimalParameter( 0.9, 0.99, default=buy_params['low_offset_2'], space='buy', optimize=False) high_offset = DecimalParameter( 0.95, 1.1, default=sell_params['high_offset'], space='sell', optimize=True) high_offset_2 = DecimalParameter( 0.99, 1.5, default=sell_params['high_offset_2'], space='sell', optimize=True) # Protection fast_ewo = 50 slow_ewo = 200 lookback_candles = IntParameter( 1, 24, default=buy_params['lookback_candles'], space='buy', optimize=True) profit_threshold = DecimalParameter(1.0, 1.03, default=buy_params['profit_threshold'], space='buy', optimize=True) ewo_low = DecimalParameter(-20.0, -8.0, default=buy_params['ewo_low'], space='buy', optimize=False) ewo_high = DecimalParameter( 2.0, 12.0, default=buy_params['ewo_high'], space='buy', optimize=False) ewo_high_2 = DecimalParameter( -6.0, 12.0, default=buy_params['ewo_high_2'], space='buy', optimize=False) rsi_buy = IntParameter(50, 100, default=buy_params['rsi_buy'], space='buy', optimize=False) # trailing stoploss hyperopt parameters # hard stoploss profit pHSL = DecimalParameter(-0.200, -0.040, default=-0.15, decimals=3, space='sell', optimize=False, load=True) # profit threshold 1, trigger point, SL_1 is used pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', optimize=False, load=True) pSL_1 = DecimalParameter(0.008, 0.020, default=0.014, decimals=3, space='sell', optimize=False, load=True) # profit threshold 2, SL_2 is used pPF_2 = DecimalParameter(0.040, 0.100, default=0.024, decimals=3, space='sell', optimize=False, load=True) pSL_2 = DecimalParameter(0.020, 0.070, default=0.022, decimals=3, space='sell', optimize=False, load=True) # Trailing stop: trailing_stop = True trailing_stop_positive = 0.001 trailing_stop_positive_offset = 0.016 trailing_only_offset_is_reached = True # Sell signal use_sell_signal = True sell_profit_only = False sell_profit_offset = 0.01 ignore_roi_if_buy_signal = False # Optional order time in force. order_time_in_force = { 'buy': 'gtc', 'sell': 'ioc' } # Optimal timeframe for the strategy timeframe = '5m' inf_1h = '1h' process_only_new_candles = True startup_candle_count = 200 use_custom_stoploss = False plot_config = { 'main_plot': { 'ma_buy': {'color': 'orange'}, 'ma_sell': {'color': 'orange'}, }, } slippage_protection = { 'retries': 3, 'max_slippage': -0.02 } # Custom Trailing Stoploss by Perkmeister def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float: # # hard stoploss profit HSL = self.pHSL.value PF_1 = self.pPF_1.value SL_1 = self.pSL_1.value PF_2 = self.pPF_2.value SL_2 = self.pSL_2.value # For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated # between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value # rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used. if (current_profit > PF_2): sl_profit = SL_2 + (current_profit - PF_2) elif (current_profit > PF_1): sl_profit = SL_1 + ((current_profit - PF_1)*(SL_2 - SL_1)/(PF_2 - PF_1)) else: sl_profit = HSL # if current_profit < 0.001 and current_time - timedelta(minutes=600) > trade.open_date_utc: # return -0.005 return stoploss_from_open(sl_profit, current_profit) def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float, time_in_force: str, sell_reason: str, current_time: datetime, **kwargs) -> bool: dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1] if (last_candle is not None): if (sell_reason in ['sell_signal']): if (last_candle['hma_50']*1.149 > last_candle['ema_100']) and (last_candle['close'] < last_candle['ema_100']*0.951): # *1.2 return False # slippage try: state = self.slippage_protection['__pair_retries'] except KeyError: state = self.slippage_protection['__pair_retries'] = {} candle = dataframe.iloc[-1].squeeze() slippage = (rate / candle['close']) - 1 if slippage < self.slippage_protection['max_slippage']: pair_retries = state.get(pair, 0) if pair_retries < self.slippage_protection['retries']: state[pair] = pair_retries + 1 return False state[pair] = 0 return True def informative_pairs(self): pairs = self.dp.current_whitelist() informative_pairs = [(pair, '1h') for pair in pairs] return informative_pairs def informative_1h_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: assert self.dp, "DataProvider is required for multiple timeframes." # Get the informative pair informative_1h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_1h) # EMA # informative_1h['ema_50'] = ta.EMA(informative_1h, timeperiod=50) # informative_1h['ema_200'] = ta.EMA(informative_1h, timeperiod=200) # # RSI # informative_1h['rsi'] = ta.RSI(informative_1h, timeperiod=14) # bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) # informative_1h['bb_lowerband'] = bollinger['lower'] # informative_1h['bb_middleband'] = bollinger['mid'] # informative_1h['bb_upperband'] = bollinger['upper'] return informative_1h def normal_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # Calculate all ma_buy values for val in self.base_nb_candles_buy.range: dataframe[f'ma_buy_{val}'] = ta.EMA(dataframe, timeperiod=val) # Calculate all ma_sell values for val in self.base_nb_candles_sell.range: dataframe[f'ma_sell_{val}'] = ta.EMA(dataframe, timeperiod=val) dataframe['hma_50'] = qtpylib.hull_moving_average(dataframe['close'], window=50) dataframe['ema_100'] = ta.EMA(dataframe, timeperiod=100) dataframe['sma_9'] = ta.SMA(dataframe, timeperiod=9) # Elliot dataframe['EWO'] = EWO(dataframe, self.fast_ewo, self.slow_ewo) # RSI dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=4) dataframe['rsi_slow'] = ta.RSI(dataframe, timeperiod=20) return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: informative_1h = self.informative_1h_indicators(dataframe, metadata) dataframe = merge_informative_pair( dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True) # The indicators for the normal (5m) timeframe dataframe = self.normal_tf_indicators(dataframe, metadata) return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dont_buy_conditions = [] dont_buy_conditions.append( ( # don't buy if there isn't 3% profit to be made (dataframe['close_1h'].rolling(self.lookback_candles.value).max() < (dataframe['close'] * self.profit_threshold.value)) ) ) dataframe.loc[ ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['EWO'] > self.ewo_high.value) & (dataframe['rsi'] < self.rsi_buy.value) & (dataframe['volume'] > 0) & (dataframe['close'] < ( dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) ), ['buy', 'buy_tag']] = (1, 'ewo1') dataframe.loc[ ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset_2.value)) & (dataframe['EWO'] > self.ewo_high_2.value) & (dataframe['rsi'] < self.rsi_buy.value) & (dataframe['volume'] > 0) & (dataframe['close'] < (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & (dataframe['rsi'] < 25) ), ['buy', 'buy_tag']] = (1, 'ewo2') dataframe.loc[ ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['EWO'] < self.ewo_low.value) & (dataframe['volume'] > 0) & (dataframe['close'] < ( dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) ), ['buy', 'buy_tag']] = (1, 'ewolow') if dont_buy_conditions: for condition in dont_buy_conditions: dataframe.loc[condition, 'buy'] = 0 return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: conditions = [] conditions.append( ((dataframe['close'] > dataframe['sma_9']) & (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset_2.value)) & (dataframe['rsi'] > 50) & (dataframe['volume'] > 0) & (dataframe['rsi_fast'] > dataframe['rsi_slow']) ) | ( (dataframe['close'] < dataframe['hma_50']) & (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & (dataframe['volume'] > 0) & (dataframe['rsi_fast'] > dataframe['rsi_slow']) ) ) if conditions: dataframe.loc[ reduce(lambda x, y: x | y, conditions), 'sell' ]=1 return dataframe
1、请用你的专业知识用中文详细注释以上代码
2、请用你的专业知识详细分析以上代码的交易逻辑、指标生成计算方法等
3、请以你的专业知识指导我用freqtrade回测以上策略,谢谢
python# for live trailing_stop = False and use_custom_stoploss = True # for backtest trailing_stop = True and use_custom_stoploss = False # --- 不要删除这些库 --- from logging import FATAL from freqtrade.strategy.interface import IStrategy from typing import Dict, List from functools import reduce from pandas import DataFrame # ----------------------- import talib.abstract as ta import numpy as np import freqtrade.vendor.qtpylib.indicators as qtpylib import datetime from technical.util import resample_to_interval, resampled_merge from datetime import datetime, timedelta from freqtrade.persistence import Trade from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, CategoricalParameter import technical.indicators as ftt # 策略作者 # @Rallipanos # @pluxury # 买入参数(经过超参数优化) buy_params = { "base_nb_candles_buy": 8, # 买入时使用的基础K线数量 "ewo_high": 2.403, # EWO指标高值 "ewo_high_2": -5.585, # EWO指标高值(第二种情况) "ewo_low": -14.378, # EWO指标低值 "lookback_candles": 3, # 回溯的K线数量 "low_offset": 0.984, # 低价偏移量 "low_offset_2": 0.942, # 低价偏移量(第二种情况) "profit_threshold": 1.008, # 盈利阈值 "rsi_buy": 72 # RSI买入阈值 } # 卖出参数(经过超参数优化) sell_params = { "base_nb_candles_sell": 16, # 卖出时使用的基础K线数量 "high_offset": 1.084, # 高价偏移量 "high_offset_2": 1.401, # 高价偏移量(第二种情况) "pHSL": -0.15, # 硬止损值 "pPF_1": 0.016, # 盈利阈值1 "pPF_2": 0.024, # 盈利阈值2 "pSL_1": 0.014, # 止盈值1 "pSL_2": 0.022 # 止盈值2 } # 定义EWO指标函数 def EWO(dataframe, ema_length=5, ema2_length=35): df = dataframe.copy() ema1 = ta.EMA(df, timeperiod=ema_length) # 计算短期EMA ema2 = ta.EMA(df, timeperiod=ema2_length) # 计算长期EMA emadif = (ema1 - ema2) / df['low'] * 100 # 计算EWO值 return emadif # 定义策略类 class NASOSv4(IStrategy): INTERFACE_VERSION = 2 # 接口版本 # 最小回报率 minimal_roi = { "0": 10 # 设置一个高值,实际上在代码中未使用ROI } # 止损 stoploss = -0.15 # 最大止损为15% # 定义参数,供优化使用 base_nb_candles_buy = IntParameter( 2, 20, default=buy_params['base_nb_candles_buy'], space='buy', optimize=True) base_nb_candles_sell = IntParameter( 2, 25, default=sell_params['base_nb_candles_sell'], space='sell', optimize=True) low_offset = DecimalParameter( 0.9, 0.99, default=buy_params['low_offset'], space='buy', optimize=False) low_offset_2 = DecimalParameter( 0.9, 0.99, default=buy_params['low_offset_2'], space='buy', optimize=False) high_offset = DecimalParameter( 0.95, 1.1, default=sell_params['high_offset'], space='sell', optimize=True) high_offset_2 = DecimalParameter( 0.99, 1.5, default=sell_params['high_offset_2'], space='sell', optimize=True) # 保护参数 fast_ewo = 50 # 快速EWO周期 slow_ewo = 200 # 慢速EWO周期 lookback_candles = IntParameter( 1, 24, default=buy_params['lookback_candles'], space='buy', optimize=True) profit_threshold = DecimalParameter(1.0, 1.03, default=buy_params['profit_threshold'], space='buy', optimize=True) ewo_low = DecimalParameter(-20.0, -8.0, default=buy_params['ewo_low'], space='buy', optimize=False) ewo_high = DecimalParameter( 2.0, 12.0, default=buy_params['ewo_high'], space='buy', optimize=False) ewo_high_2 = DecimalParameter( -6.0, 12.0, default=buy_params['ewo_high_2'], space='buy', optimize=False) rsi_buy = IntParameter(50, 100, default=buy_params['rsi_buy'], space='buy', optimize=False) # 自定义追踪止损参数 pHSL = DecimalParameter(-0.200, -0.040, default=-0.15, decimals=3, space='sell', optimize=False, load=True) pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', optimize=False, load=True) pSL_1 = DecimalParameter(0.008, 0.020, default=0.014, decimals=3, space='sell', optimize=False, load=True) pPF_2 = DecimalParameter(0.040, 0.100, default=0.024, decimals=3, space='sell', optimize=False, load=True) pSL_2 = DecimalParameter(0.020, 0.070, default=0.022, decimals=3, space='sell', optimize=False, load=True) # 追踪止损 trailing_stop = True trailing_stop_positive = 0.001 trailing_stop_positive_offset = 0.016 trailing_only_offset_is_reached = True # 卖出信号 use_sell_signal = True sell_profit_only = False sell_profit_offset = 0.01 ignore_roi_if_buy_signal = False # 订单有效时间 order_time_in_force = { 'buy': 'gtc', # Good till cancelled 'sell': 'ioc' # Immediate or cancel } # 策略的时间框架 timeframe = '5m' # 5分钟K线 inf_1h = '1h' # 1小时K线(用于获取信息) process_only_new_candles = True # 仅处理新蜡烛 startup_candle_count = 200 # 启动时需要的最小蜡烛数 use_custom_stoploss = False # 不使用自定义止损(用于回测) # 绘图配置 plot_config = { 'main_plot': { 'ma_buy': {'color': 'orange'}, 'ma_sell': {'color': 'orange'}, }, } # 滑点保护配置 slippage_protection = { 'retries': 3, # 重试次数 'max_slippage': -0.02 # 最大允许滑点 } # 自定义止损函数(由Perkmeister提供) def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float: # 获取止损参数 HSL = self.pHSL.value # 硬止损 PF_1 = self.pPF_1.value # 盈利阈值1 SL_1 = self.pSL_1.value # 止盈值1 PF_2 = self.pPF_2.value # 盈利阈值2 SL_2 = self.pSL_2.value # 止盈值2 # 根据当前利润计算动态止损 if (current_profit > PF_2): sl_profit = SL_2 + (current_profit - PF_2) elif (current_profit > PF_1): sl_profit = SL_1 + ((current_profit - PF_1)*(SL_2 - SL_1)/(PF_2 - PF_1)) else: sl_profit = HSL # 使用硬止损 # 返回从开仓价计算的止损价格 return stoploss_from_open(sl_profit, current_profit) # 确认交易退出 def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float, time_in_force: str, sell_reason: str, current_time: datetime, **kwargs) -> bool: # 获取当前数据 dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1] if (last_candle is not None): if (sell_reason in ['sell_signal']): # 如果满足特定条件,不卖出 if (last_candle['hma_50']*1.149 > last_candle['ema_100']) and (last_candle['close'] < last_candle['ema_100']*0.951): return False # 滑点保护逻辑 try: state = self.slippage_protection['__pair_retries'] except KeyError: state = self.slippage_protection['__pair_retries'] = {} candle = dataframe.iloc[-1].squeeze() slippage = (rate / candle['close']) - 1 if slippage < self.slippage_protection['max_slippage']: pair_retries = state.get(pair, 0) if pair_retries < self.slippage_protection['retries']: state[pair] = pair_retries + 1 return False # 不退出交易 state[pair] = 0 # 重置重试计数 return True # 允许退出交易 # 定义需要的附加数据对(信息性数据) def informative_pairs(self): pairs = self.dp.current_whitelist() informative_pairs = [(pair, '1h') for pair in pairs] # 1小时数据 return informative_pairs # 计算1小时时间框架的指标 def informative_1h_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: assert self.dp, "需要DataProvider来获取多时间框架数据。" informative_1h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_1h) return informative_1h # 计算正常时间框架的指标 def normal_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # 计算所有买入移动平均线 for val in self.base_nb_candles_buy.range: dataframe[f'ma_buy_{val}'] = ta.EMA(dataframe, timeperiod=val) # 计算所有卖出移动平均线 for val in self.base_nb_candles_sell.range: dataframe[f'ma_sell_{val}'] = ta.EMA(dataframe, timeperiod=val) dataframe['hma_50'] = qtpylib.hull_moving_average(dataframe['close'], window=50) dataframe['ema_100'] = ta.EMA(dataframe, timeperiod=100) dataframe['sma_9'] = ta.SMA(dataframe, timeperiod=9) # 计算EWO指标 dataframe['EWO'] = EWO(dataframe, self.fast_ewo, self.slow_ewo) # 计算RSI指标 dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=4) dataframe['rsi_slow'] = ta.RSI(dataframe, timeperiod=20) return dataframe # 填充指标数据 def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # 获取并合并1小时的指标数据 informative_1h = self.informative_1h_indicators(dataframe, metadata) dataframe = merge_informative_pair( dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True) # 计算正常时间框架的指标 dataframe = self.normal_tf_indicators(dataframe, metadata) return dataframe # 定义买入逻辑 def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dont_buy_conditions = [] # 不买入条件:如果在回溯的K线中,1小时的最高价低于当前价的盈利阈值 dont_buy_conditions.append( ( (dataframe['close_1h'].rolling(self.lookback_candles.value).max() < (dataframe['close'] * self.profit_threshold.value)) ) ) # 买入条件1 dataframe.loc[ ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['EWO'] > self.ewo_high.value) & (dataframe['rsi'] < self.rsi_buy.value) & (dataframe['volume'] > 0) & (dataframe['close'] < ( dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) ), ['buy', 'buy_tag']] = (1, 'ewo1') # 买入条件2 dataframe.loc[ ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset_2.value)) & (dataframe['EWO'] > self.ewo_high_2.value) & (dataframe['rsi'] < self.rsi_buy.value) & (dataframe['volume'] > 0) & (dataframe['close'] < (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & (dataframe['rsi'] < 25) ), ['buy', 'buy_tag']] = (1, 'ewo2') # 买入条件3 dataframe.loc[ ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['EWO'] < self.ewo_low.value) & (dataframe['volume'] > 0) & (dataframe['close'] < ( dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) ), ['buy', 'buy_tag']] = (1, 'ewolow') # 应用不买入条件 if dont_buy_conditions: for condition in dont_buy_conditions: dataframe.loc[condition, 'buy'] = 0 # 设置买入信号为0 return dataframe # 定义卖出逻辑 def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: conditions = [] # 卖出条件 conditions.append( ( (dataframe['close'] > dataframe['sma_9']) & (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset_2.value)) & (dataframe['rsi'] > 50) & (dataframe['volume'] > 0) & (dataframe['rsi_fast'] > dataframe['rsi_slow']) ) | ( (dataframe['close'] < dataframe['hma_50']) & (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & (dataframe['volume'] > 0) & (dataframe['rsi_fast'] > dataframe['rsi_slow']) ) ) # 应用卖出条件 if conditions: dataframe.loc[ reduce(lambda x, y: x | y, conditions), 'sell' ] = 1 return dataframe
总体概述
该策略名为 NASOSv4,基于 Freqtrade 的策略框架开发,使用了多种技术指标,如移动平均线、EWO指标、RSI等,旨在捕捉市场的短期波动,进行高频交易。策略主要在5分钟K线上运行,同时参考了1小时K线的数据。
指标计算方法
Elliott Wave Oscillator (EWO)
移动平均线
Hull Moving Average (HMA)
相对强弱指数 (RSI)
交易逻辑
买入逻辑
策略定义了三种主要的买入条件,均涉及到以下指标和条件:
具体的买入条件如下:
条件1(标签:ewo1)
条件2(标签:ewo2)
条件3(标签:ewolow)
此外,还有一个 不买入条件:
lookback_candles
个1小时K线中,最高价低于当前价乘以 profit_threshold
,则不买入。这是为了确保有足够的利润空间。卖出逻辑
策略定义了两种主要的卖出条件,涉及以下指标和条件:
具体的卖出条件如下:
条件1
条件2
止损和保护
其它功能
IntParameter
和 DecimalParameter
定义了多个可优化的参数,方便进行策略优化。confirm_trade_exit
函数,根据特定条件决定是否真正卖出。步骤1:准备环境
确保您已经按照之前的步骤,使用 Docker 和 VSCode 设置好了 Freqtrade 的开发环境,并将策略文件放置在 user_data/strategies
目录下。
步骤2:安装策略依赖
该策略可能需要额外的 Python 库,例如 TA-Lib。请在容器内安装:
bashpip install ta-lib pip install pandas_ta
步骤3:更新配置文件
编辑 user_data/config.json
,确保以下参数正确设置:
json{ "max_open_trades": 10, "stake_currency": "USDT", "stake_amount": "unlimited", "dry_run": true, "timeframe": "5m", "strategy": "NASOSv4", "exchange": { "name": "binance", "key": "", "secret": "", "ccxt_config": {}, "ccxt_async_config": {}, "pair_whitelist": ["BTC/USDT", "ETH/USDT", ...], "pair_blacklist": ["USD/USDT"] } }
'5m'
,与策略一致。'NASOSv4'
。["BTC/USDT", "ETH/USDT"]
。步骤4:下载历史数据
由于策略使用了多时间框架,需要下载 5 分钟和 1 小时的历史数据。
bashfreqtrade download-data --exchange binance --basecurrencies USDT --timeframes 5m 1h
步骤5:检查策略代码
确保策略代码中的 use_custom_stoploss
和 trailing_stop
设置正确:
回测时:
pythonuse_custom_stoploss = False trailing_stop = True
运行实时交易时:
pythonuse_custom_stoploss = True trailing_stop = False
步骤6:运行回测
在终端中运行以下命令,开始回测:
bashfreqtrade backtesting --config user_data/config.json --strategy NASOSv4 --timerange=20210101-20211231
步骤7:查看回测结果
回测完成后,终端会显示回测的摘要,包括:
详细的回测报告保存在 backtest_results
目录下,包括交易日志和图表。
步骤8:分析结果
步骤9:参数优化(可选)
如果希望进一步优化策略,可以使用 Hyperopt 进行参数优化。
bashfreqtrade hyperopt --config user_data/config.json --strategy NASOSv4 --hyperopt-loss SharpeHyperOptLoss --timeframe 5m --timerange=20210101-20211231
注意事项
希望以上指导能够帮助您顺利回测该策略。如有任何疑问,请随时提问!
1、请问以上策略可不可以用于合约交易?如果可以请运用你的freqtrade专业知识,生成一份用于合约可进行多空交易的策略,用中文详细注释,并详细讲解交易逻辑
2、请用你的freqtrade知识,根据策略生成一份完整的配置文件
以下是基于您的 NASOSv4
策略扩展,用于合约交易(允许做多和做空)。我们对策略进行了修改,以支持多空交易,并添加了相应的中国注释和详细解释。
python# --- 扩展用于合约交易的NASOSv4策略 --- from logging import FATAL from freqtrade.strategy.interface import IStrategy from typing import Dict, List from functools import reduce from pandas import DataFrame import talib.abstract as ta import numpy as np import freqtrade.vendor.qtpylib.indicators as qtpylib import datetime from technical.util import resample_to_interval, resampled_merge from datetime import datetime, timedelta from freqtrade.persistence import Trade from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, CategoricalParameter import technical.indicators as ftt # 策略作者 # @Rallipanos # @pluxury # 买入参数(经过超参数优化) buy_params = { "base_nb_candles_buy": 8, # 买入时使用的基础K线数量 "ewo_high": 2.403, # EWO指标高值 "ewo_high_2": -5.585, # EWO指标高值(第二种情况) "ewo_low": -14.378, # EWO指标低值 "lookback_candles": 3, # 回溯的K线数量 "low_offset": 0.984, # 低价偏移量 "low_offset_2": 0.942, # 低价偏移量(第二种情况) "profit_threshold": 1.008, # 盈利阈值 "rsi_buy": 72 # RSI买入阈值 } # 卖出参数(经过超参数优化) sell_params = { "base_nb_candles_sell": 16, # 卖出时使用的基础K线数量 "high_offset": 1.084, # 高价偏移量 "high_offset_2": 1.401, # 高价偏移量(第二种情况) "pHSL": -0.15, # 硬止损值 "pPF_1": 0.016, # 盈利阈值1 "pPF_2": 0.024, # 盈利阈值2 "pSL_1": 0.014, # 止盈值1 "pSL_2": 0.022 # 止盈值2 } # 定义EWO指标函数 def EWO(dataframe, ema_length=5, ema2_length=35): df = dataframe.copy() ema1 = ta.EMA(df, timeperiod=ema_length) # 计算短期EMA ema2 = ta.EMA(df, timeperiod=ema2_length) # 计算长期EMA emadif = (ema1 - ema2) / df['low'] * 100 # 计算EWO值 return emadif # 定义策略类 class NASOSv4_Futures(IStrategy): INTERFACE_VERSION = 2 # 接口版本 # 多空策略 can_short: bool = True # 允许做空 # 最小回报率(ROI) # 对于合约交易,最小回报率设得很高,仅用于占位 minimal_roi = { "0": 10 } # 止损 stoploss = -0.15 # 最大止损为15% # 定义参数,供优化使用 base_nb_candles_buy = IntParameter( 2, 20, default=buy_params['base_nb_candles_buy'], space='buy', optimize=True) base_nb_candles_sell = IntParameter( 2, 25, default=sell_params['base_nb_candles_sell'], space='sell', optimize=True) low_offset = DecimalParameter( 0.9, 0.99, default=buy_params['low_offset'], space='buy', optimize=False) low_offset_2 = DecimalParameter( 0.9, 0.99, default=buy_params['low_offset_2'], space='buy', optimize=False) high_offset = DecimalParameter( 0.95, 1.1, default=sell_params['high_offset'], space='sell', optimize=True) high_offset_2 = DecimalParameter( 0.99, 1.5, default=sell_params['high_offset_2'], space='sell', optimize=True) # 保护参数(EWO) fast_ewo = 50 # 快速EWO周期 slow_ewo = 200 # 慢速EWO周期 # 回溯K线数量 lookback_candles = IntParameter( 1, 24, default=buy_params['lookback_candles'], space='buy', optimize=True) # 利润阈值 profit_threshold = DecimalParameter(1.0, 1.03, default=buy_params['profit_threshold'], space='buy', optimize=True) # EWO指标阈值 ewo_low = DecimalParameter(-20.0, -8.0, default=buy_params['ewo_low'], space='buy', optimize=False) ewo_high = DecimalParameter( 2.0, 12.0, default=buy_params['ewo_high'], space='buy', optimize=False) ewo_high_2 = DecimalParameter( -6.0, 12.0, default=buy_params['ewo_high_2'], space='buy', optimize=False) # RSI买入阈值 rsi_buy = IntParameter(50, 100, default=buy_params['rsi_buy'], space='buy', optimize=False) # 自定义追踪止损参数 pHSL = DecimalParameter(-0.200, -0.040, default=-0.15, decimals=3, space='sell', optimize=False, load=True) pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', optimize=False, load=True) pSL_1 = DecimalParameter(0.008, 0.020, default=0.014, decimals=3, space='sell', optimize=False, load=True) pPF_2 = DecimalParameter(0.040, 0.100, default=0.024, decimals=3, space='sell', optimize=False, load=True) pSL_2 = DecimalParameter(0.020, 0.070, default=0.022, decimals=3, space='sell', optimize=False, load=True) # 追踪止损配置 trailing_stop = True trailing_stop_positive = 0.001 trailing_stop_positive_offset = 0.016 trailing_only_offset_is_reached = True # 卖出信号 use_sell_signal = True sell_profit_only = False sell_profit_offset = 0.01 ignore_roi_if_buy_signal = False # 订单有效时间 order_time_in_force = { 'buy': 'gtc', # Good till cancelled 'sell': 'ioc' # Immediate or cancel } # 策略的时间框架 timeframe = '5m' # 5分钟K线 inf_1h = '1h' # 1小时K线(用于获取信息) process_only_new_candles = True # 仅处理新蜡烛 startup_candle_count = 200 # 启动时需要的最小蜡烛数 use_custom_stoploss = False # 不使用自定义止损(用于回测) # 绘图配置 plot_config = { 'main_plot': { 'ma_buy': {'color': 'orange'}, 'ma_sell': {'color': 'orange'}, }, } # 滑点保护配置 slippage_protection = { 'retries': 3, # 重试次数 'max_slippage': -0.02 # 最大允许滑点 } # 自定义止损函数(由Perkmeister提供) def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float: # 获取止损参数 HSL = self.pHSL.value # 硬止损 PF_1 = self.pPF_1.value # 盈利阈值1 SL_1 = self.pSL_1.value # 止盈值1 PF_2 = self.pPF_2.value # 盈利阈值2 SL_2 = self.pSL_2.value # 止盈值2 # 根据当前利润计算动态止损 if (current_profit > PF_2): sl_profit = SL_2 + (current_profit - PF_2) elif (current_profit > PF_1): sl_profit = SL_1 + ((current_profit - PF_1)*(SL_2 - SL_1)/(PF_2 - PF_1)) else: sl_profit = HSL # 使用硬止损 # 返回从开仓价计算的止损价格 return stoploss_from_open(sl_profit, current_profit) # 确认交易退出 def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float, time_in_force: str, sell_reason: str, current_time: datetime, **kwargs) -> bool: # 获取当前数据 dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1] if (last_candle is not None): if (sell_reason in ['sell_signal']): # 如果满足特定条件,不卖出 if (last_candle['hma_50']*1.149 > last_candle['ema_100']) and (last_candle['close'] < last_candle['ema_100']*0.951): return False # 滑点保护逻辑 try: state = self.slippage_protection['__pair_retries'] except KeyError: state = self.slippage_protection['__pair_retries'] = {} candle = dataframe.iloc[-1].squeeze() slippage = (rate / candle['close']) - 1 if slippage < self.slippage_protection['max_slippage']: pair_retries = state.get(pair, 0) if pair_retries < self.slippage_protection['retries']: state[pair] = pair_retries + 1 return False # 不退出交易 state[pair] = 0 # 重置重试计数 return True # 允许退出交易 # 定义需要的附加数据对(信息性数据) def informative_pairs(self): pairs = self.dp.current_whitelist() informative_pairs = [(pair, '1h') for pair in pairs] # 1小时数据 return informative_pairs # 计算1小时时间框架的指标 def informative_1h_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: assert self.dp, "需要DataProvider来获取多时间框架数据。" informative_1h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_1h) return informative_1h # 计算正常时间框架的指标 def normal_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # 计算所有买入移动平均线 for val in self.base_nb_candles_buy.range: dataframe[f'ma_buy_{val}'] = ta.EMA(dataframe, timeperiod=val) # 计算所有卖出移动平均线 for val in self.base_nb_candles_sell.range: dataframe[f'ma_sell_{val}'] = ta.EMA(dataframe, timeperiod=val) # 其他指标 dataframe['hma_50'] = qtpylib.hull_moving_average(dataframe['close'], window=50) dataframe['ema_100'] = ta.EMA(dataframe, timeperiod=100) dataframe['sma_9'] = ta.SMA(dataframe, timeperiod=9) # 计算EWO指标 dataframe['EWO'] = EWO(dataframe, self.fast_ewo, self.slow_ewo) # 计算RSI指标 dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=4) dataframe['rsi_slow'] = ta.RSI(dataframe, timeperiod=20) return dataframe # 填充指标数据 def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # 获取并合并1小时的指标数据 informative_1h = self.informative_1h_indicators(dataframe, metadata) dataframe = merge_informative_pair( dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True) # 计算正常时间框架的指标 dataframe = self.normal_tf_indicators(dataframe, metadata) return dataframe # 定义开仓(买入/做空)逻辑 def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # 初始化 dataframe.loc[:, 'enter_long'] = 0 dataframe.loc[:, 'enter_short'] = 0 # 不做多的条件:如果在回溯的K线中,1小时的最高价低于当前价的盈利阈值 dont_long_conditions = ( (dataframe['close_1h'].rolling(self.lookback_candles.value).max() < (dataframe['close'] * self.profit_threshold.value)) ) # 买入(做多)条件1 long_condition_1 = ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['EWO'] > self.ewo_high.value) & (dataframe['rsi'] < self.rsi_buy.value) & (dataframe['volume'] > 0) & (dataframe['close'] < ( dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & ~dont_long_conditions ) # 买入(做多)条件2 long_condition_2 = ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset_2.value)) & (dataframe['EWO'] > self.ewo_high_2.value) & (dataframe['rsi'] < self.rsi_buy.value) & (dataframe['volume'] > 0) & (dataframe['close'] < (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & (dataframe['rsi'] < 25) & ~dont_long_conditions ) # 买入(做多)条件3 long_condition_3 = ( (dataframe['rsi_fast'] < 35) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['EWO'] < self.ewo_low.value) & (dataframe['volume'] > 0) & (dataframe['close'] < ( dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & ~dont_long_conditions ) # 做空条件:当价格接近高位时 short_condition = ( (dataframe['rsi_fast'] > 70) & (dataframe['close'] > dataframe['hma_50']) & (dataframe['EWO'] < 0) & (dataframe['volume'] > 0) & (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) ) # 为做多信号赋值 dataframe.loc[long_condition_1, 'enter_long'] = 1 dataframe.loc[long_condition_2, 'enter_long'] = 1 dataframe.loc[long_condition_3, 'enter_long'] = 1 # 为做空信号赋值 dataframe.loc[short_condition, 'enter_short'] = 1 return dataframe # 定义平仓(卖出/做多平仓)逻辑 def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # 初始化 dataframe.loc[:, 'exit_long'] = 0 dataframe.loc[:, 'exit_short'] = 0 # 做多仓位平仓条件 long_exit_condition = ( ((dataframe['close'] > dataframe['sma_9']) & (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset_2.value)) & (dataframe['rsi'] > 50) & (dataframe['volume'] > 0) & (dataframe['rsi_fast'] > dataframe['rsi_slow'])) | ((dataframe['close'] < dataframe['hma_50']) & (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & (dataframe['volume'] > 0) & (dataframe['rsi_fast'] > dataframe['rsi_slow'])) ) # 做空仓位平仓条件 short_exit_condition = ( ((dataframe['close'] < dataframe['sma_9']) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset_2.value)) & (dataframe['rsi'] < 50) & (dataframe['volume'] > 0) & (dataframe['rsi_fast'] < dataframe['rsi_slow'])) | ((dataframe['close'] > dataframe['hma_50']) & (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & (dataframe['volume'] > 0) & (dataframe['rsi_fast'] < dataframe['rsi_slow'])) ) # 为平多信号赋值 dataframe.loc[long_exit_condition, 'exit_long'] = 1 # 为平空信号赋值 dataframe.loc[short_exit_condition, 'exit_short'] = 1 return dataframe
总体概述:
该策略 NASOSv4_Futures
基于原始的 NASOSv4
策略扩展,使其支持合约交易中的多空策略。在此策略中,我们使用5分钟K线作为主要时间框架,并参考1小时K线作为附加信息。策略会自动根据市场情况决定何时做多或做空,并通过止损和追踪止损机制来管理风险。
1. 新增做空逻辑:
can_short = True
,允许策略打开空头头寸。populate_entry_trend
函数中添加了 enter_short
信号,定义了满足特定条件时做空的逻辑。2. 指标计算:
策略使用了多个技术指标来进行市场分析:
3. 买入(做多)逻辑:
策略在以下情况下做多(enter_long
):
rsi_fast < 35
和 EWO > ewo_high
表明市场可能处于超卖状态,等待反弹。rsi < 25
) 且 EWO > ewo_high_2
,市场处于极端超卖状态。EWO < ewo_low
表明市场动量可能正在转向。同时,还应用了其他条件以确保买入时价格处于相对于移动平均线的低位,并且在过去的数根1小时K线中有足够的利润空间。
4. 卖出(做多平仓)逻辑:
策略在以下情况下平多(exit_long
):
SMA9
)且相对于移动平均线过高(ma_sell
),同时 RSI > 50
表明价格可能进入高位区域,动量增强。HMA50
以下,但仍高于卖出移动平均线的高偏移,同时 RSI_fast > RSI_slow
表明市场可能处于高位但开始回落。5. 做空逻辑:
我们为策略添加了做空逻辑。当市场显示反向迹象时,策略将做空(enter_short
):
rsi_fast > 70
和 EWO < 0
,表明市场可能处于超买状态,价格有可能下跌。HMA50
上方,并高于 ma_sell
移动平均线的高偏移,这些条件表明价格可能过高,将要回落。6. 做空平仓逻辑:
策略在以下情况下平空(exit_short
):
SMA9
)以下,并相对于移动平均线过低(ma_buy
),同时 RSI < 50
表明价格可能触底反弹。HMA50
以上,但仍低于买入移动平均线的低偏移,同时 RSI_fast < RSI_slow
表明市场有可能从低位反弹。7. 止损和追踪止损:
策略使用 stoploss
和 custom_stoploss
来管理风险:
stoploss
设置为 -0.15,即如果亏损达到15%,将止损。custom_stoploss
根据当前利润动态调整止损位置,保护已获得的利润。8. 滑点保护:
confirm_trade_exit
函数包含滑点保护逻辑。如果卖出出现滑点超过设定阈值,策略将尝试重新卖出,最多重试3次。
9. 多时间框架:
策略使用1小时K线的最高价信息来确定是否有足够的利润空间进行交易,并使用 merge_informative_pair
将1小时数据合并到5分钟数据中。
总结:
NASOSv4_Futures
策略通过多项技术指标和多时间框架分析市场情况,根据市场状况灵活地决定做多或做空位置。通过止损、追踪止损和滑点保护等机制,该策略旨在最大化利润并最小化风险。
以下是一个适用于合约交易(Futures)的 config.json
示例文件。该文件配置了交易所和策略等相关设置。
json{ "max_open_trades": 10, "stake_currency": "USDT", "stake_amount": "unlimited", "dry_run": true, "margin_mode": "isolated", "margin_leverage": 10, "timeframe": "5m", "strategy": "NASOSv4_Futures", "exit_profit_only": false, "trailing_stop": true, "trailing_stop_positive": 0.001, "trailing_stop_positive_offset": 0.016, "trailing_only_offset_is_reached": true, "ignore_roi_if_buy_signal": false, "exchange": { "name": "binance_futures", "key": "YOUR_BINANCE_API_KEY", "secret": "YOUR_BINANCE_API_SECRET", "password": "", "uid": "", "ccxt_config": { "enableRateLimit": true }, "ccxt_async_config": {}, "pair_whitelist": [ "BTC/USDT", "ETH/USDT", "BNB/USDT" ], "pair_blacklist": [ "USD/USDT" ] }, "pairlists": [ { "method": "StaticPairList", "pairs": [ "BTC/USDT", "ETH/USDT", "BNB/USDT" ] } ], "telegram": { "enabled": false, "token": "", "chat_id": "" }, "bot_name": "freqtrade-futures", "initial_safety_order_trigger": -0.05, "max_safety_orders": 0, "max_so_vol_scale": 1, "max_so_price_scale": 1, "unfilledtimeout": { "buy": 15, "sell": 15, "unit": "minutes" }, "bid_strategy": { "price_side": "bid", "ask_last_balance": 0.0, "use_order_book": false, "order_book_top": 1 }, "ask_strategy": { "price_side": "ask", "use_order_book": false, "order_book_top": 1 }, "api_server": { "enabled": false, "listen_ip_address": "127.0.0.1", "listen_port": 8080, "verbosity": "error", "whitelist": [], "jwt_secret_key": "random_key_here", "CORS_origins": [], "username": "freqtrade", "password": "freqtrade" }, "bot_credentials": { "username": "freqtrade", "password": "freqtrade" }, "log_level": "info", "experimental": { "roi_enhancement": false } }
USDT
。unlimited
,即根据可用余额进行交易。true
表示模拟交易模式,不会进行真实交易。isolated
孤立模式。NASOSv4_Futures
策略。binance_futures
。
binance_futures
。BTC/USDT
、ETH/USDT
和 BNB/USDT
。freqtrade-futures
。log_level
设置为 info
,表示输出信息级别的日志。key
和 secret
,以便连接到Binance Futures进行合约交易。dry_run
为 true
,进行模拟交易。当您准备好进行真实交易时,可以将其设置为 false
。BTC/USDT
、ETH/USDT
和 BNB/USDT
。在本解答中,我们详细介绍了如何将 NASOSv4
策略扩展为可用于合约交易的多空策略,包括在代码中添加详细的中文注释和对交易逻辑的深入讲解。此外,我们还根据策略生成了一份完整的配置文件,以帮助您在Binance Futures上进行多空合约交易。
请根据您具体的交易所API密钥、风险偏好和交易对进行适当调整后再使用该策略。合约交易具有高风险,请谨慎操作。