进阶 · 代码逐项

Supertrend · 代码逐项

对着 Supertrend4h.py 从上往下走。三条 4h 加日线都向上买,主线翻空卖。

Supertrend4h.py 4h + 1d 10/2 · 14/3 · 21/4 日线 10/3

1怎么走

4h 上算快、中、慢三条 Supertrend,再把日线那条并进来。买要四条都 up。卖只看中线 st_mid 是否 down,不等三条凑齐。

2逐项

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

class Supertrend4h(IStrategy)
class Supertrend4h(IStrategy):

向引擎登记这份 4 小时 Supertrend。对照选的是类名。

它是什么
策略类。
不管它会怎样
没有这个类,回测选不中。
拧大 / 拧小 / 拧反
改名以后配置里的策略名要对上。
INTERFACE_VERSION = 3
    INTERFACE_VERSION = 3

按第三版接口读 enter / exit,后面 informative 合并也走这套。

它是什么
接口版本号。
不管它会怎样
版本对不上,进出场字段对不齐。
拧大 / 拧小 / 拧反
拧成 2:新字段名会被旧约定忽略。
timeframe = "4h"
    timeframe = "4h"

主图是 4 小时。三条快中慢都画在这张图上。

它是什么
主周期。
不管它会怎样
落成 1h:参数还是按 4h 调的,线会乱翻。
拧大 / 拧小 / 拧反
拧成 1d:和 informative 撞车,日线滤网没意义。
informative_timeframe = "1d"
    informative_timeframe = "1d"

再要一根日线。大天气不对,4h 再整齐也不出门。

它是什么
辅周期。后面合并时列名会带上 _1d。
不管它会怎样
不管它,informative_pairs 和 merge 没有目标周期。
拧大 / 拧小 / 拧反
拧成 1h:滤网几乎和主图一样快,大周期一票否决没了。拧成 1w:更懒,更少买。
startup_candle_count = 80
    startup_candle_count = 80

先丢掉大约 80 根 4h。慢线 21、日线还要并进来,前面一段方向是空的。

它是什么
暖机根数。
不管它会怎样
太短:st_slow 或日线还没成形,== "up" 比的是空字符串。
拧大 / 拧小 / 拧反
拧到 10:慢线和日线都半残。拧到 2000:白白丢掉很长一段。
process_only_new_candles = True
    process_only_new_candles = True

只在 4h 收盘时看四条线翻没翻。Supertrend 穿越本就跟收盘走。

它是什么
只处理收盘。
不管它会怎样
未收盘就判翻向,一条线会在一根 K 里来回跳。
拧大 / 拧小 / 拧反
拧成 False:盘中刺穿轨道就会提前买卖。
can_short = False
    can_short = False

只做多。主线翻空是平多,不是开空。

它是什么
空仓开关。关着。
不管它会怎样
有人看见 down 就想开空。这份没有 enter_short。
拧大 / 拧小 / 拧反
拧成 True:还要自己写空头条件。
use_exit_signal = True
    use_exit_signal = True

st_mid == down 那行 exit_long,引擎会听。

它是什么
出信号门开着。
不管它会怎样
门关着,主线翻空也不卖,只剩 -12% 地板。
拧大 / 拧小 / 拧反
拧成 False:趋势翻了还拿着。
exit_profit_only = False
    exit_profit_only = False

亏着也能按主线翻空卖。假趋势可以认赔。

它是什么
出信号是否只许盈利时触发。这里不限制。
不管它会怎样
拧成 True:主线已空、浮亏还在扛,回撤更深。
拧大 / 拧小 / 拧反
拧反 True:和「主路牌翻停就回家」相反。
ignore_roi_if_entry_signal = False
    ignore_roi_if_entry_signal = False

入场信号不压 ROI。这版 ROI 几乎焊死,这行很少派上用场。

它是什么
入场信号是否压住 ROI。这里不压。
不管它会怎样
ROI 是 10 倍,本来就碰不到。
拧大 / 拧小 / 拧反
拧成 True:只在 ROI 真开门时才有差别。这版几乎没差别。
minimal_roi = {"0": 10}
    minimal_roi = {"0": 10}

