第 8 章 · 03 比特币大波动分类案例


文档摘要

第 8 章 · 03 比特币大波动分类案例 本节摘要:本节用一个完整案例把前两节串起来——精读 ( ),ABU 机器学习与交易决策衔接的最佳示例。BtcBigWaveClf 解决一个具体问题:预测今天比特币会不会有大波动。它把"大波动"定义为 (日震荡 5.5%),作为分类标签 y;注入 ma5/ma10/ma21/ma60 四条均线作为特征;用三倍数据增强( / / 向前跳 1/2 条各生成一组特征)把样本量翻三倍;核心变换 把"连续 3 天 K 线"压缩成"1 条特征":用 标准化连续特征(消除绝对价格差异),第 1/2 天取全部特征改 / 前缀,第 3 天只取 open/low/preclose/dateweek + bigwave(作 y),用 把"周几"离散化成 one-hot。

第 8 章 · 03 比特币大波动分类案例

本节摘要:本节用一个完整案例把前两节串起来——精读 BtcBigWaveClf(ABuMLPd.py:158-289),ABU 机器学习与交易决策衔接的最佳示例。BtcBigWaveClf 解决一个具体问题:预测今天比特币会不会有大波动。它把"大波动"定义为 (high - low) / pre_close > 0.055(日震荡 5.5%),作为分类标签 y;注入 ma5/ma10/ma21/ma60 四条均线作为特征;用三倍数据增强(btc_siblings_df(raw) / raw[1:] / raw[2:] 向前跳 1/2 条各生成一组特征)把样本量翻三倍;核心变换 btc_siblings_df 把"连续 3 天 K 线"压缩成"1 条特征":用 scaler_std 标准化连续特征(消除绝对价格差异),第 1/2 天取全部特征改 one_*/two_* 前缀,第 3 天只取 open/low/pre_close/date_week + big_wave(作 y),用 pd.get_dummies 把"周几"离散化成 one-hot。训练好后,AbuBTCDayBuy.fit_day(ABuFactorBuyDemo.py:210-329)在回测中调用 btc_ml.predict(btc_today_x),预测为大波动才考虑买入——这是 ABU 把 ML 预测作为买入信号的标准范式。本节最后总结 ABU 的三条 ML 接入路径:① UMP 裁判用 predict_proba_threshold 拦截;② BtcBigWaveClf 把 predict 作为买入信号;③ AbuCrossVal 用相关度做策略稳健性验证。读完本节,你将看到 ABU 是怎么把第 1 节的三层架构、第 2 节的概率阈值搜索,落地成一个可回测的完整策略。

内容来源:原项目源码 abupy/MLBu/ABuMLPd.py 的 BtcBigWaveClf 类(L158-289)+ abupy/FactorBuyBu/ABuFactorBuyDemo.py 的 AbuBTCDayBuy 类(L210-329)。

⚠️ 注意:本节是第 8 章的总结。建议先读懂前两节(三层架构 + 概率阈值搜索),再读本节。重点理解"三倍数据增强"为什么有效(比特币样本少,3 天窗口的滑动切片能在不引入未来函数的前提下扩样),以及 btc_siblings_df 为什么是 ABU 全书最有"特征工程味道"的代码。

学习目标

阅读完本节,你应当能够:

  1. 解释 BtcBigWaveClf 的 y 标签定义((high - low) / pre_close > 0.055)及 0.055 阈值的业务含义。
  2. 说清三倍数据增强的原理(raw / raw[1:] / raw[2:] 各跑一次 btc_siblings_df),以及为什么不引入未来函数。
  3. 逐行读懂 btc_siblings_df:3 天一组切片 → scaler_std 标准化连续特征 → 第 1/2 天改 one_*/two_* 前缀、第 3 天只取子集改 today_* 前缀 + big_wave → concat 成一条。
  4. 解释为什么第 3 天只取 open/low/pre_close/date_week(避免泄漏当天完整 K 线)。
  5. 说清 pd.get_dummies 周几离散化的作用,以及 AbuBTCDayBuy 在运行时怎么手动 one-hot。
  6. 逐行读懂 AbuBTCDayBuy.fit_day:make_btc_today 构造特征 → btc_ml.predictsimilar_predict 投票 → buy_today()
  7. 列举 ABU 的三条 ML 接入路径(UMP 拦截 / 买入信号 / 稳健性验证)及各自的技术核心。

