【投機】逆張りからのトレンドフォロー(もどき)検証用インジ

 

まえがき

こんにちは、こんばんは、趣味のプログラマーさつま芋です。

 

2本の矢印の長さを見比べる錯覚は有名ですが、錯覚を排除することは本当に難しいです。

f:id:satsumaim0:20201213111022p:plain

投機の難しさは感覚的な個人差が出ることですから、その差を知ることが一つのアプローチになると思います。

 

今回は検証用インジのコード紹介です。

 

 

勝率6割以上と聞いて検証用インジにした

プログラムの練習を兼ねて、ある投資系ユーチューバーの公開手法を参考に、検証用インジにしてみました。

 

「裁量手法」として紹介されているものですが、機械的な結果が知りたくてプログラミングしました。

 

参考にした手法は、逆張りからのトレンドフォローと呼ばれているものですが、それを完ぺきに再現した保証はなく、所詮は私の解釈に過ぎません。

 

一応の動作確認はしていますが、使用上の責任は負いません

 

 

コンパイルしたファイルにはパスワードを設定してあります。

パスワード 「abc」 Gyakubari.ex4

 

一方、下のコードには制限を付けていませんので、パスワード入力を邪魔と感じる人は ご自身でコンパイルしてください。

 

 

手法の概要

ボリンジャーバンドの-2σからの上昇後、ミドルライン上でヒゲを形成すれば売りエントリーし、損切り20pips、利確40pipsを決済条件としています。

 

ただし、20pipsの含み益で損切をブレイクイーブン(建値移動)します。

 

 

補足

f:id:satsumaim0:20201213103017p:plain


エントリー(新規注文)からエグジット(決済)まで線を引いています。

 

勝ちトレードなら水色、負けトレードなら赤色の線にしています。

 

ブレイクイーブン(同値撤退)の場合は黄色で表記しています。

 

赤い親指の印は-2σの反発を表示しています。

 

ちなみに、短い足(分足や時間足)よりも日足以上で検証するほうが良さそうです。

 

 

コード

//+------------------------------------------------------------------+
//| Gyakubari.mq4 |
//| Copyright 2020, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 6
#define PREFIX MQLInfoString(MQL_PROGRAM_NAME)+"_"
//--- plot UP
#property indicator_label1 "UP"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
//--- plot DN
#property indicator_label2 "DN"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrAqua
#property indicator_style2 STYLE_SOLID
#property indicator_width2 2

//--- plot BBupper
#property indicator_label3 "BBupper"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrYellow
#property indicator_style3 STYLE_DOT
#property indicator_width3 1
//--- plot BBmiddle
#property indicator_label4 "BBmiddle"
#property indicator_type4 DRAW_LINE
#property indicator_color4 clrYellow
#property indicator_style4 STYLE_SOLID
#property indicator_width4 1
//--- plot BBlower
#property indicator_label5 "BBlower"
#property indicator_type5 DRAW_LINE
#property indicator_color5 clrYellow
#property indicator_style5 STYLE_DOT
#property indicator_width5 1
//--- plot MA
#property indicator_label6 "MA"
#property indicator_type6 DRAW_LINE
#property indicator_color6 clrLime
#property indicator_style6 STYLE_SOLID
#property indicator_width6 1
//--- input parameters
input string PassWord="";
string pwAllowed = "abc";
input int TP=40; // 利確[pips]
input int SL=20; //損切[pips]
input int TERM=5000; //検証期間(ローソク足本数)
//--- parameters
int p=Bars;
int win=0, lose=0, even=0, lossing=0, counter=0;
int ratio, total;
//--- indicator buffers
double UP;
double DN
;
double BBupper;
double BBmiddle
;
double BBlower;
double MA
;

string expire = "2021.12.31";
bool authenticated = true; // restriction

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
/*
//--- password
if(authenticated && PassWord != pwAllowed)
{
authenticated = false;
Alert("bad password");
return INIT_FAILED;
}

//--- expire
if(authenticated && TimeCurrent() >= StringToTime(expire))
{
authenticated = false;
Alert("expire");
return INIT_FAILED;
}
*/

