私はmql4
コード。次のろうそく足パターンが発生したときに長方形を描画するための助けを得ることができればありがたいです。
FIG1:
Run code snippet
<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>
FIG2:
Run code snippet
<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:
Run code snippet
<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>
およびそれぞれの供給ゾーン
そして指定されたpipsのストップロスとテイクプロフィットで未決注文を開く.
画像を直接含めないでください。私はそれを行うのに十分な賛成票を持っていません。
リンクされた画像のローソク足パターンの説明は次のとおりです。
一般的な candlestick pattern
(デマンドゾーン)は、少なくとも2つ以上の強気のキャンドル(最後の強気のキャンドルが期間の最高である)の後に、高低が最後の強気のキャンドルよりも低い1つ以上の弱気のキャンドルが続く場合に発生します。 。そして最後に、新しい高値を形成する強気のキャンドルが続きます。デマンドゾーンである長方形の領域は、最後の弱気ろうそくの始値から安値までの範囲です。
一連の連続した強気のろうそくに、前のろうそくよりも低い、低いろうそくがあり、その高が終値と一致している場合、隠し需要ゾーンは、強気のろうそくの低から開始に移動します。
完全な説明が利用可能です ここ 需要ゾーンと供給ゾーンの両方について。
bullish
とbearish
のキャンドルは、
if ( ( Open[1] - Close[1] ) > 0)
{
// candle is bearish
}
else
{
// candle is bullish
}
本当に助かります。
これらのパターンは完全に記述されていないようですので、それらを正しくコーディングすることはできません。では、パターン#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の場合、up =バー#2のオープン、down =そのバーのローです。そして、
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);
}
}
長方形を描く必要がありますか? Okしかし、描画を停止する時間をどのように決定しますか?右側の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;
}
ここがメインブロックです。新しいバーチェックを追加することを忘れないでください。そうしないと、ツールがティックごとにオブジェクトをチェックするため、時間の無駄になります。 string prefix = ""; //すべてのオブジェクトに一意のプレフィックスを追加します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;
}
私は遅れています: '(仕事によってStackOverflowから遠ざけられました:'(とにかく、バウンティに従って完全なプログラムを提供することも、このデマンドゾーンの質問を解決するための完全なコードを提供することもできません。
ただし、MT4(MQL4)で独自のパターン認識機能を構築するための「出発点」を提供したいと思います。
テキストを短くするために、私はそれを説明するためにYouTubeビデオを録画しました。 https://youtu.be/WSiyY52QyBI
とにかく、ここにコードがあります:
//+------------------------------------------------------------------+
//| SO56854700.mq4 |
//| Copyright 2019, Joseph Lee, TELEGRAM JosephLee74 |
//| https://stackoverflow.com/users/1245195/joseph-lee |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Joseph Lee, TELEGRAM JosephLee74"
#property link "https://stackoverflow.com/users/1245195/joseph-lee"
#property version "1.00"
#property strict
#include <clsBar.mqh>
#include <stderror.mqh>
#include <stdlib.mqh>
//==========================================================================
//-------------------------------------------------------------------
// System Variables
//-------------------------------------------------------------------
double viPipsToPrice = 0.0001;
double viPipsToPoint = 1;
string vsDisplay = "";
//-------------------------------------------------------------------
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
ObjectsDeleteAll(); Comment("");
// Caclulate PipsToPrice & PipsToPoints (old sytle, but works)
if((Digits == 2) || (Digits == 3)) {viPipsToPrice=0.01;}
if((Digits == 3) || (Digits == 5)) {viPipsToPoint=10;}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
ObjectsDeleteAll();
return(0);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
if(!isNewBar())
return;
clsCandlestickPattern voPatterns[];
clsPatternRecognizer voRec(Symbol(), true), PERIOD_CURRENT, 0);
voRec.sbRecognizePatterns(voPatterns);
for(...
Display the content with Comment() ...
}
//+------------------------------------------------------------------+
さらに重要なのは、clsBar.mqhです。これは「インクルードファイル」であり、インクルードフォルダーに配置する必要があることに注意してください。インクルードファイルは、プログラムを整理し、再利用可能なコードを記述できるようにするのに役立ちます。 OOPクラスを書くときに非常に役立ちます。
clsBar.mqh:ダウンロード(OneDrive) https://1drv.ms/u/s!AoLFy6fRYNsvjTU-xSzAADCwGjPQ
残念ながら、ファイルが大きすぎてこの投稿に含めることができません。 OneDriveをアップロードする必要があります。