一、业务问题:预测比特币大波动

比特币日内交易的核心痛点:今天值不值得做交易。如果今天波动很小(比如全天振幅 1%),日内交易根本赚不到钱(覆盖不了手续费和滑点);只有大波动日才值得做。

BtcBigWaveClf(ABuMLPd.py:158-171)就是把这个判断 ML 化:

158 class BtcBigWaveClf(AbuMLPd): 159 """ 160 任何大的决策其实都是由很多看极起来极不起眼的小事组成的,如果我们是做比特币日内的交易者, 161 首先你需要判断今天适不适合做交易,做出这个判断的依据里有一条即是今天的波动需要足够大 162 """ 163 164 def __init__(self, **kwarg): 169 self.btc = kwarg.pop('btc', None) 170 super(BtcBigWaveClf, self).__init__(**kwarg)

BtcBigWaveClf 继承 AbuMLPd(第 1 节讲的业务层抽象基类),__init__ 把外部传入的 btc 数据 pop 出来,再调父类构造。父类 __init__ 会自动调 make_xy(下面详讲),把金融数据切成 x/y/df 三件套,然后构造 self.fiter = AbuML(...)。从此 BtcBigWaveClf 实例就拥有了 AbuML 的全部方法(__getattr__ 代理)。

big_wave 标签定义(ABuMLPd.py:181-182)

180 # .055的日震荡幅度可以成做大波动的交易对比特币来说,下面对数据添加新列big_wave 181 btc['big_wave'] = (btc.high - btc.low) / btc.pre_close > 0.055 182 btc['big_wave'] = btc['big_wave'].astype(int)

(high - low) / pre_close 是日震荡率(最高价减最低价除以昨收)。> 0.055 即日震荡超过 5.5%,astype(int) 把布尔转成 0/1。5.5% 是 ABU 的经验阈值——比特币日波动大,5.5% 算"够大"的日子。

这个 0/1 就是 y 标签。注意这是个二分类问题,所以第 1 节的 entry_wrapper 会把 E_FIT_AUTO 归约成 E_FIT_CLF(因为 len(np.unique(y)) = 2 ≤ 10)。BtcBigWaveClf 不用显式声明分类,自动判断。

二、make_xy:特征注入 + 三倍数据增强

make_xy(ABuMLPd.py:172-237)是 BtcBigWaveClf 的核心。先看特征注入(L193-201):

193 # 下面为训练集和测试集数据都加上5,10,21,60日均线特征 194 def calc_ma(tc, p_ma): 195 ma_key = 'p_ma{}'.format(p_ma) 196 tc[ma_key] = ABuNDMa.calc_ma_from_prices(tc.close, p_ma, min_periods=1) 197 198 for ma in [5, 10, 21, 60]: 199 calc_ma(btc_train_raw, ma) 200 if btc_test_raw is not None: 201 calc_ma(btc_test_raw, ma)

注入四条均线:ma5(周线)、ma10(半月线)、ma21(月线)、ma60(季线)。这四条均线代表短/中/长期趋势。calc_ma_from_prices 是 ABu 的均线计算函数(第 9 章详讲),min_periods=1 保证开头数据不足时也能算(用部分数据)。

均线是技术分析的核心特征——它们捕捉"价格相对趋势的位置"。大波动往往发生在价格突破均线(ma5 上穿 ma60)或均线收敛后发散时,这些信息原始 OHLC 给不了,必须注入。

三倍数据增强(L203-209)