//--- indicator buffers mapping
SetIndexBuffer(0,UP);
SetIndexBuffer(1,DN);
SetIndexBuffer(2,BBupper);
SetIndexBuffer(3,BBmiddle);
SetIndexBuffer(4,BBlower);
SetIndexBuffer(5,MA);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
SetIndexStyle(0,DRAW_ARROW);
SetIndexArrow(0,233);
SetIndexStyle(1,DRAW_ARROW);
SetIndexArrow(1,234);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0,PREFIX);
Comment("");
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
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
)
{
//---
double SPREAD=MarketInfo(Symbol(),MODE_SPREAD)*0.1;

int limit=Bars-prev_calculated-1;
if(limit<1)limit=1;
for(int i=limit; i>=0; i--) {
BBupper[i] =iBands(NULL,PERIOD_CURRENT,20,2,0,PRICE_CLOSE,MODE_UPPER,i);
BBmiddle[i] =iBands(NULL,PERIOD_CURRENT,20,2,0,PRICE_CLOSE,MODE_MAIN,i);
BBlower[i] =iBands(NULL,PERIOD_CURRENT,20,2,0,PRICE_CLOSE,MODE_LOWER,i);
}

for(int i=limit/(PeriodSeconds()/PeriodSeconds()); i>=0; i--) {
int y=iBarShift(NULL,PERIOD_D1,Time[i]);
MA[i]=iMA(NULL,PERIOD_D1,100,0,MODE_SMA,PRICE_CLOSE,y);
}

//売サイン
for(int i=MathMin(Bars-1,TERM); i>0; i--) {
if(BBmiddle[i]>Close[i] && BBmiddle[i]<=High[i]) {
for(int j=i+1; j<=Bars; j++) {
if(BBupper[j]<=High[j]) break;
else if(BBlower[j]<High[i] && BBlower[j+1]>=Low[j+1] && i<p) {
ObjectCreate(0,PREFIX+"point"+(string)i,OBJ_ARROW_THUMB_UP,0,Time[j+1],Low[j+1]);
DN[i]=High[i];
ObjectCreate(0,PREFIX+"sell"+(string)i,OBJ_ARROW_SELL,0,Time[i],Close[i]);
ObjectSetInteger(0,PREFIX+"sell"+(string)i,OBJPROP_COLOR,clrDodgerBlue);

//---結果判定
int k, m, n;
int EVEN=SL;
for(k=i-1; k>0 && Close[i]-PipsToPrice(TP+SPREAD)<Low[k] && Close[i]+PipsToPrice(SL-SPREAD)>High[k]; k--) {
continue;
}
if(Close[i]-PipsToPrice(TP+SPREAD)>=Low[k]) {
for(m=i; m>=k; m--) {
if(Low[m]<=Close[i]-PipsToPrice(EVEN+SPREAD)) {
for(n=m-1; n>=k ; n--) {
if(High[n]>=Close[i]-PipsToPrice(SPREAD)) {
ObjectCreate(0,PREFIX+"stop"+(string)i,OBJ_ARROW_STOP,0,Time[i],High[i]+PipsToPrice(SL-SPREAD));
p=k;
even++;
if(win>0)win--;
TextCreate(PREFIX+"even"+(string)i,"勝ち喪失",Time[k],Close[i]-PipsToPrice(TP+SPREAD),clrYellow);
ObjectSetInteger(0,PREFIX+"even"+(string)i,OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
break;
}
}
}
}
p=k;
win++;
TrendCreate(PREFIX+"line"+(string)i,Time[i],Close[i],Time[k],Close[i]-PipsToPrice(TP+SPREAD),clrAqua);
} else if(Close[i]+PipsToPrice(SL-SPREAD)<=High[k]) {
for(m=i; m>=k; m--) {
if(Low[m]<=Close[i]-PipsToPrice(EVEN+SPREAD)) {
p=k;
even++;
if(lose>0)lose--;
TextCreate(PREFIX+"even"+(string)i,"負け回避",Time[k],Close[i]+PipsToPrice(SL-SPREAD),clrYellow);
ObjectSetInteger(0,PREFIX+"even"+(string)i,OBJPROP_ANCHOR,ANCHOR_LEFT_LOWER);
break;
}
}
p=k;
lose++;
TrendCreate(PREFIX+"line"+(string)i,Time[i],Close[i],Time[k],Close[i]+PipsToPrice(SL-SPREAD),clrRed);
}
}
}
}
}

ratio=(int)100*win/(win+lose);
LabelCreate(PREFIX+"Retio","勝率 "+(string)ratio+" % ("+(string)win+"勝"+(string)lose+"敗"+(string)even+"引分)",20,70,CORNER_LEFT_LOWER,clrWhite);

total=(int)40*win-20*lose;
LabelCreate(PREFIX+"Total","合計 "+(string)total+" pips",20,40,CORNER_LEFT_LOWER,clrWhite);

//--- return value of prev_calculated for next call
return(rates_total);
}

//+------------------------------------------------------------------+
//| pipsを価格に換算する関数
//+------------------------------------------------------------------+
double PipsToPrice(double pips)
{
double price = 0;

// 現在の通貨ペアの小数点以下の桁数を取得
int digits = (int)MarketInfo(Symbol(), MODE_DIGITS);

// 3桁・5桁のFXブローカー
if(digits == 3 || digits == 5) {
price = pips / MathPow(10, digits) * 10;
}
// 2桁・4桁のFXブローカー
if(digits == 2 || digits == 4) {
price = pips / MathPow(10, digits);
}
// 価格を有効桁数で丸める
price = NormalizeDouble(price, digits);
return(price);
}
//+------------------------------------------------------------------+
//| Create a trend line by the given coordinates |
//+------------------------------------------------------------------+
bool TrendCreate(
const string name="TrendLine", // line name
datetime time1=0, // first point time
double price1=0, // first point price
datetime time2=0, // second point time
double price2=0, // second point price
const color clr=clrLightBlue, // line color
const long chart_ID=0, // chart's ID
const int sub_window=0, // subwindow index
const ENUM_LINE_STYLE style=STYLE_SOLID, // line style
const int width=4, // line width
const bool back=false, // in the background
const bool selection=false, // highlight to move
const bool ray_right=false, // line's continuation to the right
const bool hidden=true, // hidden in the object list
const long z_order=0) // priority for mouse click
{
//--- create a trend line by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_TREND,sub_window,time1,price1,time2,price2)) {
return(false);
}
//--- set line color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set line display style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set line width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the line by mouse
//--- when creating a graphical object using ObjectCreate function, the object cannot be
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,true);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- enable (true) or disable (false) the mode of continuation of the line's display to the right
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}

