将您自己的 LLM 集成到 EA 中(第 3 部分):使用 CPU 训练自己的 LLM(基础篇)
📘

将您自己的 LLM 集成到 EA 中(第 3 部分):使用 CPU 训练自己的 LLM(基础篇)

第 1/3 篇

「在 MT5 里用 CPU 跑通自己的 LLM 训练」

把大语言模型接进 EA 并不一定要靠云端 GPU,MetaTrader 5 的本地环境就能用 CPU 完成轻量训练。2025 年 2 月 21 日发布的示例工程显示,一个参数量可控的 LLM 在普通多核处理器上也能完成前向与反向传播,适合把行情文本信号做成私有模型。 外汇与贵金属市场杠杆高、跳空频繁,本地训练出的模型只代表历史样本下的概率倾向,实盘前必须在 MT5 策略测试器里用 tick 级数据回测。 下面这段 MQL5 代码演示了如何在 EA 中初始化一个极简线性层并做 CPU 上的梯度更新,重点看权重数组与学习率的硬设定。

MQL5 / C++
class="type">class="kw">double weights[class="num">10];
class="type">class="kw">double lr = class="num">0.01;
for(class="type">int i=class="num">0;i<class="num">10;i++){
   class="type">class="kw">double grad = ComputeGradient(i);
   weights[i] = weights[i] - lr * grad;
}

在普通电脑上跑LLM训练的可行性

上一节我们把 WSL 加 llama.cpp 的环境跑通了,核心结论是:不依赖独显,纯 CPU 也能让一个轻量 LLM 实例跑起来。这一节先把系列的定位说清楚——后续示例都尽量压低硬件门槛,让读者在自家笔记本上就能复现。 系列会分两条硬件分支:纯 CPU 训练线,以及支持 AMD 显卡加速的计算线。模型训练章节里两者都会给到,避免出现「没好卡就别玩」的门槛。 有人会质疑,CPU 训出来的模型能干什么?客观说,让它学复杂金融推理不现实,但针对某类固定格式、样本量不大的任务(比如特定品种的价格注释归类),CPU 版完全够用。本文就聚焦用 CPU 造一个金融数据集并跑通训练。 外汇与贵金属数据带杠杆、波动剧烈,用模型辅助分析属高风险行为,任何输出仅作概率参考。文中涉及的前期环境配置不重复展开,需要的读者可查本系列前篇。

◍ Tokenizer 与预训练模型的分工

在 MT5 接 LLM 做行情点评前,先得弄清文本是怎么被切成 token 的。Tokenizer 把一段文字拆成独立标记再转成向量,这一步决定了模型能『看懂』什么。主流实现已封装在 Transformers 和 tiktoken 库里,不用自己写底层。 不同预训练模型对应不同结构:Encoder 类(BERT、RoBERTa、ALBERT)擅长句子分类和实体识别;Decoder 类(GPT-2、CTRL、Transformer XL)围绕预测下一个词训练,适合生成类任务;Encoder-Decoder 类(BART、T5、mBART)则用于翻译、摘要等输入到输出的重写。

实际切串时,模型靠特殊符号定位边界。我们这套流程用 `<endoftext>` 作终止符,而不是 BERT 系的 [CLS]/[SEP],接 GPT 类模型时少一层转换。外汇与贵金属信号解读属高风险场景,任何文本生成结果都只是概率倾向,需人工复核。

「在 CPU 上造一个 60 根收盘价的序列池」

自己搭数据集最磨人,公开教程多教怎么用现成数据训模型,少有讲怎么按自己的想法攒数据。外汇与贵金属交易带杠杆,数据准备失误会直接放大实盘风险,这一步得自己踩通。 考虑到多数 PC 只在 CPU 上跑,序列不能太长,否则取数和处理会慢到没法调试。示例里只拉单品种 2500 个报价点做底料,纯演示用途,结果理想与否不保证;想要更好表现,得换更大的集或重做预处理,那些不在这基础示例里。 具体切法:只取报价里的 close 列,从索引 0 起每 60 个报价作为一个序列,不足 60 的丢弃。序列长度 60 是依 CPU 能力定的,原则上越长潜在效果可能越好,你可按机器改 sr_len。用 ct 控取几个品种、k 控偏移量捞序列,剩的自动停写。 账户类型是隐藏坑:示例用 symbols_get(group='*micro*') 是因微型账户,标准户要把条件删掉,否则一个品种都捞不到;把 'micro' 换成 'GBP' 就能只抓英镑系。处理完建议落盘 llm_data.csv,免得下次重连终端再拉。 下面代码封成函数就能反复调。注意 mt_data_len=2500、sr_len=60 这两个数是示例基线,你改了它们,序列池规模和单条长度会直接变。

MQL5 / C++
DATA_DIR = os.path.dirname(__file__)
data_file = os.path.join(DATA_DIR, "llm_data.csv")
    mt_data_len=class="num">2500
    sr_len=class="num">60
    if not mt.initialize():
        print("mt initialize failed!")
    else:
        sbs=mt.symbols_get(group=&class="macro">#x27;*micro*&class="macro">#x27;)
        if sbs is not None:
            # for i in [mt.TIMEFRAME_M5,mt.TIMEFRAME_M15,mt.TIMEFRAME_H1,mt.TIMEFRAME_D1]:
            for i in [mt.TIMEFRAME_M5,]:
                xy=None
                # xy_list=[]
                ct=class="num">0
                for j in sbs:
                    if ct>class="num">0:
                        class="kw">break
                    print(j.name)
                    d_=mt.copy_rates_from_pos(j.name,i,class="num">0,mt_data_len)
                    df_d=pd.DataFrame(d_)
                    cl_d=df_d[&class="macro">#x27;close&class="macro">#x27;]
                    k=class="num">0
                    while k+class="num">1:
                        if mt_data_len-k>=sr_len:
                            cl_ds=cl_d[k:k+sr_len].tolist()
                            if xy is None:
                                xy=pd.DataFrame([cl_ds])
                                # xy_list=[cl_ds]
                            else:
                                xy.loc[len(xy)]=cl_ds
                                # xy_list.append(cl_ds)

常见问题

可以,CPU 能跑通基础训练,只是速度慢;用 60 根收盘价的小序列池就能在普通电脑上验证可行性。
Tokenizer 负责把价格序列切成可计算的 token,预训练模型学这些 token 的分布规律,两者分工不重叠。
可以,小布能替你跑通 CPU 训练流程并标记异常,你只管看结论和调整序列池参数。
基础篇实测 60 根收盘价足够跑通,内存占用低,适合先验证再扩容。
多半是 tokenizer 切分方式和序列长度不匹配,先固定 60 根再查切分逻辑。