203 # 下面使用训练集数据btc_train_raw做为参数抽取组合特征,重新组合好的特征 204 btc_train0 = self.btc_siblings_df(btc_train_raw) 205 # 由于每3条连续交易日数据组合成一个特征,只要向前跳一条数据进行特征组合抽取即可以得到另一组新特征 206 btc_train1 = self.btc_siblings_df(btc_train_raw[1:]) 207 btc_train2 = self.btc_siblings_df(btc_train_raw[2:]) 208 209 # 把周几这个特征使用pd.get_dummies进行离散化处理 210 btc_train = pd.concat([btc_train0, btc_train1, btc_train2])

关键三行(204/206/207):

  • btc_train0 = self.btc_siblings_df(btc_train_raw):从第 0 行开始,每 3 天一组切。
  • btc_train1 = self.btc_siblings_df(btc_train_raw[1:]):从第 1 行开始(跳过第 0 天),每 3 天一组切。
  • btc_train2 = self.btc_siblings_df(btc_train_raw[2:]):从第 2 行开始(跳过前 2 天),每 3 天一组切。

三组结果 concat,样本量接近三倍。为什么这有效?因为 btc_siblings_df 是按"固定 3 天一组"切的(第 0-2 天一组、第 3-5 天一组...),中间的"第 1-3 天""第 2-4 天"组合被漏掉。向前跳 1/2 条再切,就把这些漏掉的组合都纳入——本质是滑动窗口,步长从 3 降到 1。

**为什么不引入未来函数?**每个 3 天窗口里的特征都来自窗口内的 3 天(第 1/2 天的全部 + 第 3 天的子集),y 是第 3 天的 big_wave。预测时输入的是"前 2 天 + 今天部分特征",输出"今天是否大波动"——预测用的是过去和当下,没有未来信息。三倍增强只是增加了训练样本的多样性,没有改变"用过去预测当下"的因果结构。

测试集也做同样的三倍增强(L222-237),保持训练/测试特征分布一致。

💡 解剖要点:三倍数据增强是处理"金融数据样本少"的经典手法。比特币 2013-2017 年约 1400 个交易日,去掉 60 天测试集剩 1340 天。如果固定 3 天一组,只能切 446 个样本;滑动窗口(步长 1)能切 1338 个,接近三倍。这种增强对 ML 特别重要——样本越多,模型越不容易过拟合。但要注意:增强后的样本不是完全独立的(相邻窗口共享 2 天数据),所以交叉验证的 KFold 可能高估精度。ABU 没有显式处理这个相关性,是已知的统计瑕疵。

三、btc_siblings_df:3 天 K 线 → 1 条特征

btc_siblings_df(ABuMLPd.py:240-289)是全节最精妙的函数,把 3 天 K 线压缩成 1 条 ML 特征:

240 def btc_siblings_df(self, btc_raw): 253 # 将所有交易日以3个为一组,切割成多个子df 254 btc_siblings = [btc_raw.iloc[sib_ind * 3:(sib_ind + 1) * 3, :] 255 for sib_ind in np.arange(0, int(btc_raw.shape[0] / 3))] 256 257 btc_df = pd.DataFrame() 258 for sib_btc in btc_siblings: 259 # 使用数据标准化将连续3天交易日中的连续数值特征进行标准化操作 260 sib_btc_scale = ABuScalerUtil.scaler_std( 261 sib_btc.filter(['open', 'close', 'high', 'low', 'volume', 'pre_close', 262 'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14'])) 263 # 把标准化后的和big_wave,date_week连接起来 264 sib_btc_scale = pd.concat([sib_btc['big_wave'], sib_btc_scale, sib_btc['date_week']], axis=1)

3.1 第一步:3 天一组切片(L254-255)

btc_siblings = [btc_raw.iloc[sib_ind * 3:(sib_ind + 1) * 3, :] for sib_ind in np.arange(0, int(btc_raw.shape[0] / 3))]

列表推导,每个 sib_btc 是 3 行(3 天)的子 DataFrame。int(btc_raw.shape[0] / 3) 算能切多少组,余数(最后 1-2 天)丢弃。

3.2 第二步:scaler_std 标准化连续特征(L260-262)

