人の目ではMT4のチャートの進行方向は一目で分かります。
数理的にはどのような方法で判断すべきでしょう。
色々な方法が考えられますが、ここで最小二乗法による回帰直線の傾きで判断する方法を紹介します。
まず直感として、最小二乗法による回帰直線は次のようなものです。
これをMT4のOpenまたはCloseなどの値に適応すれば、方向判定できます。
次の赤丸の点はOpen値を入力とした場合のイメージです。
最小二乗法による回帰直線の傾きの計算方法は次の数式の「a」です。
そして上の数式をコーディングする場合、次のサンプルコードが一例です。
まず平均値、次に共分散と分散、最後に傾きaの順に求めます。
一つ注意しなければいけないのはデータの入力順番です。iCloseなどを利用してデータを取得する場合、現在位置から近いほど、シフトが小さいことです。
通常のプログラミングの場合、インデックスが0, 1, 2, ・・・ので、この順にデータを格納して、この順でデータを取り出して計算すると、実際の為替チャートと逆順のデータ出力になります。
ですので、これを正すのに、傾きaの結果を正負反転させる必要があります。
// Least Squares Method.
void GeneralManager_UpdateDirection(const double ask, const double bid) export
{
static int minute = Minute();
static int count = 0; // Test code.
double closeValue[MOVING_AVERAGE_N], y[MOVING_AVERAGE_N];
double currDir = 0, avgX = 0, avgY = 0;
ArrayInitialize(closeValue, 0.0);
ArrayInitialize(y, 0.0);
if (minute != Minute())
{
minute = Minute();
count += 1; // Test code.
if (count < 200) // Test code.
{ // Test code.
for (int i = 0; i < MOVING_AVERAGE_N; i++)
{
// i = 0:newest close value, MOVING_AVERAGE_N-1:oldest value.
closeValue[i] = iClose(Symbol(), PERIOD_M1, i + 1);
y[i] = i + 1;
// Sum xi, yi.
avgX += closeValue[i];
avgY += y[i];
Print("The close value of ", i+1, " minutes ago is ", DoubleToStr(closeValue[i], Digits));
}
double s1 = 0, s2 = 0;
// Average xi, yi.
avgX = avgX / MOVING_AVERAGE_N;
avgY = avgY / MOVING_AVERAGE_N;
for (int i = 0; i < MOVING_AVERAGE_N; i++)
{
// sum[1~n]((xi-x)*(yi-y))
s1 += (closeValue[i] - avgX) * (y[i] - avgY);
// sum[1~n]((xi-x)^2)
s2 += (closeValue[i] - avgX) * (closeValue[i] - avgX);
}
// a = sum[1~n]((xi-x)*(yi-y)) / sum[1~n]((xi-x)^2)
if (s1 / s2 > 0)
{
// a > 0, but the data are reversed, so the gradient is a minus value.
currDirection = DIRECTION_DN;
Print(__FUNCTION__, ", Current direction is Down. Line:", __LINE__);
}
else
{
// a < 0, but the data are reversed, so the gradient is a plus value.
currDirection = DIRECTION_UP;
Print(__FUNCTION__, ", Current direction is Up. Line:", __LINE__);
}
} // Test code.
}
}
※「// Test code.」になっている所はテストコードで、実践時外してください。
※「if (minute != Minute())」にガードしているのは頻繁な実行を抑えるために、分ペースでチェックしています。
※「MOVING_AVERAGE_N」は何個のデータで方向判定したいのかを必要に応じて設定してください。
※関数パラメータは使ってませんが、乱高下発生時に大幅な変動が起こった時の改善に利用できます。
※iCloseで分単位の終値を使ってますが、MQLの公開APIはもちろん、自ら形成した均一間隔のデータを利用しても大丈夫でしょう。むしろ後者の方が綺麗な論理グラフになれます。後者の場合、多少データ処理を追加で行う必要があるので、ご挑戦してください。
|
|
コメント