原创指标,免费送,高准确率入场,下载的朋友点关注,后续发高质量指标源码。
源码如下:
//+------------------------------------------------------------------+
//| DeMarker_Arrow_Email.mq4
//| 主图箭头 + 邮件提示 + DeMarker条件触发
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Lime
#property indicator_color2 Red
#property indicator_width1 4
#property indicator_width2 4
//============================= 参数 =============================//
input int DeMarkerPeriod = 20; // DeMarker周期
input double UpperLevel = 0.7989; // 上阈值
input double LowerLevel = 0.2413; // 下阈值
input bool ClosedBarsOnly = true; // 仅已收盘K线出信号(推荐true)
input int ArrowGapPoints = 120; // 箭头离K线高低点距离(点)
input int BuyArrowCode = 233; // 向上箭头Wingdings代码
input int SellArrowCode = 234; // 向下箭头Wingdings代码
input bool EnableAlert = true; // 弹窗提醒
input bool EnableEmail = true; // 邮件提醒
input string EmailSubject = "DeMarker Signal";
//============================= 缓冲区 =============================//
double BuyBuffer[];
double SellBuffer[];
//============================= 工具函数 =============================//
string TFToString(int tf)
{
switch(tf)
{
case PERIOD_M1: return "M1";
case PERIOD_M5: return "M5";
case PERIOD_M15: return "M15";
case PERIOD_M30: return "M30";
case PERIOD_H1: return "H1";
case PERIOD_H4: return "H4";
case PERIOD_D1: return "D1";
case PERIOD_W1: return "W1";
case PERIOD_MN1: return "MN";
}
return "TF";
}
void SendSignalMessage(bool isBuy, datetime barTime, double demValue)
{
string sig = isBuy ? "BUY" : "SELL";
string msg = StringFormat("%s %s %s signal | Time: %s | DeMarker: %.5f",
Symbol(),
TFToString(Period()),
sig,
TimeToString(barTime, TIME_DATE|TIME_MINUTES),
demValue);
if(EnableAlert)
Alert(msg);
if(EnableEmail)
SendMail(EmailSubject, msg);
}
//============================= 初始化 =============================//
int OnInit()
{
IndicatorBuffers(2);
SetIndexBuffer(0, BuyBuffer);
SetIndexStyle(0, DRAW_ARROW, STYLE_SOLID, 4, clrLime);
SetIndexArrow(0, BuyArrowCode);
SetIndexLabel(0, "Buy Arrow");
SetIndexEmptyValue(0, EMPTY_VALUE);
SetIndexBuffer(1, SellBuffer);
SetIndexStyle(1, DRAW_ARROW, STYLE_SOLID, 4, clrRed);
SetIndexArrow(1, SellArrowCode);
SetIndexLabel(1, "Sell Arrow");
SetIndexEmptyValue(1, EMPTY_VALUE);
IndicatorShortName("DeMarker Arrow Email");
return(INIT_SUCCEEDED);
}
//============================= 主计算 =============================//
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
if(rates_total < DeMarkerPeriod + 5)
return 0;
ArrayInitialize(BuyBuffer, EMPTY_VALUE);
ArrayInitialize(SellBuffer, EMPTY_VALUE);
bool buyArmed = false; // 先下穿Lower后,等待再上穿Lower触发做多
bool sellArmed = false; // 先上穿Upper后,等待再下穿Upper触发做空
double gap = ArrowGapPoints * Point;
// 从最老K线向最新K线推进,保证“先穿越、再回穿”的状态逻辑正确
for(int i = rates_total - 2; i >= 0; i--)
{
double demPrev = iDeMarker(NULL, 0, DeMarkerPeriod, i + 1); // 更老一根
double demCurr = iDeMarker(NULL, 0, DeMarkerPeriod, i); // 当前这一根
if(demPrev == EMPTY_VALUE || demCurr == EMPTY_VALUE)
continue;
//==================== 做空逻辑 ====================//
// 第一步:先上穿 UpperLevel
if(demPrev <= UpperLevel && demCurr > UpperLevel)
{
sellArmed = true;
buyArmed = false;
}
// 第二步:再下穿 UpperLevel -> 做空箭头
if(sellArmed && demPrev >= UpperLevel && demCurr < UpperLevel)
{
SellBuffer = high + gap;
sellArmed = false;
}
//==================== 做多逻辑 ====================//
// 第一步:先下穿 LowerLevel
if(demPrev >= LowerLevel && demCurr < LowerLevel)
{
buyArmed = true;
sellArmed = false;
}
// 第二步:再上穿 LowerLevel -> 做多箭头
if(buyArmed && demPrev <= LowerLevel && demCurr > LowerLevel)
{
BuyBuffer = low - gap;
buyArmed = false;
}
}
//============================= 提醒逻辑 =============================//
int sigShift = ClosedBarsOnly ? 1 : 0;
static datetime lastBuyAlertBar = 0;
static datetime lastSellAlertBar = 0;
if(sigShift < rates_total)
{
double demNow = iDeMarker(NULL, 0, DeMarkerPeriod, sigShift);
if(BuyBuffer[sigShift] != EMPTY_VALUE && time[sigShift] != lastBuyAlertBar)
{
SendSignalMessage(true, time[sigShift], demNow);
lastBuyAlertBar = time[sigShift];
}
if(SellBuffer[sigShift] != EMPTY_VALUE && time[sigShift] != lastSellAlertBar)
{
SendSignalMessage(false, time[sigShift], demNow);
lastSellAlertBar = time[sigShift];
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
|