sib_btc_scale = ABuScalerUtil.scaler_std( sib_btc.filter(['open', 'close', 'high', 'low', 'volume', 'pre_close', 'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14']))

scaler_std 是 ABU 的标准化工具(封装 sklearn StandardScaler)。关键:标准化是按 3 天一组做的,不是全局。这消除了"绝对价格差异"——比特币 2013 年 100 美元,2017 年 4000 美元,绝对价格差 40 倍,直接用原始价格会让模型只学到"价格高=某个时期"。标准化后,模型学到的是"这 3 天内的相对形态"(涨跌、波动率),这才是跨周期稳定的信号。

filter 选 12 个连续特征:OHLCV + pre_close + 4 条均线 + 2 个 ATR(平均真实波幅)。这些都是连续数值,需要标准化。

3.3 第三步:拼接 big_wave + date_week(L264)

sib_btc_scale = pd.concat([sib_btc['big_wave'], sib_btc_scale, sib_btc['date_week']], axis=1)

big_wave 是 0/1 离散标签(不标准化),date_week 是 0-6 离散(周几,不标准化)。concat 拼回标准化后的连续特征。

3.4 第四步:抽取 + 改前缀(L266-286)

266 # 抽取第一天,第二天的大多数特征分别改名字以one,two为特征前缀 267 a0 = sib_btc_scale.iloc[0].filter(['open', 'close', 'high', 'low', 'volume', 'pre_close', 268 'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14', 'date_week']) 269 a0.rename(index={'open': 'one_open', 'close': 'one_close', 'high': 'one_high', 'low': 'one_low', 270 'volume': 'one_volume', 'pre_close': 'one_pre_close', 271 'ma5': 'one_ma5', 'ma10': 'one_ma10', 'ma21': 'one_ma21', 272 'ma60': 'one_ma60', 'atr21': 'one_atr21', 'atr14': 'one_atr14', 273 'date_week': 'one_date_week'}, inplace=True) 274 275 a1 = sib_btc_scale.iloc[1].filter([...]) # 同 a0,前缀改 two_ 281 282 # 第三天的特征只使用'open', 'low', 'pre_close', 'date_week',该名前缀today 283 a2 = sib_btc_scale.iloc[2].filter(['big_wave', 'open', 'low', 'pre_close', 'date_week']) 284 a2.rename(index={'open': 'today_open', 'low': 'today_low', 285 'pre_close': 'today_pre_close', 286 'date_week': 'today_date_week'}, inplace=True)

三天的处理策略不同:

取哪些特征 改什么前缀 为啥
第 1 天(前天) 全部 12 连续 + date_week one_* 历史完整信息,全要
第 2 天(昨天) 全部 12 连续 + date_week two_* 历史完整信息,全要
第 3 天(今天) 只 big_wave + open + low + pre_close + date_week today_* 刻意不全

第 3 天只取 open/low/pre_close 是反常识的——明明有 close/high 为什么不要?答案是避免泄漏当天完整信息。big_wave 是用 (high - low) / pre_close > 0.055 算的,如果第 3 天带上 high,模型直接学"high - low > 0.055 × pre_close → big_wave=1",变成恒等式,没有任何预测价值。

实战中,AbuBTCDayBuy 是当日买入(下面讲),决策时刻只有 open(开盘能知道)。low 是盘中实时更新,close/high 要收盘才知道。所以第 3 天的特征必须是"决策时刻能拿到的信息"——open + pre_close + date_week 是开盘就确定的,low 是盘中近似可得(虽然收盘才精确)。big_wave 作为 y,只在训练时用(运行时预测不算 big_wave,而是预测它)。

3.5 第五步:concat 成一条(L288)

288 btc_df = btc_df.append(pd.concat([a0, a1, a2], axis=0), ignore_index=True)

a0(13 字段)+ a1(13 字段)+ a2(5 字段)= 31 字段,组成一条。a0/a1/a2 都是 Series(concat axis=0 拼成 31 长的 Series),append 到 btc_df 成一行。循环完所有 3 天组,btc_df 就是 ML 用的特征矩阵。

