进阶 · 代码逐项

持有不动 · 代码逐项

对着 BuyHold.py 从上往下走。它是尺子,不是买卖想法。

BuyHold.py 4h 不卖

1怎么走

第一天有量就上车,三扇出门的门都焊死。Freqtrade 已在场内时,入场信号不会再开第二仓,所以看起来每根 K 都在喊买,实际是一直拿着。

2逐项

每一项是文件里的原文,不是口诀。先看黑底那几行,再听人话,再答三问。

class BuyHold(IStrategy)
class BuyHold(IStrategy):

向引擎登记一份叫 BuyHold 的策略。对照选的是类名。

它是什么
策略类。引擎靠这个名字找到这份尺子。
不管它会怎样
没有这个类,回测名单里选不中这份文件。
拧大 / 拧小 / 拧反
改名以后,配置里的策略名必须一起改,否则引擎找不到。
INTERFACE_VERSION = 3
    INTERFACE_VERSION = 3

按第三版接口读:进场字段叫 enter,出场字段叫 exit。

它是什么
告诉引擎用哪一套字段名。
不管它会怎样
版本对不上,你写的 enter_long 它可能在找 buy。
拧大 / 拧小 / 拧反
拧成 2:新接口的进出场名会被旧约定忽略或报错。
timeframe = "4h"
    timeframe = "4h"

每根 K 是 4 小时。和另外五份对照同一根时钟,尺子才比得过。

它是什么
这把尺子的采样间隔。
不管它会怎样
落成默认 5 分钟,尺子和别人不在同一张表上。
拧大 / 拧小 / 拧反
拧成 1d 或 5m:窗口对不齐,数字不能并排比。
startup_candle_count = 1
    startup_candle_count = 1

几乎不用暖机。没有指标要算稳,第一根有量的 K 就能买。

它是什么
指标算稳之前要丢掉的根数。这里没有指标。
不管它会怎样
默认丢掉一截,第一天可能买不上,尺子就晚起步。
拧大 / 拧小 / 拧反
拧大:尺子晚买,不再是窗口一开始就上车。
process_only_new_candles = True
    process_only_new_candles = True

只在 K 线收盘时想一次。一根没走完的 K 里不反复改主意。

它是什么
开着只处理收盘;关着每个跳动都算。
不管它会怎样
同一根未收盘的 K 可能被写进多次信号,回测和实盘对不齐。
拧大 / 拧小 / 拧反
拧成 False:会在还没收盘的价格上提前下手。
can_short = False
    can_short = False

只许做多,不许做空。尺子是满仓多头持有。

它是什么
空仓开关。关着。
不管它会怎样
有人会以为持有也能做空对冲。这份文件不会。
拧大 / 拧小 / 拧反
拧成 True:尺子变成也能开空,就不是满仓多头了。
use_exit_signal = True
    use_exit_signal = True

引擎会去问 populate_exit_trend。这份问了,但里面一行卖都不写。

它是什么
出信号这扇门开着。
不管它会怎样
门关着,后面就算写了卖也不会被看见。这里门开着,只是屋里没人。
拧大 / 拧小 / 拧反
拧成 False:看起来也不卖,但你分不清是门关了还是真不卖。
minimal_roi = {"0": 100}
    minimal_roi = {"0": 100}

一上车就要涨 100 倍,ROI 这扇门才开。等于把门焊死。100 是 10000%。

它是什么
按持仓时间止盈的表。这里把门槛抬到几乎碰不到。
不管它会怎样
默认 ROI 会在涨一点后先平仓,尺子中途就被卖掉。
拧大 / 拧小 / 拧反
拧小到 0.1:涨 10% 就走,持有变成短线,尺子脏了。
stoploss = -0.99
    stoploss = -0.99

要跌掉 99% 才硬止损。几乎等于没有止损。

它是什么
引擎的保命地板。这里放到几乎踩不到。
不管它会怎样
默认大约一成的止损会在半路把尺子卖掉。
拧大 / 拧小 / 拧反
拧到 -0.1:尺子有了防守,就不再是「不卖」。
trailing_stop = False
    trailing_stop = False

不让利润回吐来跟踪止盈。涨了也不自动收紧。

它是什么
跟着价格上移的止损开关。关着。
不管它会怎样
开着会在回撤里提前下车,持有被剪成一段段。
拧大 / 拧小 / 拧反
拧成 True:尺子中途会被跟踪止盈卖掉。
populate_indicators 原样还表
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe

不计算任何指标。表怎么来,怎么还回去。

它是什么
指标函数。这里是空的。
不管它会怎样
往里塞均线,尺子就沾上策略味,启动根数也不再是 1。
拧大 / 拧小 / 拧反
加指标不会让它自己买卖,但对照就不干净了。
有量就写 enter_long
        dataframe.loc[dataframe["volume"] > 0, "enter_long"] = 1

凡是有成交量的 K,都写可以开多。引擎已经在场内时不会再开第二仓,所以效果是第一根有量就上车,然后一直拿着。

它是什么
入场条件。唯一的门是「这根 K 不是零量」。
不管它会怎样
没有这行,第一天买不上,尺子是空仓。
拧大 / 拧小 / 拧反
拧成很大的量门槛:第一天可能买不上。去掉量条件:正常 K 都有量,和现在几乎一样。
populate_exit_trend 空还
    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe

出场函数直接还表,一行 exit_long 都不写。信号这扇门永远不开。

它是什么
卖的信号口。这里是空的。
不管它会怎样
你若在这里写条件,持有就变成策略。
拧大 / 拧小 / 拧反
写上 exit,再配上 ROI 和止损,三扇门都会卖,尺子废了。

3假懂

人们会说:「每根有量的 K 都写 enter_long = 1,所以它在疯狂加仓。」
更短的一句:引擎在已有仓时,不会按这个信号再开一笔。它保证上车,不保证连开。不卖靠的是 ROI 100、止损 -0.99、跟踪关着、出场函数空着。这是尺子,不是交易想法。

4你来讲

对着这份文件讲。口头就行。不要编回测数字。

  1. 为什么每根有量的 K 都写 enter_long,对照里却不是几百笔,而是每个币一笔?
  2. ROI 写成 100、止损写成 -0.99,和「不卖」是什么关系?少改哪一个,尺子会先脏?
  3. populate_exit_trend 是空的,use_exit_signal 却是 True。门开着和屋里没人,差在哪?