一上车要涨 10 倍才用 ROI。注释写了:几乎关掉 ROI,让 Supertrend 翻向来平仓。

它是什么
ROI 表。门槛抬到几乎碰不到。
不管它会怎样
默认小 ROI 会先于主线翻空把仓平了。
拧大 / 拧小 / 拧反
拧小:闹钟先响,趋势还没翻你就走。
stoploss = -0.12
    stoploss = -0.12

硬止损 12%。注释写了:只防暴跌,不替代指标出场。

它是什么
暴跌地板,不是主卖点。
不管它会怎样
没有地板,四条线还没翻,暴跌会把回撤拉穿。
拧大 / 拧小 / 拧反
拧到 -0.03:地板比主线更敏。拧到 -0.99:暴跌几乎不防。
trailing_stop = False
    trailing_stop = False

不用跟踪止盈。出场交给主线和地板。

它是什么
跟踪止损开关。关着。
不管它会怎样
开着会和主线抢出场,持仓更碎。
拧大 / 拧小 / 拧反
拧成 True:出场更碎,和主线抢着剪仓。
三条 4h 线
    st_fast_period = 10
    st_fast_mult = 2
    st_mid_period = 14
    st_mid_mult = 3
    st_slow_period = 21
    st_slow_mult = 4

快 10/2,中 14/3,慢 21/4。注释写了:倍数越大,线离价格越远,越不容易翻。三条都要算,买的时候三条都要 up。

它是什么
同一张 4h 图上三条不同钝度的 Supertrend。
不管它会怎样
只留一条:翻得太勤。三条是为了少被单线晃出去。
拧大 / 拧小 / 拧反
倍数一起拧大:几乎不翻,像持有。一起拧小:一根 K 翻一次,像噪音。再加第四条:更难等齐。
日线 10 / 3
    st_1d_period = 10
    st_1d_mult = 3

日线用经典 10、3,确认大方向。买的时候它也要 up。

它是什么
大周期那一票。
不管它会怎样
不管它:4h 自己玩,逆着日线追,假趋势会更多。
拧大 / 拧小 / 拧反
拧成更慢:更少买。拧成和快线一样敏:日线滤网没了。
informative_pairs 白名单 × 1d
    def informative_pairs(self):
        pairs = self.dp.current_whitelist()
        return [(pair, self.informative_timeframe) for pair in pairs]

白名单里每个币,再要一份日线数据。引擎按这个列表去拉 1d。

它是什么
告诉引擎:除了 4h,还要下载这些辅周期。
不管它会怎样
不写:后面 get_pair_dataframe(1d) 可能没有日线,日线列是空的。
拧大 / 拧小 / 拧反
写成别的周期:和 informative_timeframe 对不上,合并会乱。
_st_dir:只要方向
    def _st_dir(self, dataframe: DataFrame, period: int, multiplier: float, name: str) -> pd.Series:
        _value, stx = ftt.supertrend(dataframe, period=period, multiplier=multiplier)
        return pd.Series(stx, index=dataframe.index, name=name).fillna("")

调用 technical 的 supertrend,丢掉轨道数值,只留下 STX 方向。空值填成空字符串,后面和 "up" / "down" 比才不会是空。

它是什么
方向提取器。up 是多,down 是空。
不管它会怎样
用 _value 当条件:你在比轨道价格,不是比立场。不 fillna:空值和 "up" 比永远假。
拧大 / 拧小 / 拧反
period / multiplier 跟上面三条和日线走。函数本身不决定买卖,只生产列。
4h 三条拼进主表
        cols = [
            self._st_dir(dataframe, self.st_fast_period, self.st_fast_mult, "st_fast"),
            self._st_dir(dataframe, self.st_mid_period, self.st_mid_mult, "st_mid"),
            self._st_dir(dataframe, self.st_slow_period, self.st_slow_mult, "st_slow"),
        ]
        dataframe = pd.concat([dataframe] + cols, axis=1)