四、get_dummies 周几离散化(ABuMLPd.py:211-216)

211 dummies_one_week = pd.get_dummies(btc_train['one_date_week'], prefix='one_date_week') 212 dummies_two_week = pd.get_dummies(btc_train['two_date_week'], prefix='two_date_week') 213 dummies_today_week = pd.get_dummies(btc_train['today_date_week'], prefix='today_date_week') 214 btc_train.drop(['one_date_week', 'two_date_week', 'today_date_week'], inplace=True, axis=1) 215 # make_xy中需要确定self.df 216 self.df = pd.concat([btc_train, dummies_one_week, dummies_two_week, dummies_today_week], axis=1) 217 # make_xy中需要确定x, y 218 train_matrix = self.df.as_matrix() 219 self.y = train_matrix[:, 0] 220 self.x = train_matrix[:, 1:]

pd.get_dummies 把"周几"(0-6 整数)展开成 7 列 one-hot(monday=0 → [1,0,0,0,0,0,0])。三个周几字段(第 1/2/3 天)各展开 7 列,共 21 列。drop 掉原始的整数列,concat one-hot 列。

为什么要 one-hot?因为 date_week 是离散类别,不是有序数值——周一(0)和周二(1)在数值上差 1,但语义上没有"周二比周一大"的关系。如果直接用整数,模型(尤其是线性模型、距离模型如 KNN)会误以为有大小关系。one-hot 让每个周几独立成一维,模型可以学到"周一容易大波动""周末波动小"这种周期性模式。

219-220 行遵循 ABU 的硬约定:y 在第一列(big_wave,因为 btc_siblings_df 里 a2 第一个字段是 big_wave),x 是其余列。这跟第 1 节讲的 list(self.df.columns)[1:] 跳过 y 完全一致。

五、AbuBTCDayBuy.fit_day:ML 作为买入信号

训练好 BtcBigWaveClf 后,怎么在回测里用?AbuBTCDayBuy(ABuFactorBuyDemo.py:210-329)给出范式:

210 class AbuBTCDayBuy(AbuFactorBuyBase, BuyCallMixin): 211 """ 212 比特币日交易策略: 213 1. 买入条件1: 当日这100个股票60%以上都是上涨的 214 2. 买入条件2: 使用在第12节:机器学习与比特币示例中编写的:信号发出今天比特币会有大行情 215 """ 216 237 def fit_day(self, today): 242 # 忽略不符合买入的天(统计周期内前两天, 因为btc的机器学习特证需要三天交易数据) 243 if self.today_ind < 2: 244 return None 245 246 # 今天,昨天,前天三天的交易数据进行特证转换 247 btc = self.kl_pd[self.today_ind - 2:self.today_ind + 1] 248 # 三天的交易数据进行转换后得到btc_today_x 249 btc_today_x = self.make_btc_today(btc) 250 251 # btc_ml并没有在这里传入,实际如果要使用,需要对外部的btc_ml进行本地序列化后,构造读取本地 252 # 买入条件2: 使用在第12节:机器学习与比特币示例中编写的:信号发出今天比特币会有大行情 253 if btc_ml.predict(btc_today_x): 254 # 买入条件1: 当日这100个股票60%以上都是上涨的 255 vote_val = self.similar_predict(today.date) 256 if vote_val > self.btc_vote_val: 257 # 没有使用当天交易日的close等数据,且btc_ml判断的大波动是当日,所以当日买入 258 return self.buy_today()

两个买入条件 AND:

  1. btc_ml.predict(btc_today_x)(253 行):ML 预测今天有大波动。make_btc_today 把回测中的 3 天 K 线用与训练时相同的逻辑(标准化 + one/two/today 前缀 + 周几 one-hot)转成特征向量。
  2. similar_predict(today.date) > btc_vote_val(255-256 行):与比特币最相关的 top 100 股票中,60% 今天方向一致(都涨或都跌,考虑相关性正负)。

