本家のLSMAの方は、二乗平均誤差をベースにあれこれしていますが、メジャーインジケータであるボリンジャーバンドも、分けて考えると違った物が見えてくるかもしれません。
ということで、早速サラッと作ってみました。標準的なボリンジャーバンドの計算方法を移動平均より上のデータと下のデータを分けて計算して描画しています。
データ量が1/2になっっている前提で、バンド幅のσ値を通常の2倍にしています。
わりあい機能するような・・・しないような??
M1とかの逆張りとかのほうがいいのかもしれません。
ソースコードはブログの最後です。
ボリンジャーバンド特有の価格が動いた時に逆方向にもバンド幅が伸びてしまう症状が無いだけでも優秀かもしれません。
せっかく上と下に分けるんだから、high/low見た方がいいかな?ということで、下はlow、上はhighと分けて計算しています。
「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧
Twitterもよろしくお願いします。
https://twitter.com/mt4program
Trading View プロフィール
ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 |
お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。
//------------------------------------------------------------------
// +と-側のボリンジャーバンドを別に計算してみた。
#property copyright "Copyright 2017, Daisuke"
#property link "http://mt4program.blogspot.jp/"
#property version "1.00"
#property strict
#property indicator_chart_window
//バッファーを指定する。
#property indicator_buffers 5
//プロット数を指定する。
#property indicator_plots 5
#property indicator_label1 "Band1"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrAqua
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_label2 "Band2"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrAqua
#property indicator_style2 STYLE_DOT
#property indicator_width2 1
#property indicator_label3 "Band3"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrIndianRed
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
#property indicator_label4 "Band4"
#property indicator_type4 DRAW_LINE
#property indicator_color4 clrIndianRed
#property indicator_style4 STYLE_SOLID
#property indicator_width4 1
#property indicator_label5 "MA"
#property indicator_type5 DRAW_LINE
#property indicator_color5 clrYellow
#property indicator_style5 STYLE_DOT
#property indicator_width5 2
double m_buffer1[];
double m_buffer2[];
double m_buffer3[];
double m_buffer4[];
double m_buffer5[];
input int MaPeriod = 21; // 移動平均期間
input ENUM_APPLIED_PRICE PriceMode = PRICE_TYPICAL; // 対象価格
input double BandWidth1 = 2.0; // バンド幅1
input double BandWidth2 = 4.0; // バンド幅2
//------------------------------------------------------------------
//初期化
int OnInit()
{
//インジケーターバッファを初期化する。
SetIndexBuffer(0,m_buffer1);
SetIndexBuffer(1,m_buffer2);
SetIndexBuffer(2,m_buffer3);
SetIndexBuffer(3,m_buffer4);
SetIndexBuffer(4,m_buffer5);
string short_name = "HBB(" + IntegerToString(MaPeriod) + ")";
IndicatorShortName(short_name);
return(INIT_SUCCEEDED);
}
//------------------------------------------------------------------
//計算イベント
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 upDiff[];
double downDiff[];
ArrayResize(upDiff, MaPeriod);
ArrayResize(downDiff, MaPeriod);
for( int i = rates_total - prev_calculated - 1; i >= 0 && !IsStopped(); i-- )
{
if( i > rates_total - MaPeriod ) continue;
m_buffer5[i] = iMA(NULL, PERIOD_CURRENT, MaPeriod, 0, MODE_SMA, PriceMode, i);
ArrayInitialize(upDiff, 0);
ArrayInitialize(downDiff, 0);
for( int j = 0; j < MaPeriod; j++ )
{
if( high[i + j] > m_buffer5[i + j] ) upDiff[j] = high[i + j] - m_buffer5[i + j];
if( low[i + j] < m_buffer5[i + j] ) downDiff[j] = m_buffer5[i + j] - low[i + j];
}
double upStd = StdDev(upDiff, MaPeriod, 0);
double downStd = StdDev(downDiff, MaPeriod, 0);
m_buffer1[i] = m_buffer5[i] + BandWidth1 * upStd;
m_buffer2[i] = m_buffer5[i] + BandWidth2 * upStd;
m_buffer3[i] = m_buffer5[i] - BandWidth1 * downStd;
m_buffer4[i] = m_buffer5[i] - BandWidth2 * downStd;
}
ArrayFree(upDiff);
ArrayFree(downDiff);
return rates_total - 1;
}
//------------------------------------------------------------------
//標準偏差を求める。
// return 標準偏差
double StdDev(
const double &values[], //元となる配列
int count, //計算対象数
int shift //シフト
)
{
if( (count + shift) > ArraySize(values) ) return 0;
double avg = 0 ;
double mu = 0 ;
for( int i = shift; i < shift + count; i++ )
{
avg += values[i];
}
avg = avg / count;
for( int i = shift; i < shift + count; i++ )
{
mu += MathPow(values[i] - avg, 2);
}
// 標本標準偏差
return MathSqrt(mu / (count - 1));
}