算出 st_fast / st_mid / st_slow 三列,横着拼回主表。列名就是后面 == "up" 要比的名字。

它是什么
三条 4h 方向列。
不管它会怎样
少拼一列:入场那条 == "up" 会 KeyError,或者你删掉对应条件。
拧大 / 拧小 / 拧反
只算 fast:中线和慢线没有,四人同意少了两人。
日线表上算 st_1d
        informative = self.dp.get_pair_dataframe(
            pair=metadata["pair"], timeframe=self.informative_timeframe
        )
        informative["st_1d"] = self._st_dir(
            informative, self.st_1d_period, self.st_1d_mult, "st_1d"
        )

另取这份币的日线表,在日线上算一条 Supertrend,列名先叫 st_1d。

它是什么
辅表上的大方向。注意:这里还没合并,列名还没有第二个 _1d。
不管它会怎样
在 4h 表上算却名叫 1d:那是 4h 的 10/3,不是日线。
拧大 / 拧小 / 拧反
周期跟 st_1d_period / mult。取错 pair:方向是别人的。
merge_informative_pair ffill=True
        dataframe = merge_informative_pair(
            dataframe, informative, self.timeframe, self.informative_timeframe, ffill=True
        )

把日线并进 4h。合并后列名变成 st_1d_1d。ffill=True:一天里的六根 4h,都沿用这根日线收盘后的方向。

它是什么
跨周期对齐。后缀是辅周期名,所以 st_1d 变成 st_1d_1d。
不管它会怎样
ffill=False:只有日线收盘那根 4h 有值,其余五根是空,== "up" 大多为假。
拧大 / 拧小 / 拧反
看错列名去比 st_1d:合并后没有这列,真正要比的是 st_1d_1d。
入场:三条 4h 都 up
                (dataframe["st_fast"] == "up")
                & (dataframe["st_mid"] == "up")
                & (dataframe["st_slow"] == "up")

快、中、慢都向上,才承认 4 小时这边同意。三行是一个意思:四人里的三个小的举手。

它是什么
4h 三票。必须同时 up。
不管它会怎样
只看一条:翻得太勤。三条是为了少被单线晃出去。
拧大 / 拧小 / 拧反
改成任意一条 up:滤网废了。要求再多一条:更难等齐。
入场:日线也 up,且有量
                & (dataframe["st_1d_1d"] == "up")
                & (dataframe["volume"] > 0)

日线那一票也要向上,并且这根 4h 有量。列名是合并后的 st_1d_1d,不是 st_1d。

它是什么
大周期一票否决加零量过滤。
不管它会怎样
不管日线:4h 自己玩。写 st_1d:列不存在。去掉量:零量棒也可能进。
拧大 / 拧小 / 拧反
改成日线 down 才买:逆着大天气出门,逻辑反了。
出场:只看 st_mid == down
                (dataframe["st_mid"] == "down")
                & (dataframe["volume"] > 0)

主线(经典 14,3)翻空就走。注释写了:不等三条卖点凑齐,官方卖点偏晚。有量才写。

它是什么
出门听主路牌。进门四人同意,出门不要求全翻。
不管它会怎样
出门也要三条 down:你会在回撤里多坐一截。
拧大 / 拧小 / 拧反
改成任意一条 down:更碎。改成只看慢线:更晚。官方那种「另外三条都 down」这版没用。

3假懂

人们会说:「买要四条都 up,卖也该四条都 down,才对称。」
更短的一句:文件故意不对称。入场是 st_fast / st_mid / st_slow / st_1d_1d 全 up。出场只有 st_mid == down。注释写明官方卖点偏晚。对称不是这版的目标。

4你来讲

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

  1. 合并之后为什么要比 st_1d_1d,而不是 st_1d?ffill=True 少了会怎样?
  2. 三条 4h 的 period/mult 各是多少?为什么买要三条都 up,卖只看 st_mid?
  3. _st_dir 为什么丢掉轨道数值,只留 STX?和 "up" 比的是价格还是立场?