两个条件都满足,buy_today()(258 行)当日买入。注意是 buy_today 不是 buy_tomorrow——因为比特币 7×24 交易,且大波动判定是当日的,信号出来当天就得买(第 3 章讲过 buy_today 适合 7×24 市场)。

make_btc_today:运行时特征构造(L261-310)

make_btc_todaybtc_siblings_df 的"单样本运行时版"——训练时批量处理,运行时一次处理一条:

261 def make_btc_today(self, sib_btc): 265 sib_btc['big_wave'] = (sib_btc.high - sib_btc.low) / sib_btc.pre_close > 0.55 # ← 注意 0.55 不是 0.055 266 sib_btc['big_wave'] = sib_btc['big_wave'].astype(int) 267 sib_btc_scale = ABuScalerUtil.scaler_std( 268 sib_btc.filter(['open', 'close', 'high', 'low', 'volume', 'pre_close', 269 'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14']))

注意 265 行的 0.55 是源码笔误(训练时是 0.055),但这无所谓——运行时 big_wave 不参与预测(只是特征构造流程的一部分),predict 用的 x 会去掉 y 列(L310 [:, 1:])。这种小瑕疵在 ABU 源码里偶尔出现,读源码时要警惕。

之后流程与 btc_siblings_df 完全一致:scaler_std 标准化 → a0/a1 取全部改 one_/two_ → a2 取子集改 today_ → concat。唯一区别是周几 one-hot(L298-309):

298 dummies_week_col = btc_ml.df.filter(regex='(^one_date_week_|^two_date_week_|^today_date_week_)').columns 299 dummies_week_df = pd.DataFrame(np.zeros((1, len(dummies_week_col))), columns=dummies_week_col) 300 301 # 手动修改每一天的one hot 302 one_day_key = 'one_date_week_{}'.format(btc_today.one_date_week.values[0]) 303 dummies_week_df[one_day_key] = 1

训练时用 pd.get_dummies 自动 one-hot(因为批量),运行时手动 one-hot(因为只有一条):先创建全 0 的 DataFrame(列名从 btc_ml.df 抄,保证列顺序一致),再根据实际周几把对应列置 1。这种"训练自动 + 运行时手动"的设计,保证了运行时特征列与训练时完全对齐(否则 predict 会因列数不匹配报错)。

💡 解剖要点:make_btc_today 揭示了 ML 工程化的核心难点——训练特征构造与运行时特征构造必须完全一致。同一个标准化逻辑(scaler_std)、同一个前缀规则(one/two/today)、同一个 one-hot 列顺序。任何一处不一致都会让 predict 失效。ABU 用"复制 btc_siblings_df 的逻辑"实现一致性,代价是两份代码需要同步维护。生产级 ML 系统通常用 sklearn Pipeline + ColumnTransformer 把特征工程流水线化,避免这种复制。ABU 受限于代码风格,选择了复制路线。

六、AbuBTCDayBuy 的设计意图:两个独立信号的 AND

为什么 AbuBTCDayBuy 要 AND 两个条件,而不是只用 ML?答案是信号正交性。ML 学的是"基于历史 K 线形态,今天是否大波动";similar_predict 学的是"基于市场其他股票,今天比特币是否被同步推动"。两个信号来源完全不同(技术面 vs 市场情绪),误判的相关性低。AND 之后,只有"ML 说是大波动 + 市场也确认"才买入,大幅降低误判。

similar_predict(ABuFactorBuyDemo.py:312-328)的实现:对 btc_similar_top 里每个相关股票,查它今天涨还是跌,乘以 vote_direction(负相关股票反向),统计"方向一致的比例"。1 - False 占比 = 支持率。这跟第 6 章的"市场宽度"思路一脉相承。

七、ML 与回测衔接的三条路径(全章总结)

至此,第 8 章的三条 ML 接入路径全部讲完。汇总如下:

路径 接入点 ML 角色 技术核心
① UMP 拦截 回测 make_buy_order 钩子 决策是否拦截已发出的订单 GMM 聚类找危险簇 / predict_proba_threshold 高放行低拦截
② 买入信号 买入因子 fit_day 决策是否买入 btc_ml.predict(btc_today_x) 作为 AND 条件之一
③ 稳健性验证 回测后分析 决策策略是否可信 AbuCrossVal 用策略间相关度判断过拟合

