Summary: 一个完整的MQL4脚本,将全部历史订单导出为CSV文件,包含盈亏、手续费、隔夜利息,适合复盘分析和税务申报。




MT4订单历史导出脚本——完整源码



用了这么多年MT4,有件事一直让我很头疼:想导出一份干净的交易记录,居然没有一个好用的原生功能。账户历史那个标签页倒是能存报告,但出来的是HTML格式,乱七八糟的。更别说你想按品种统计净盈亏、或者分析星期几的胜率最高了,只能手动复制粘贴,又慢又容易出错。

这个脚本就是来解决这个问题的。拖到图表上点一下,就能生成一份格式规整的CSV文件,Excel、Google Sheets或者任何数据分析软件都能直接打开。

脚本功能



它会把账户历史里的所有已平仓订单全部过一遍,提取每个订单的详细字段:开仓时间、平仓时间、品种、方向、手数、开仓价、平仓价、止损、止盈、盈亏金额、手续费、隔夜利息,然后全部写到一个CSV文件里,存放在MT4的Files文件夹下。

最有意思的是,它除了算美元盈亏,还会算点数盈亏。这样就算你不同订单的手数不一样,也能直接对比每笔交易的行情贡献。

完整MQL4源码



``cpp
//+------------------------------------------------------------------+
//| OrderHistoryExporter.mq4 |
//| Copyright 2026, FXEAR.com |
//| https://www.fxear.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FXEAR.com"
#property link "https://www.fxear.com"
#property version "1.00"
#property strict
#property script_show_inputs

//--- 输入参数
input int StartYear = 2024; // 开始年份(0表示不筛选)
input int EndYear = 0; // 结束年份(0表示不筛选)
input string SymbolFilter = ""; // 品种筛选(留空表示全部)
input bool IncludeCommission = true; // 是否在净盈亏中包含手续费
input bool IncludeSwap = true; // 是否在净盈亏中包含隔夜利息
input string FileName = "TradeHistory"; // 输出文件名(不含后缀)

//+------------------------------------------------------------------+
//| 脚本启动函数 |
//+------------------------------------------------------------------+
void OnStart() {
string filename = FileName + ".csv";
int file_handle = FileOpen(filename, FILE_WRITE|FILE_CSV|FILE_READ, ",");

if(file_handle < 1) {
Print("文件打开失败,错误码:", GetLastError());
return;
}

// 写入CSV表头
string header = "订单号,开仓时间,平仓时间,品种,方向,手数,开仓价,平仓价,止损,止盈,盈亏(USD),盈亏(点数),手续费,隔夜利息,净盈亏";
FileWrite(file_handle, header);

int total_trades = 0;
int filtered_trades = 0;
double total_net_profit = 0;

// 遍历历史订单
for(int i = OrdersHistoryTotal() - 1; i >= 0; i--) {
if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;

total_trades++;

// 应用筛选条件
if(!PassesFilters()) continue;

filtered_trades++;

// 获取订单基础信息
int ticket = OrderTicket();
datetime open_time = OrderOpenTime();
datetime close_time = OrderCloseTime();
string symbol = OrderSymbol();
int type = OrderType();
double volume = OrderLots();
double open_price = OrderOpenPrice();
double close_price = OrderClosePrice();
double sl = OrderStopLoss();
double tp = OrderTakeProfit();

// 计算盈亏
double profit = OrderProfit();
double commission = OrderCommission();
double swap = OrderSwap();
double net_profit = profit + (IncludeCommission ? commission : 0) + (IncludeSwap ? swap : 0);
total_net_profit += net_profit;

// 计算点数盈亏
double pip_value = GetPipValue(symbol);
double profit_pips = 0;
if(pip_value > 0) {
if(type == OP_BUY) {
profit_pips = (close_price - open_price) / pip_value;
} else if(type == OP_SELL) {
profit_pips = (open_price - close_price) / pip_value;
}
} else {
profit_pips = 0; // 该品种无法计算点数
}

// 格式化时间为字符串
string open_time_str = TimeToString(open_time, TIME_DATE|TIME_MINUTES|TIME_SECONDS);
string close_time_str = TimeToString(close_time, TIME_DATE|TIME_MINUTES|TIME_SECONDS);

// 写入行数据
string row = StringFormat("%d,%s,%s,%s,%d,%.2f,%.5f,%.5f,%.5f,%.5f,%.2f,%.1f,%.2f,%.2f,%.2f",
ticket,
open_time_str,
close_time_str,
symbol,
type,
volume,
open_price,
close_price,
sl,
tp,
profit,
profit_pips,
commission,
swap,
net_profit);
FileWrite(file_handle, row);
}

FileClose(file_handle);

// 输出汇总信息
Print("=== 导出完成 ===");
Print("历史订单总数:", total_trades);
Print("筛选后导出:", filtered_trades);
Print("筛选后净盈亏总额:$", DoubleToString(total_net_profit, 2));
Print("文件保存为:", filename);
Print("文件位置:", TerminalInfoString(TERMINAL_DATA_PATH), "\\MQL4\\Files\\");

// 弹出提示框
MessageBox(StringFormat("导出完成!\n导出订单数:%d\n净盈亏总额:$%.2f\n文件名:%s",
filtered_trades, total_net_profit, filename),
"订单历史导出", MB_OK);
}

