本文会讲述如何生成一份 HTML 文件格式的交易结果报告(利用“EA 交易”、指标或脚本),并通过 FTP 将其上传到 WWW 服务器。赫兹量化还会考虑以短消息形式向手机发送交易事件通知。
想要更自如地阅读本文内容,建议读者熟悉 HTML (超文本标记语言)知识。
要实施报告上传,赫兹量化需要一个可以通过 FTP 接受数据的 WWW 服务器(可以是任何计算机)。而要实现接收短消息形式的交易事件通知,我们需要一个电子邮箱 - 短消息的网关(大多数移动运营商和第三方组织都提供该服务)。
(相关资料图)
我们来创建一个 MQL5 程序,并利用它来生成一份交易报告,再将报告通过 FTP 协议发送出去。首先,赫兹量化将其制作为脚本。将来我们能用它作为一个成品块,插入到“EA 交易”和指标中。比如说,在“EA 交易”中,您可以将此程序块作为 Trade 或 Timer 事件处理程序,于交易请求后运行此块,或是为 ChartEvent 事件设定一些动作。而在指标中,您则可以将此块加入到 Timer 或 ChartEvent 事件处理程序中。
程序创建的报告示例,如图 1、2、3 所示。或者,您也可以通过本文末尾处的链接下载该报告。
图 1. 报告示例 - 交易与仓位表
图 2. 报告示例 - 平衡图
图 3. 报告示例 - 当前工具的价格图表
交易与仓位表(图 1)中,为方便起见,所有交易都被划分成仓位。该表的左侧,会显示进入市场(持仓和添加)的交易量、时间和价格。表右侧显示的则是退出市场(部分或完全平仓)的上述参数。根据 in/out (买入/卖出),交易为分两个部分 - 一个平仓,下一个开仓。
交易与仓位表的下方是平衡图表(横轴 - 时间),而其底部则是当前工具价格图表。
该程序会在 MetaTarder5_istall_dir\MQL5\Files 文件夹中创建 ""、"" 和 "" 文件(html 格式报告文件、平衡图表与价格图表的图像文件)。而且终端设置中的 FTP 发布已启用 - 它会向指定服务器发送上述三种文件。此外,赫兹量化还需要两种文件 - 带有指向持仓方向箭头的图像 - 买入或卖出("" 与 "")。您可以采用这些图像(下载链接在文末),也可以利用任何图形编辑器自行绘制。而这两个文件也要放到 WWW 服务器中与 "" 文件相同的文件夹。
作为输入参数,该程序接受报告生成周期的开始与结束时间。本例中,报告周期的结束为当前时间,用户选择报告周期的变体:整个周期、昨天、上周、上月或去年。
简单说说我们创建报告的方式。所有可用的交易历史都会请求交易服务器。获取到的成交会被一个接一个地处理。deal_status[] 数组会存储交易是否被处理的相关信息。该数组的元素索引,就是从交易服务器交易列表中接收到的交易编号。而元素的值则如下阐释:0 - 交易尚未处理,1 - 交易已被部分处理 (in/out),127 - 交易处理完毕(其它值未被使用,留作后用)。
symb_list[] 数组包含交易得以执行的金融工具名称的列表,而 lots_list[] 数组则包含交易处理时每个工具的开仓交易量。交易量正值对应的是买入持仓,而负值则对应着卖出持仓。如果交易量等于零,则意味着该工具没有敞口仓位。如果交易处理期间出现了未于列表中(symb_list[] 数组中)出现的金融工具 - 则将其添加到那里,且金融工具的编号(symb_total 变量)以 1 为增量增长。
根据每个交易处理过程,每一个后续交易都利用相同的金融工具进行分析,直到平仓或买入/卖出。只有 deal_status[] 数组值小于 127 的那些交易会被分析。交易处理之后,对应的 deal_status[] 数组元素即被赋值为 127,如果交易为仓位 in/out,则赋值 1。如果开仓时间匹配报告周期(由 StartTime 和 EndTime 变量定义) - 则此仓位被记录到报告中(所有的输入和输出)。
除交易表外,还有一个新的当前金融工具图表被打开。此图表的所有必要属性均已提供,并用 ChartScreenShot() 函数做了一个屏幕截图 - 这样我们就能获取带有当前工具价格图表的图像文件了。接下来,此图表上的价格图表会被隐藏,余额变动图表会被绘制,然后再创建另一个屏幕截图。
两个带有图表的图像文件和带有报告的 HTML 文件创建之后,通过 FTP 发送文件的功能即被勾选。如果允许 - 则会根据赫兹量化中指定的设置,利用 SendFTP() 函数发送 ""、"" 和 "" 文件。
启动 MetaQuotes Language Editor (语言编辑器),开始创建一个脚本。定义常量 - 图表刷新超时(以秒计)、价格图表的宽度和高度以及平衡图表的最大宽度。显示余额变动曲线的图表周期,根据报告周期的期限和图表的最大宽度进行选择。图表的宽度调整为平衡图所需的尺寸。
图表的高度自动计算为宽度的一半。赫兹量化还要将纵轴的宽度指定为常量 - 即图形面积相比图像宽度因纵轴而缩减的像素数。
#define timeout 10 // 图表刷新时间#define Picture1_width 800 // 报告中图表最大宽度#define Picture2_width 800 // 报告中价格图表宽度#define Picture2_height 600 // 报告中价格图表高度#define Axis_Width 59 // 纵轴宽度 (以像素为单位)
指定将从用户请求的输入参数。
// 请求输入参数#property script_show_inputs
创建报告周期的枚举。
// 报告周期的枚举enum report_periods { All_periods, Last_day, Last_week, Last_month, Last_year };
就报告周期询问用户(默认为整个周期)。
// 询问报告周期input report_periods ReportPeriod=0;
编写 OnStart() 函数的主体。
void OnStart() {
确定报告周期的开头和结尾。
datetime StartTime=0; // 报告周期起始时间 datetime EndTime=TimeCurrent(); // 报告周期结束时间 // 计算报告周期起始时间 switch(ReportPeriod) { case 1: StartTime=EndTime-86400; // 日 break; case 2: StartTime=EndTime-604800; // 周 break; case 3: StartTime=EndTime-2592000; // 月 break; case 4: StartTime=EndTime-31536000; // 年 break; } // 如果不是以上的选项, 那么 StartTime=0 (整个周期)
声明将在本程序内使用的变量。变量的用途描述见评论。
int total_deals_number; // 历史数据中的交易总数 int file_handle; // 文件句柄 int i,j; // 循环计数器 int symb_total; // 交易中的资产数量 int symb_pointer; // 当前资产的指针 char deal_status[]; // 交易状态 (处理/未处理) ulong ticket; // 交易订单号 long hChart; // 图表 id double balance; // 当前余额值 double balance_prev; // 之前余额值 double lot_current; // 当前交易交易量 double lots_list[]; // 根据资产种类的开放交易量列表 double current_swap; // 当前交易的库存费 double current_profit; // 当前交易的利润 double max_val,min_val; // 最大值和最小值 string symb_list[]; // 交易的资产种类列表 string in_table_volume; // 建仓交易量 string in_table_time; // 进场时间 string in_table_price; // 进场价格 string out_table_volume; // 出场交易量 string out_table_time; // 出场时间 string out_table_price; // 出场价格 string out_table_swap; // 出场库存费 string out_table_profit; // 出场利润 bool symb_flag; // 资产在列表中的标志 datetime time_prev; // 前面的时间值 datetime time_curr; // 当前时间值 datetime position_StartTime; // 建仓时间 datetime position_EndTime; // 最后一个退场时间 ENUM_TIMEFRAMES Picture1_period; // 余额图表时段
打开一个新图表并设置其属性 - 这是一个价格图表,会在报告底部输出。
// 开启一个新图表并设置其属性hChart=ChartOpen(Symbol(),0);ChartSetInteger(hChart,CHART_MODE,CHART_BARS); // 柱状图ChartSetInteger(hChart,CHART_AUTOSCROLL,true); // 启用自动滚动ChartSetInteger(hChart,CHART_COLOR_BACKGROUND,White); // 背景色为白色ChartSetInteger(hChart,CHART_COLOR_FOREGROUND,Black); // 线和标签为黑色ChartSetInteger(hChart,CHART_SHOW_OHLC,false); // 不显示OHLCChartSetInteger(hChart,CHART_SHOW_BID_LINE,true); // 显示 BID 线ChartSetInteger(hChart,CHART_SHOW_ASK_LINE,false); // 隐藏 ASK 线ChartSetInteger(hChart,CHART_SHOW_LAST_LINE,false); // 隐藏 LAST 线ChartSetInteger(hChart,CHART_SHOW_GRID,true); // 显示网格线ChartSetInteger(hChart,CHART_SHOW_PERIOD_SEP,true); // 显示时段分隔符ChartSetInteger(hChart,CHART_COLOR_GRID,LightGray); // 网格线为浅灰色ChartSetInteger(hChart,CHART_COLOR_CHART_LINE,Black); // 图表线为黑色ChartSetInteger(hChart,CHART_COLOR_CHART_UP,Black); // 向上的柱为黑色ChartSetInteger(hChart,CHART_COLOR_CHART_DOWN,Black); // 向下的柱为黑色ChartSetInteger(hChart,CHART_COLOR_BID,Gray); // BID 线为灰色ChartSetInteger(hChart,CHART_COLOR_VOLUME,Green); // 交易量和订单水平为绿色ChartSetInteger(hChart,CHART_COLOR_STOP_LEVEL,Red); // SL 和 TP 水平为红色ChartSetString(hChart,CHART_COMMENT,ChartSymbol(hChart)); // 注释包含资产种类
图表截屏,并将其保存为 ""。
// 把图表保存为图像文件ChartScreenShot(hChart,"",Picture2_width,Picture2_height);
请求现有账户整个时间段的交易历史。
// 请求整个时段的交易历史HistorySelect(0,TimeCurrent());
打开 "" 文件,并在其中写入带有报告的 HTML 页面(ANSI 编码)。
// 打开图表文件file_handle=FileOpen("",FILE_WRITE|FILE_ANSI);
编写 HTML 文档的开头部分:
html 文档的开头 (<html>)
显示于您浏览器窗口顶部的标题 (<head><title>“EA 交易报告”</title></head>)
带有背景色的 html 文档主体部分的开头 (<body bgcolor='#EFEFEF'>)
居中对齐 (<center>)
交易与仓位表的标题 (<h2>交易报告</h2>)
交易与仓位表的开头,带有对齐、边框宽度、背景颜色、边框颜色、单元格间距及单元格填充 (<table align='center' border='1' bgcolor='#FFFFFF' bordercolor='#7F7FFF' cellspacing='0' cellpadding='0'>)
表标题
// 写 HTML 开头部分 FileWrite(file_handle,"<html>"+ "<head>"+ "<title>Expert Trade Report</title>"+ "</head>"+ "<body bgcolor='#EFEFEF'>"+ "<center>"+ "<h2>Trade Report</h2>"+ "<table align='center' border='1' bgcolor='#FFFFFF' bordercolor='#7F7FFF' cellspacing='0' cellpadding='0'>"+ "<tr>"+ "<th rowspan=2>SYMBOL</th>"+ "<th rowspan=2>Direction</th>"+ "<th colspan=3>Open</th>"+ "<th colspan=3>Close</th>"+ "<th rowspan=2>Swap</th>"+ "<th rowspan=2>Profit</th>"+ "</tr>"+ "<tr>"+ "<th>Volume</th>"+ "<th>Time</th>"+ "<th>Price</th>"+ "<th>Volume</th>"+ "<th>Time</th>"+ "<th>Price</th>"+ "</tr>");
获取列表中的交易数量。