路径①是第 7 章的主题——UMP 裁判用 GMM(主裁)或 KNN(边裁)学习历史交易特征,对新订单 predict_proba_threshold 拦截。本节第 2 章讲的 cross_val_prob_accuracy_score + search_match_pos_threshold 就是 UMP 找最优阈值的工具。

路径②是本节的主题——BtcBigWaveClf 把 ML 预测直接作为买入信号。AbuBTCDayBuy 的 fit_daybtc_ml.predict,这是 ABU 唯一一个"ML 直接决定买入"的示例因子。

路径③AbuCrossVal 不在本章范围(属于第 11 章回测分析),但它用 ML 的相关度做策略过拟合检测——把多个策略的收益序列算相关矩阵,相关性高的策略组(>0.7)很可能是对同一批数据的过拟合,实盘会同时失效。这是 ML 在"策略评估"层的应用。

三条路径共同体现 ABU 的设计哲学:ML 不是孤立的预测模型,而是嵌入回测各环节的决策辅助。从"要不要买"(路径②)、"买了要不要拦"(路径①)、"策略可不可信"(路径③),ML 在每个决策点都提供服务。这种"ML as a service"的架构,让 ABU 的回测流水线具备了"自我进化"的能力——回测越多,UMP 越聪明,买入信号越准,策略评估越可靠。

本节要点回顾

  1. BtcBigWaveClf y 标签:(high - low) / pre_close > 0.055(日震荡 5.5%),astype(int) 转 0/1。继承 AbuMLPd,自动归约成 CLF。
  2. 特征注入:ma5/ma10/ma21/ma60 四条均线,捕捉短/中/长期趋势。原始 OHLC 给不了均线信息,必须显式注入。
  3. 三倍数据增强:btc_siblings_df(raw) / raw[1:] / raw[2:] 各切一次。本质是滑动窗口(步长 1 替代步长 3),把样本量翻三倍,不引入未来函数(每个窗口只用过去和当下信息)。
  4. btc_siblings_df 五步:3 天一组切片 → scaler_std 标准化 12 连续特征(按组内标准化,消除绝对价格差异)→ 第 1/2 天取全部改 one_/two_ → 第 3 天只取 big_wave+open+low+pre_close+date_week 改 today_*(避免泄漏 high/close)→ concat 成 31 字段一条。
  5. 第 3 天只取子集:避免泄漏当天完整 K 线(big_wave 由 high-low 算出,带 high 等于告诉答案)。决策时刻只能拿到 open/pre_close/date_week(开盘确定)+ low(盘中近似)。
  6. get_dummies 周几离散化:训练时自动 one-hot(批量),运行时 make_btc_today 手动 one-hot(单条)。列顺序从 btc_ml.df 抄,保证训练/运行时特征对齐。
  7. AbuBTCDayBuy.fit_day:today_ind < 2 跳过(需要 3 天数据)→ make_btc_today 构造特征 → btc_ml.predict(ML 信号) AND similar_predict > btc_vote_val(市场信号)→ buy_today() 当日买入。
  8. 两信号 AND 的动机:ML(技术面)与 similar_predict(市场情绪)来源正交,误判相关性低,AND 后大幅降低误判。
  9. ML 接入三路径:① UMP 拦截(predict_proba_threshold 高放行低拦截,决策拦截);② 买入信号(BtcBigWaveClf predict 作 AND 条件,决策买入);③ 稳健性验证(AbuCrossVal 相关度,决策策略可信度)。ML 嵌入回测各环节,非孤立预测模型。

第 8 章到此结束。下一章(第 9 章)讲 ABU 的技术分析模块(TLineBu 趋势线、IndicatorBu 指标),它们为 ML 提供更多特征(均线、ATR、MACD 等),也为买入/卖出因子提供更多触发条件。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U