似乎这些模式没有完全描述清楚,因此无法正确编码。好的,让我们尝试使用模式#1。
用于模式(从图片中看起来合理的条件):
1. 在新的柱子(bar#0)开始时检查。
2. 柱子1(如果我们将0计算为当前值,则为MQL4中的bar#3)必须是看涨的。
3. 柱子2(bar#2)是看跌的。(或者在模式#2的情况下是N个柱子,N可以是2个或更多)
4. 柱子3(MT4中的bar#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;
if(open-close>_Point/2.)
return SHORT;
return NONE;
}
bool isPattern1Detected(const EnmDir dir)
{
if(dir==0)return(false);
if(getCandleDirection(3)!=dir)
return false;
if(getCandleDirection(2)+dir!=0)
return false;
if(getCandleDirection(1)!=dir)
return false;
if(dir>0)
{
if(iHigh(_Symbol,0,1)-iClose(_Symbol,0,1)>_Point/2.)
return false;
if(iHigh(_Symbol,0,1)-iHigh(_Symbol,0,3)>_Point/2.)
return true;
return false;
}
else
{
if(iClose(_Symbol,0,1)-iLow(_Symbol,0,1)>_Point/2.)
return false;
if(iLow(_Symbol,0,3)-iLow(_Symbol,0,1)>_Point/2.)
return true;
return false;
}
}
bool isPattern2Detected(const EnmDir dir,const int numCandlesAgainst=1)
{
if(dir==NONE)return(false);
if(getCandleDirection(1)!=dir)
return false;
for(int i=1;i<=numCandlesAgainst;i++)
{
if(getCandleDirection(1+i)!=dir)
return(false);
}
if(getCandleDirection(2+numCandlesAgainst)!=dir)
return false;
if(dir>0)
{
if(iHigh(_Symbol,0,1)-iClose(_Symbol,0,1)>_Point/2.)
return false;
if(iHigh(_Symbol,0,1)-iHigh(_Symbol,0,2+numCandlesAgainst)>_Point/2.)
return true;
return false;
}
else
{
if(iClose(_Symbol,0,1)-iLow(_Symbol,0,1)>_Point/2.)
return false;
if(iLow(_Symbol,0,2+numCandlesAgainst)-iLow(_Symbol,0,1)>_Point/2.)
return true;
return false;
}
}
还需要什么?要检测矩形的HL吗?这很简单,规则很清晰。让我们假设它们是:对于LONG,up=第2根K线的开盘价,down=该K线的最低价。然后,
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;
const string name=prefix+"_"+(dir>0?"DEMAND":"SUPPLY")+"_"+TimeToString(starts);
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);
return true;
}
这是主要的代码块,请不要忘记添加新的检查条,否则工具将在每个时间片检查对象,这是浪费时间。
string prefix=""; //为所有对象添加一些唯一的前缀
const int N_bars = 15; //本例中有15个条形图
void OnDeinit(const int reason){ObjectsDeleteAll(0,prefix);}
void OnTick()
{
if(!isNewBar())
return;
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;
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);
}
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;
}