//+------------------------------------------------------------------+
//| Create a text label |
//+------------------------------------------------------------------+
bool LabelCreate(
const string name="Label", // label name
const string text="Label", // text
const int x=0, // X coordinate
const int y=0, // Y coordinate
const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER, // chart corner for anchoring
const color clr=clrRed, // color
const int font_size=20, // font size
const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // anchor type
const string font="メイリオ", // font
const long chart_ID=0, // chart's ID
const int sub_window=0, // subwindow index
const double angle=0.0, // text slope
const bool back=false, // in the background
const bool selection=false, // highlight to move
const bool hidden=true, // hidden in the object list
const long z_order=0) // priority for mouse click
{
//--- create a text label
if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)) {
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
return(false);
}
//--- set label coordinates
ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
//--- set the chart's corner, relative to which point coordinates are defined
ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
//--- set the text
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- set text font
ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//--- set font size
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//--- set the slope angle of the text
ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
//--- set anchor type
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
//--- set color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the label by mouse
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Creating Text object |
//+------------------------------------------------------------------+
bool TextCreate(
const string name="Text", // object name
const string text="Text", // the text itself
datetime time=0, // anchor point time
double price=0, // anchor point price
const color clr=clrWhite, // color
const int font_size=20, // font size
const string font="メイリオ", // font
const long chart_ID=0, // chart's ID
const int sub_window=0, // subwindow index
const double angle=0.0, // text slope
const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // anchor type
const bool back=false, // in the background
const bool selection=false, // highlight to move
const bool hidden=true, // hidden in the object list
const long z_order=0) // priority for mouse click
{
//--- create Text object
if(!ObjectCreate(chart_ID,name,OBJ_TEXT,sub_window,time,price)) {
return(false);
}
//--- set the text
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- set text font
ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//--- set font size
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//--- set the slope angle of the text
ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
//--- set anchor type
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
//--- set color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the object by mouse
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+

 

 

あとがき

繰り返しになりますが、使用上の責任は負いません

 

また、一般公開されている手法とはいえ、監修を受けていないプログラムなので、引用した裁量手法の優位性を肯定するものでも否定するものでもありません。

 

以上、さつま芋でした。