真实作者: Ramdass - 仅转换
SilverTrend 信号指示器为交易者提供了警报、邮件和推送通知功能,非常实用。
为实现这些功能,指示器代码进行了以下修改:
- 新增输入参数:
input uint Bar数量=1;//信号的柱数 input bool 声音开启=true; //启用警报 input uint 警报数量=2;//警报数量 input bool 邮件开启=false; //启用邮件发送信号 input bool 推送开启=false; //启用移动设备推送信号
- 在指示器代码末尾新增了三个函数:BuySignal()、SellSignal() 和 GetStringTimeframe()
//+------------------------------------------------------------------+ //| 买入信号函数 | //+------------------------------------------------------------------+ void BuySignal(string 信号名称, //用于邮件和推送消息的指示器名称文本 double &买入箭头[], //存储买入信号的指示器缓冲区 const int 总柱数, //当前柱数 const int 上一计算, //上一个刻度的柱数 const double &收盘价[], //收盘价 const int &点差[]) //点差 { //--- static uint 计数器=0; if(总柱数!=上一计算) 计数器=0; bool 买入信号=false; bool 数组测试=ArrayGetAsSeries(买入箭头); int 索引; if(数组测试) 索引=int(Bar数量); else 索引=总柱数-int(Bar数量)-1; if(NormalizeDouble(买入箭头[索引],_Digits) && 买入箭头[索引]!=EMPTY_VALUE) 买入信号=true; if(买入信号 && 计数器<=警报数量) { 计数器++; MqlDateTime tm; TimeToStruct(TimeCurrent(),tm); string 文本=TimeToString(TimeCurrent(),TIME_DATE)+" "+string(tm.hour)+":"+string(tm.min); 数组测试=ArrayGetAsSeries(收盘价); if(数组测试) 索引=int(Bar数量); else 索引=总柱数-int(Bar数量)-1; double 卖盘=收盘价[索引]; double 买盘=收盘价[索引]; 数组测试=ArrayGetAsSeries(点差); if(数组测试) 索引=int(Bar数量); else 索引=总柱数-int(Bar数量)-1; 买盘+=点差[索引]; string s卖盘=DoubleToString(卖盘,_Digits); string s买盘=DoubleToString(买盘,_Digits); string s周期=GetStringTimeframe(ChartPeriod()); if(声音开启) Alert("买入信号 卖盘=",卖盘," 买盘=",买盘," 当前时间=",文本," 符号=",Symbol()," 周期=",s周期); if(邮件开启) SendMail(信号名称+": 买入信号警报","买入信号在 卖盘="+s卖盘+", 买盘="+s买盘+", 日期="+文本+" 符号="+Symbol()+" 周期="+s周期); if(推送开启) SendNotification(信号名称+": 买入信号在 卖盘="+s卖盘+", 买盘="+s买盘+", 日期="+文本+" 符号="+Symbol()+" 周期="+s周期); } //--- } //+------------------------------------------------------------------+ //| 卖出信号函数 | //+------------------------------------------------------------------+ void SellSignal(string 信号名称, //用于邮件和推送消息的指示器名称文本 double &卖出箭头[], //存储卖出信号的指示器缓冲区 const int 总柱数, //当前柱数 const int 上一计算, //上一个刻度的柱数 const double &收盘价[], //收盘价 const int &点差[]) //点差 { //--- static uint 计数器=0; if(总柱数!=上一计算) 计数器=0; bool 卖出信号=false; bool 数组测试=ArrayGetAsSeries(卖出箭头); int 索引; if(数组测试) 索引=int(Bar数量); else 索引=总柱数-int(Bar数量)-1; if(NormalizeDouble(卖出箭头[索引],_Digits) && 卖出箭头[索引]!=EMPTY_VALUE) 卖出信号=true; if(卖出信号 && 计数器<=警报数量) { 计数器++; MqlDateTime tm; TimeToStruct(TimeCurrent(),tm); string 文本=TimeToString(TimeCurrent(),TIME_DATE)+" "+string(tm.hour)+":"+string(tm.min); 数组测试=ArrayGetAsSeries(收盘价); if(数组测试) 索引=int(Bar数量); else 索引=总柱数-int(Bar数量)-1; double 卖盘=收盘价[索引]; double 买盘=收盘价[索引]; 数组测试=ArrayGetAsSeries(点差); if(数组测试) 索引=int(Bar数量); else 索引=总柱数-int(Bar数量)-1; 买盘+=点差[索引]; string s卖盘=DoubleToString(卖盘,_Digits); string s买盘=DoubleToString(买盘,_Digits); string s周期=GetStringTimeframe(ChartPeriod()); if(声音开启) Alert("卖出信号 卖盘=",卖盘," 买盘=",买盘," 当前时间=",文本," 符号=",Symbol()," 周期=",s周期); if(邮件开启) SendMail(信号名称+": 卖出信号警报","卖出信号在 卖盘="+s卖盘+", 买盘="+s买盘+", 日期="+文本+" 符号="+Symbol()+" 周期="+s周期); if(推送开启) SendNotification(信号名称+": 卖出信号在 卖盘="+s卖盘+", 买盘="+s买盘+", 日期="+文本+" 符号="+Symbol()+" 周期="+s周期); } //--- } //+------------------------------------------------------------------+ //| 获取时间框架字符串 | //+------------------------------------------------------------------+ string GetStringTimeframe(ENUM_TIMEFRAMES 时间框架) { //---- return(StringSubstr(EnumToString(时间框架),7,-1)); //---- }
- 在 OnCalculate() 块的指示器计算循环后新增了 BuySignal() 和 SellSignal() 函数的调用 //---
BuySignal("SilverTrend_Signal_Alert",买入缓冲区,总柱数,上一计算,收盘价,点差);
SellSignal("SilverTrend_Signal_Alert",卖出缓冲区,总柱数,上一计算,收盘价,点差);
//---
其中,买入缓冲区和卖出缓冲区是存储买入和卖出信号的指示器缓冲区。指示器缓冲区中的空值应设置为零或 EMPTY_VALUE。
预计在指示器代码的 OnCalculate() 块中只会调用一次 BuySignal() 和 SellSignal() 函数。

图1. SilverTrend_Signal_Alert 指标在图表上

图2. SilverTrend_Signal_Alert 指标. 生成警报