我对编写mql4
代码很陌生,如果在发生以下烛台模式时能获得一些绘制矩形的帮助,将不胜感激。
图1:
运行代码段
<blockquote class="imgur-embed-pub" lang="en" data-id="a/fRoPzsm"><a href="//imgur.com/a/fRoPzsm">Demand Zone 1</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
图2:
运行代码段
<blockquote class="imgur-embed-pub" lang="en" data-id="a/4E8KE1R" data-context="false"><a href="//imgur.com/a/4E8KE1R">Demand Zone 2</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
和
图3:
运行代码段
<blockquote class="imgur-embed-pub" lang="en" data-id="a/h6D6o6R"><a href="//imgur.com/a/h6D6o6R">Hidden Demand Zone</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
和相应的供应区
并以指定的点数止损和止盈开立挂单。
请原谅我不直接包含图片。我没有足够的赞成票。
以下是链接图像中烛台图案的说明:
一般candlestick pattern
(需求区)发生在至少两个或多个连续的看涨蜡烛(最后一个看涨蜡烛的高点是该时间段的高点)之后,接着是一个或多个看跌蜡烛,其高点和低点低于最后一个看涨蜡烛。然后最后是形成新高的看涨蜡烛。需求区域的矩形区域是从最后一个看跌蜡烛的开盘价到最低价。
当一系列连续的看涨蜡烛的蜡烛的低位,低于前一根蜡烛,其高位的蜡烛线与收盘价重合时,则隐藏需求区域将从看涨蜡烛的低位变为开盘价。
>here可以对需求区和供应区进行完整说明。
我知道bullish
和bearish
蜡烛可以由
if ( ( Open[1] - Close[1] ) > 0)
{
// candle is bearish
}
else
{
// candle is bullish
}
我非常感谢您的帮助。
答案 0 :(得分:1)
似乎这些模式没有完整描述,因此无法正确编码。好的,让我们尝试模式1。
用于图案的条件(从图片看似合理):
1.检查新栏的开始(bar#0)。
2.小节1(如果我们将0计算为当前值,则为MQL4中的小节#3)必须看涨。
3.第2条(第2条)看跌。 (如果是模式#2,则为N条,N可以为2或更大)
4.第3条(MT4中的第1条)看涨。
5.其最高价=收盘价。
6.其最高价>最高价#3。
enum EnmDir
{
LONG = 1,
SHORT=-1,
NONE = 0,
};
int getCandleDirection(const int shift)
{
const double open=iOpen(_Symbol,0,shift), close=iClose(_Symbol,0,shift);
if(close-open>_Point/2.)
return LONG; //bullish
if(open-close>_Point/2.)
return SHORT; //bearish
return NONE; //doji
}
bool isPattern1Detected(const EnmDir dir)
{
if(dir==0)return(false);
if(getCandleDirection(3)!=dir)
return false; //rule#2
if(getCandleDirection(2)+dir!=0)
return false; //rule#3
if(getCandleDirection(1)!=dir)
return false; //rule#4
if(dir>0)
{
if(iHigh(_Symbol,0,1)-iClose(_Symbol,0,1)>_Point/2.)
return false; //rule#5 for long
if(iHigh(_Symbol,0,1)-iHigh(_Symbol,0,3)>_Point/2.)
return true; //rule#6 for long
return false; //if rule#6 is not hold
}
else
{
if(iClose(_Symbol,0,1)-iLow(_Symbol,0,1)>_Point/2.)
return false; //rule#5 for short
if(iLow(_Symbol,0,3)-iLow(_Symbol,0,1)>_Point/2.)
return true; //rule#6 for short
return false; //if rule#6 is not hold
}
}
bool isPattern2Detected(const EnmDir dir,const int numCandlesAgainst=1)
{
if(dir==NONE)return(false);
if(getCandleDirection(1)!=dir)
return false; //rule#4
for(int i=1;i<=numCandlesAgainst;i++)
{
if(getCandleDirection(1+i)!=dir)
return(false); //rule#3 - checking that all numCandlesAgainst must be bearish
}
if(getCandleDirection(2+numCandlesAgainst)!=dir)
return false; //rule#2
if(dir>0)
{
if(iHigh(_Symbol,0,1)-iClose(_Symbol,0,1)>_Point/2.)
return false; //rule#5 for long
if(iHigh(_Symbol,0,1)-iHigh(_Symbol,0,2+numCandlesAgainst)>_Point/2.)
return true; //rule#6 for long
return false; //if rule#6 is not hold
}
else
{
if(iClose(_Symbol,0,1)-iLow(_Symbol,0,1)>_Point/2.)
return false; //rule#5 for short
if(iLow(_Symbol,0,2+numCandlesAgainst)-iLow(_Symbol,0,1)>_Point/2.)
return true; //rule#6 for short
return false; //if rule#6 is not hold
}
}
您还需要什么?要检测矩形的HL?这很简单,规则很明确。让我们假设它们是:对于LONG,向上=条形#2的打开,向下=该条形的低。然后,
void detectRangeOfZone(double &top,double &bottom,const EnmDir dir)
{
if(dir>0)
{
top=iOpen(_Symbol,0,2);
bottom=iLow(_Symbol,0,2);
}
else if(dir<0)
{
top=iClose(_Symbol,0,2);
bottom=iHigh(_Symbol,0,2);
}
}
您需要绘制一个矩形吗?好的,但是您将如何决定何时停止绘制?让我们假设右边的N条就足够了,现在让我们忽略周末(如果要记住市场休市时的周末会稍微复杂一些)。
bool drawRectangle(const int dir,const double top,const double bottom)
{
const datetime starts=iTime(_Symbol,0,2), ends=starts+PeriodSeconds()*N_bars;//time of start and end of the rectangle
const string name=prefix+"_"+(dir>0?"DEMAND":"SUPPLY")+"_"+TimeToString(starts);//name would be unique sinse we use time of start of the range. DO NOT FORGET about prefix - it should be declared globally, you would be able to delete all the objects with 'ObjectsDeleteAll()' function that accepts prefix in one of its implementations.
if(!ObjectCreate(0,name,OBJ_RECTANGLE,0,0,0,0,0))
{
printf("%i %s: failed to create %s. error=%d",__LINE__,__FILE__,name,_LastError);
return false;
}
ObjectSetInteger(0,name,OBJPROP_TIME1,starts);
ObjectSetInteger(0,name,OBJPROP_TIME2,ends);
ObjectSetDouble(0,name,OBJPROP_PRICE1,top);
ObjectSetDouble(0,name,OBJPROP_PRICE2,bottom);
//add color, width, filling color, access modifiers etc, example is here https://docs.mql4.com/ru/constants/objectconstants/enum_object/obj_rectangle
return true;
}
这是主要块,请不要忘记添加新的条形检查,否则该工具将在每个刻度上检查对象,这是浪费时间。 字符串前缀=“”; //为您的所有对象添加一些唯一的前缀 const int N_bars = 15; //在此示例中为15个小节
void OnDeinit(const int reason){ObjectsDeleteAll(0,prefix);}
void OnTick()
{
if(!isNewBar())
return; //not necessary but waste of time to check every second
const bool pattern1Up=isPattern1Detected(1), pattern1Dn=isPattern1Detected(-1);
if(pattern1Up)
{
double top,bottom;
detectRangeOfZone(top,bottom,1);
drawRectangle(1,top,bottom);
PlacePendingOrder(1,top,bottom);
}
if(pattern1Dn)
{
double top,bottom;
detectRangeOfZone(top,bottom,-1);
drawRectangle(-1,top,bottom);
PlacePendingOrder(-1,top,bottom);
}
}
int PlacePendingOrder(const EnmDir dir,const double oop,const double suggestedSl)
{
const double lot=0.10; //FOR EXAMPLE, PUT YOUR DATA HERE
const string comment="example for SOF";
const int magicNumber=123456789;
int cmd=dir>0 ? OP_BUY : OP_SELL;
double price=(dir>0 ? Ask : Bid), spread=(Ask-Bid);
if(dir*(oop-price)>spread)
cmd+=(OP_BUYSTOP-OP_BUY);
else if(dir*(price-oop)>spread)
cmd+=(OP_BUYLIMIT-OP_BUY);
int attempt=0, ATTEMPTS=5, SLEEP=25, SLIPPAGE=10, result=-1, error=-1;
while(attempt<ATTEMPTS)
{
attempt++;
RefreshRates();
if(cmd<=OP_SELL)
{
price=dir>0 ? Ask : Bid;
result=OrderSend(_Symbol,cmd,lot,price,SLIPPAGE,0,0,comment,magicNumber);
}
else
{
result=OrderSend(_Symbol,cmd,lot,oop,SLIPPAGE,0,0,comment,magicNumber);
}
if(result>0)
break;
error=_LastError;
Sleep(SLEEP);
}
if(result>0)
{
if(OrderSelect(result,SELECT_BY_TICKET))
{
price=OrderOpenPrice();
if(!OrderModify(result,price,suggestedSl,0,OrderExpiration()))
printf("%i %s: failed to modify %d. error=%d",__LINE__,__FILE__,result,_LastError);
//tp is zero, sl is suggested SL, put yours when needed
}
return result;
}
printf("%i %s: failed to place %s at %.5f. error=%d",__LINE__,__FILE__,EnumToString((ENUM_ORDER_TYPE)cmd),(cmd>OP_SELL ? oop : price),error);
return -1;
}
答案 1 :(得分:1)
我来晚了:'(工作使我无法进入StackOverflow:'(无论如何,根据赏金计划,我将无法提供完整的程序,也无法提供完整的代码来解决此需求区问题。
但是,我仍然想为每个人提供一些“起点”,以便他们在MT4(MQL4)上构建自己的模式识别器。
为了简短起见,我录制了一段YouTube视频对其进行描述。 https://youtu.be/WSiyY52QyBI
无论如何,这里是代码:
\S+ (/(?:[^/\s]+/)*[^\s"]+)
更重要的是 clsBar.mqh 。请注意,这是一个“包含文件”,应位于包含文件夹中。包含文件有助于我们减少程序的混乱度,并有助于我们编写可重用的代码。编写OOP类时非常有用。
clsBar.mqh:下载(OneDrive)https://1drv.ms/u/s!AoLFy6fRYNsvjTU-xSzAADCwGjPQ
不幸的是,该文件太大,无法包含在此帖子中。因此,我必须将其上传到OneDrive。