【解説】【MQL5 community】 Ultimate Oscillator (究極のオシレーター): 3つの時間枠(相場の短期サイクル、中期サイクル、長期サイクル)を用いることでオシレーターの欠点を補い潜在的な買い圧力と売り圧力を計ります。 単純にある期の高値から終値への価格変動を「売り圧力」と捉え、 安値と終値の差を「買い圧力」と捉える。 ただし、これらの高値・安値は、トゥルーレンジを使って計算する。
【計算法】
実際に計算の基礎となるのは、3つの設定期間におけるそれぞれの買い圧力(Buying Pressure, 以下、BP)と、トゥルーレンジ(以下、TR)である。
まず、当日のBPは、
当日のBP=当日の終値−当日のTL(真の安値)
これを元として、7期間ごとのBPの合計、14期間ごとのBPの合計、28期間間ごとのBPの合計を求める。 最終的に、この3つのBPの合計を、それぞれの期間のTRの合計で割ったものを究極のオシレーター(UO)の値としますが、このままでは、一番期間の長い28期間の値の影響力が大きく、一番期間の短い7期間の値の影響力が小さくなってしまう。 そこで、期間による値の比重が偏らないように、7期間の合計に4を掛け、 14期間の合計に2を掛けて、3つの期間の数値をそろえます。 式で表すと、
UOの基本値=4(7日間のBPの合計 / 7日間のTRの合計)+2(14日間のBPの合計 / 14日間のTRの合計)+(28日間のBPの合計 / 28日間のTRの合計)
さらに、100分率に修正するために、以下の計算を行う。
UO={UOの基本値 /(4+2+1)}×100
【シグナル】
究極のオシレーター(UO)は、価格とUOのダイバージェンス(逆行現象)を売買シグナルとします。 ただし全ての逆行現象を対象にするのではなく、 買いの場合は30%以下、売りの場合は50%以上からの逆行現象を対象とする。
買いシグナル
1.逆行現象、価格が下がっているのにUOのボトムが下がっていない、がある。
2.逆行現象が起きた箇所のUOのピークを注目し、 それを抜けたタイミングで買い
買いポジションを持ったら、
1.逆のシグナルが出たらドテン、買いから売りポジションへ
2.UOが70%以上になったら利食いし、ポジションはスクエア(中立)とする(ドテンはしない)
3.UOが35%以下に下がったらロスカットし、ポジションをスクエア(中立)とする(ドテンはしない)
売りシグナル
1.逆行現象、価格が上がっているのにUOのピークが上がっていない、がある。
2.逆行現象が起きた箇所のUOのボトムを注目し、それを抜けたタイミングで売り。
売りポジションを持ったら、
1.逆のシグナルが出たらドテン、売りから買いポジションへ。
2.UOが30%以下になったら利食い。ポジションはスクエア(中立)とする(ドテンはしない)
3.UOが65%を超えたらロスカット。ポジションをスクエア(中立)とする(ドテンはしない)
//+------------------------------------------------------------------+ //| Ultimate_Oscillator.mq5 | //| Copyright 2009, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2009, MetaQuotes Software Corp." #property link "http://www.mql5.com" #include <MovingAverages.mqh> //--- indicator settings #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 1 #property indicator_type1 DRAW_LINE #property indicator_color1 DodgerBlue //--- input parameters input int InpFastPeriod=7; // Fast ATR period input int InpMiddlePeriod=14; // Middle ATR period input int InpSlowPeriod=28; // Slow ATR period input int InpFastK=4; // Fast K input int InpMiddleK=2; // Middle K input int InpSlowK=1; // Slow K //--- indicator buffers double ExtUOBuffer[]; double ExtBPBuffer[]; double ExtFastATRBuffer[]; double ExtMiddleATRBuffer[]; double ExtSlowATRBuffer[]; //--- indicator handles int ExtFastATRhandle; int ExtMiddleATRhandle; int ExtSlowATRhandle; //--- global variable double ExtDivider; int ExtMaxPeriod; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,ExtUOBuffer,INDICATOR_DATA); SetIndexBuffer(1,ExtBPBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(2,ExtFastATRBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(3,ExtMiddleATRBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(4,ExtSlowATRBuffer,INDICATOR_CALCULATIONS); //--- set accuracy IndicatorSetInteger(INDICATOR_DIGITS,2); //--- set levels IndicatorSetInteger(INDICATOR_LEVELS,2); IndicatorSetDouble(INDICATOR_LEVELVALUE,0,30); IndicatorSetDouble(INDICATOR_LEVELVALUE,1,70); //--- set maximum and minimum for subwindow IndicatorSetDouble(INDICATOR_MINIMUM,0); IndicatorSetDouble(INDICATOR_MAXIMUM,100); //--- set first bar from which index will be drawn PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpSlowPeriod-1); //--- name for DataWindow and indicator subwindow label IndicatorSetString(INDICATOR_SHORTNAME,"UOS("+string(InpFastPeriod)+", "+string(InpMiddlePeriod)+", "+string(InpSlowPeriod)+")"); //--- get handles ExtFastATRhandle=iATR(Symbol(),0,InpFastPeriod); ExtMiddleATRhandle=iATR(Symbol(),0,InpMiddlePeriod); ExtSlowATRhandle=iATR(Symbol(),0,InpSlowPeriod); //--- ExtDivider=InpFastK+InpMiddleK+InpSlowK; ExtMaxPeriod=InpSlowPeriod; if(ExtMaxPeriod<InpMiddlePeriod) ExtMaxPeriod=InpMiddlePeriod; if(ExtMaxPeriod<InpFastPeriod) ExtMaxPeriod=InpFastPeriod; //--- initialization done } //+------------------------------------------------------------------+ //| Ultimate Oscillator | //+------------------------------------------------------------------+ 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 &TickVolume[], const long &Volume[], const int &Spread[]) { int i,limit; double TL,RawUO; //--- check for rates count if(rates_total<ExtMaxPeriod) return(0); //--- not all data may be calculated int calculated=BarsCalculated(ExtFastATRhandle); if(calculated<rates_total) { Print("Not all data of ExtFastATRhandle is calculated (",calculated,"bars ). Error",GetLastError()); return(0); } calculated=BarsCalculated(ExtMiddleATRhandle); if(calculated<rates_total) { Print("Not all data of ExtMiddleATRhandle is calculated (",calculated,"bars ). Error",GetLastError()); return(0); } calculated=BarsCalculated(ExtSlowATRhandle); if(calculated<rates_total) { Print("Not all data of ExtSlowATRhandle is calculated (",calculated,"bars ). Error",GetLastError()); return(0); } //--- we can copy not all data int to_copy; if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total; else { to_copy=rates_total-prev_calculated; if(prev_calculated>0) to_copy++; } //---- get ATR buffers if(CopyBuffer(ExtFastATRhandle,0,0,to_copy,ExtFastATRBuffer)<=0) { Print("getting ExtFastATRhandle is failed! Error",GetLastError()); return(0); } if(CopyBuffer(ExtMiddleATRhandle,0,0,to_copy,ExtMiddleATRBuffer)<=0) { Print("getting ExtMiddleATRhandle is failed! Error",GetLastError()); return(0); } if(CopyBuffer(ExtSlowATRhandle,0,0,to_copy,ExtSlowATRBuffer)<=0) { Print("getting ExtSlowATRhandle is failed! Error",GetLastError()); return(0); } //--- preliminary calculations if(prev_calculated==0) { //--- set empty value for first bar ExtBPBuffer[0]=0.0; ExtUOBuffer[0]=0.0; //--- set value for first InpSlowPeriod bars for(i=1;i<=InpSlowPeriod;i++) { ExtUOBuffer[i]=0.0; TL=MathMin(Low[i],Close[i-1]); ExtBPBuffer[i]=Close[i]-TL; } //--- now we are going to calculate from limit index in main loop limit=InpSlowPeriod+1; } else limit=prev_calculated-1; //--- the main loop of calculations for(i=limit;i<rates_total;i++) { //--- TL is True Low TL=MathMin(Low[i],Close[i-1]); //--- buying pressure ExtBPBuffer[i]=Close[i]-TL; //--- first we calculate "raw" value if(ExtFastATRBuffer[i]!=0.0 && ExtMiddleATRBuffer[i]!=0.0 && ExtSlowATRBuffer[i]!=0.0) { RawUO=InpFastK*SimpleMA(i,InpFastPeriod,ExtBPBuffer)/ExtFastATRBuffer[i]+ InpMiddleK*SimpleMA(i,InpMiddlePeriod,ExtBPBuffer)/ExtMiddleATRBuffer[i]+ InpSlowK*SimpleMA(i,InpSlowPeriod,ExtBPBuffer)/ExtSlowATRBuffer[i]; //--- now we can get current Ultimate value ExtUOBuffer[i]=RawUO/ExtDivider*100; } else { //--- set current Ultimate value as previous Ultimate value ExtUOBuffer[i]=ExtUOBuffer[i-1]; } } //--- OnCalculate done. Return new prev_calculated. return(rates_total); } //+------------------------------------------------------------------+
【表示結果】
Back to Meta Trader