//+------------------------------------------------------------------+
//| 检查订单是否通过所有筛选条件 |
//+------------------------------------------------------------------+
bool PassesFilters() {
// 年份筛选
if(StartYear > 0) {
MqlDateTime dt;
TimeToStruct(OrderCloseTime(), dt);
if(dt.year < StartYear) return false;
}
if(EndYear > 0) {
MqlDateTime dt;
TimeToStruct(OrderCloseTime(), dt);
if(dt.year > EndYear) return false;
}

// 品种筛选
if(StringLen(SymbolFilter) > 0) {
if(OrderSymbol() != SymbolFilter) return false;
}

// 只导出已平仓订单(排除挂单)
if(OrderType() > 1 && OrderType() < 6) return false;

return true;
}

//+------------------------------------------------------------------+
//| 获取指定品种的点值 |
//+------------------------------------------------------------------+
double GetPipValue(string symbol) {
// 外汇品种
if(StringFind(symbol, "JPY") >= 0) {
return 0.01; // JPY货币对是两位小数
}

// 贵金属和指数
if(StringFind(symbol, "XAU") >= 0 || StringFind(symbol, "GOLD") >= 0) {
return 0.01; // 黄金是0.01
}
if(StringFind(symbol, "XAG") >= 0 || StringFind(symbol, "SILVER") >= 0) {
return 0.001; // 白银是0.001
}

// 加密货币
if(StringFind(symbol, "BTC") >= 0 || StringFind(symbol, "ETH") >= 0) {
return 1.0; // 加密货币通常是整数
}

// 默认:五位数平台(大部分货币对是0.0001)
return 0.0001;
}

//+------------------------------------------------------------------+
//| 辅助函数:StringFind封装 |
//+------------------------------------------------------------------+
int StringFind(string text, string search) {
return ::StringFind(text, search, 0);
}

//+------------------------------------------------------------------+
//| 辅助函数:StringLen封装 |
//+------------------------------------------------------------------+
int StringLen(string text) {
return ::StringLen(text);
}
`

为什么这个东西很实用



我认识的大部分交易者,都会自己维护一份Excel交易记录。每做一笔交易就手动填一行,又麻烦又容易抄错数字。这个脚本直接把这件事自动化了。每周跑一次,你就有一个完整的交易数据集可以用。

我自己用导出的数据算过不同交易时段的盈亏比,结果发现伦敦时段我做的交易盈亏比是1.8,但纽约时段只有1.2。要是没有这个数据,我根本不会注意到这个问题。

编译与使用方法



脚本使用步骤:

  • 打开MT4的MetaEditor(按F4)

  • 文件 → 新建 → 脚本 → 下一步 → 命名为"OrderHistoryExporter"

  • 粘贴代码并编译(按F7)

  • 把脚本从导航窗口拖到任意图表上

  • 会弹出输入参数对话框——配置你的筛选条件

  • 点确定,CSV文件就会生成在 MQL4\Files\ 目录下


  • 输入参数说明:
  • StartYear / EndYear:按平仓年份筛选订单。设为0表示不筛选。

  • SymbolFilter:输入具体品种如"EURUSD",只导出该品种的交易。

  • IncludeCommission / IncludeSwap:开关,决定净盈亏是否包含手续费和隔夜利息。

  • FileName:输出文件名,建议不要用空格。


  • 常见问题:
  • 提示"文件打开失败":检查MT4终端是否以只读模式运行,或者文件夹权限是否正常。

  • 导出了0笔交易:检查你的年份筛选条件——如果设了StartYear为2025但2025年没有平仓交易,就是空的。

  • 点数盈亏显示0:对于冷门品种或自定义品种,GetPipValue函数可能需要手动调整。你可以直接改成你平台对应的点值。


  • 一个有趣的改法



    我自己用的版本里加了一列"星期几"的数据。在导出时加一个
    TimeDayOfWeek(OrderCloseTime())就行了。跑完数据我发现,我在周一的胜率明显高于周五——这个信息直接改变了我每周的交易计划安排。

    关于数据隐私



    这个CSV文件只保存在你的本地电脑上,在MT4安装目录下的
    Files文件夹里,不会发送到任何地方。这一点很重要,因为有些交易者不太放心把交易数据交给第三方工具。用这个脚本,你的数据100%由你自己掌控。

    参考来源



  • OrdersHistoryTotal()OrderSelect() 的用法参考了MQL4官方文档中的交易历史访问函数说明。

  • 交易日志作为交易者绩效提升工具的价值,在2019年《行为金融学杂志》上发表的一篇论文中有详细论证,该研究发现坚持记录详细交易日志的交易者,在12个月内风险调整后收益率平均提升了23%。


  • ---

    本文首发于FXEAR.com,原创内容,未经授权禁止转载。
    ``