财经建模中合成数据的生成式对抗网络(GAN)(第 2 部分):创建测试合成品种·进阶篇
「给合成品种挂上报价与跳动参数」
在 MT5 里造一个自定义合成符号,第一步是把交易相关的双精度属性钉死。下面这段代码把每跳价值锁成 1,最小变动价位设成 0.00001,意味着价格每动 0.00001 账面就跳 1 单位保证金等价,点差设为浮动模式,避免被券商固定点差逻辑干扰。 接着从 CSV 把历史 rates 读进来,读失败直接 Print 报错并 return,不往下走脏数据。rates 到位后用 CustomRatesUpdate 灌进符号,失败则打出 GetLastError 方便排查;成功才调用 MarketBookAdd 把符号丢进市场报价窗口。 整段跑完若终端打印“Synthetic symbol successfully created and added to Market Watch.”,说明自定义品种已可在 MT5 里看见并接收你自己的序列。外汇与贵金属合成标的同样受平台高风险规则约束,爆仓概率不因为数据是本地生成的而降低。
CustomSymbolSetDouble(syntheticSymbol, SYMBOL_TRADE_TICK_VALUE, class="num">1); CustomSymbolSetDouble(syntheticSymbol, SYMBOL_TRADE_TICK_SIZE, class="num">0.00001); CustomSymbolSetInteger(syntheticSymbol, SYMBOL_SPREAD_FLOAT, true); class=class="str">"cmt">// Step class="num">3: Load Data from CSV class="type">MqlRates rates[]; if (!ReadSyntheticDataFromCSV(SYNTHETIC_CSV_FILE_NAME, rates)) { Print("Error reading synthetic data from CSV."); class="kw">return; } class=class="str">"cmt">// Step class="num">4: Update Rates and Add to Market Watch if (!CustomRatesUpdate(syntheticSymbol, rates)) { Print("Error updating synthetic symbol rates: ", GetLastError()); class="kw">return; } MarketBookAdd(syntheticSymbol); class=class="str">"cmt">// Add to Market Watch Print("Synthetic symbol successfully created and added to Market Watch.");}
用夏皮罗-威尔克看合成与真实盘口像不像
夏皮罗-威尔克检验干一件事:判断一组样本是否贴合正态分布。做合成行情的人最怕自嗨——造出来的数据分布和真实 EURUSD 根本不是一回事,拿去回测只会得出漂亮但无用的结论。 检验逻辑只有两个假设:H₀ 是数据正态,H₁ 是非正态。跑完看 p 值,p > 0.05 就倾向接受 H₀,认为样本像正态分布;p ≤ 0.05 则拒绝,分布明显偏了。 实测一组三年 EURUSD 收盘价,合成与真实同周期对齐后分别跑检验:合成 W=0.998、p=0.432,真实 W=0.997、p=0.398。两者 p 都远超 0.05,说明这套合成数据在分布形态上可能和真实市场匹配得不错,拿来建模有底。 下面这段 Python 用 scipy 直接对比两个 CSV 的 close 列,开个 notebook 把你的合成数据丢进去就能复算。外汇与贵金属属高风险品种,分布检验通过不代表策略能盈利,只代表数据底座没歪。
class="kw">import pandas as pd from scipy.stats class="kw">import shapiro # Load synthetic and real datasets synthetic_data = pd.read_csv(&class="macro">#x27;EURUSD_3_years_synthetic(class="num">1).csv&class="macro">#x27;) real_data = pd.read_csv(&class="macro">#x27;EURUSD_CSV(class="num">1).csv&class="macro">#x27;) # Select the &class="macro">#x27;close&class="macro">#x27; column for the test synthetic_close = synthetic_data[&class="macro">#x27;close&class="macro">#x27;] real_close = real_data[&class="macro">#x27;close&class="macro">#x27;] # Perform Shapiro-Wilk test synthetic_stat, synthetic_p = shapiro(synthetic_close) real_stat, real_p = shapiro(real_close) # Print results print("Shapiro–Wilk Test Results:") print(f"Synthetic Data W-statistic: {synthetic_stat:.4f}, P-value: {synthetic_p:.4f}") print(f"Real Data W-statistic: {real_stat:.4f}, P-value: {real_p:.4f}") # Interpretation if synthetic_p > class="num">0.05: print("Synthetic data follows a normal distribution.") else: print("Synthetic data does not follow a normal distribution.") if real_p > class="num">0.05: print("Real data follows a normal distribution.") else: print("Real data does not follow a normal distribution.")
◍ 用 t 检验核对合成与真实 EURUSD 收盘价
学生 t-检验的核心任务是判断两组样本的平均测量值是否来自同一分布。做财经模型时,我们常拿合成数据去逼近真实行情,若两者的中值差异在统计上站不住脚,说明这套合成引擎大概率抓住了典型市场中价格上下游走的基本形态。 原假设 H₀ 设两组中值相等,对立假设 H₁ 为中值不等。判定线固定在显著性水平 0.05:p 值大于它,接受 H₀,认为中值无显著差异;p 值不大于它,拒绝 H₀,中值显著不同。 实跑一次同周期 EURUSD 合成与真实数据对比,统计量 T = 0.534,p = 0.594。因为 p 明显高于 0.05,两组 close 中值未见显著分离,模型在均值层面通过了现实匹配检验。外汇与贵金属属高风险品种,该结论仅描述样本统计属性,不预示任何未来走势。 下面这段 Python 可直接在本地复算,把两个 csv 换成你自己的合成与实盘导出文件即可: import pandas as pd from scipy.stats import ttest_ind # 载入合成与真实数据集 synthetic_data = pd.read_csv('EURUSD_3_years_synthetic(1).csv') real_data = pd.read_csv('EURUSD_CSV(1).csv') # 抽取 close 列做检验 synthetic_close = synthetic_data['close'] real_close = real_data['close'] # 执行独立双样本 t 检验,方差不等时设 equal_var=False t_stat, p_value = ttest_ind(synthetic_close, real_close, equal_var=False) # 输出结果 print("Student's T-Test Results:") print(f"T-statistic: {t_stat:.4f}, P-value: {p_value:.4f}") # 依据 p 值给出解释 if p_value > 0.05: print("The means of the synthetic and real data are not significantly different.") else: print("The means of the synthetic and real data are significantly different.") 别把 p>0.05 当模型完美 中值无差只说明均值层面贴近,不代表波动率、尾部风险或连跌结构一致。MT5 里导出真实 close 后,建议再补一道方差齐性与分布形态检查。
class="kw">import pandas as pd from scipy.stats class="kw">import ttest_ind # Load synthetic and real datasets synthetic_data = pd.read_csv(&class="macro">#x27;EURUSD_3_years_synthetic(class="num">1).csv&class="macro">#x27;) real_data = pd.read_csv(&class="macro">#x27;EURUSD_CSV(class="num">1).csv&class="macro">#x27;) # Select the &class="macro">#x27;close&class="macro">#x27; column for the test synthetic_close = synthetic_data[&class="macro">#x27;close&class="macro">#x27;] real_close = real_data[&class="macro">#x27;close&class="macro">#x27;] # Perform Student&class="macro">#x27;s t-test t_stat, p_value = ttest_ind(synthetic_close, real_close, equal_var=False) # Use equal_var=False if variances are unequal # Print results print("Student&class="macro">#x27;s T-Test Results:") print(f"T-statistic: {t_stat:.4f}, P-value: {p_value:.4f}") # Interpretation if p_value > class="num">0.05: print("The means of the synthetic and real data are not significantly different.") else: print("The means of the synthetic and real data are significantly different.")
「用莱文检验卡住合成数据的波动失真」
莱文检验干的事很直接:判断两组样本的价格波动方差是否稳定可比。对外汇这类高波动品种,若合成数据方差和真实盘口差太多,拿去做回测或训练就是自欺。EURUSD 这类品种,波动形态本身就是交易信号的一部分,不能只比均值不比离散度。 零假设 H₀ 是两组方差相等,备择 H₁ 是不相等。判定门槛放在 p=0.05:p>0.05 时接受 H₀,认为方差统计上相似;p≤0.05 则拒绝,波动结构存在显著分歧。 实测一组 EURUSD 三年合成与真实数据,取 close 列做检验,得到 W=0.8742、p=0.3517。因为 p 明显大于 0.05,说明合成集和真实集的方差无显著差异,合成数据在波动层面可能可靠代表了市场行为。外汇与贵金属属高风险品类,任何统计相似都不构成实盘盈利保证,仅降低数据失真概率。 下面这段 Python 是跑该检验的最小可运行例,读两个 csv 的 close 列直接出结果: import pandas as pd from scipy.stats import levene # 载入合成与真实数据集 synthetic_data = pd.read_csv('EURUSD_3_years_synthetic(1).csv') real_data = pd.read_csv('EURUSD_CSV(1).csv') # 抽取 close 列用于检验 synthetic_close = synthetic_data['close'] real_close = real_data['close'] # 执行莱文检验 stat, p_value = levene(synthetic_close, real_close) # 输出结果 print("Levene's Test Results:") print(f"Statistic: {stat:.4f}, P-value: {p_value:.4f}") # 结论判断 if p_value > 0.05: print("The variances of the synthetic and real data are not significantly different.") else: print("The variances of the synthetic and real data are significantly different.") 开 MT5 导出真实 EURUSD 的 close,用你自己生成的合成集替换文件路径,跑一遍就能知道合成引擎有没有把波动搞变形。
class="kw">import pandas as pd from scipy.stats class="kw">import levene # Load synthetic and real datasets synthetic_data = pd.read_csv(&class="macro">#x27;EURUSD_3_years_synthetic(class="num">1).csv&class="macro">#x27;) real_data = pd.read_csv(&class="macro">#x27;EURUSD_CSV(class="num">1).csv&class="macro">#x27;) # Select the &class="macro">#x27;close&class="macro">#x27; column for the test synthetic_close = synthetic_data[&class="macro">#x27;close&class="macro">#x27;] real_close = real_data[&class="macro">#x27;close&class="macro">#x27;] # Perform Levene&class="macro">#x27;s test stat, p_value = levene(synthetic_close, real_close) # Print results print("Levene&class="macro">#x27;s Test Results:") print(f"Statistic: {stat:.4f}, P-value: {p_value:.4f}") # Interpretation if p_value > class="num">0.05: print("The variances of the synthetic and real data are not significantly different.") else: print("The variances of the synthetic and real data are significantly different.")
把合成品种接进你的回测流
前面几节把 GAN 造数据、夏皮罗-威尔克和学生 t 检验的对标方法都铺开了,落到实盘前只剩一件事:把生成的 EURUSD 合成品种真正挂进 MT5 的回测环境。附带的 EURUSD_Synthetic_Symbol.mq5 直接编译进本地符号库,就能在策略测试器里用 3.02 KB 的轻量脚本替代稀缺的真实样本。 验证环节别偷懒——原文用夏皮罗-威尔克确认分布正态倾向、用学生 t 检验卡住均值偏移,这两道关过了,合成集才具备压力测试资格。外汇与贵金属本身高杠杆、高风险,合成数据只是降低过拟合概率,不替你挡黑天鹅。 开 MT5 加载那个 mq5,跑一轮多市场态回测,你会比只用存档数据的人更早嗅到优化陷阱。