LINE通知インジケーターを改変してみる
こんなコメントをいただきました。
cTrader(cBot)からの通知をLINEで受け取る / https://www.merryoneslife.com/use-line-notify/
拝見させていただきました。
LINEによる通知をMAクロス時に送るインジケーターが作りたいのですが、お恥ずかしい話どこをどういじっていいのか分からず途方に暮れています。。。
以前に作ったものはポジションを通知するインジケーターだったため、イベント処理系のコードになっており、インジケーターを使うように変更するにはわかりにくかったかもしれません。
今回はMAクロスでLINE通知するサンプルコードを紹介していきたいと思います。
MANotifyAtLine
機能概要
上記記事のPositionNotifyAtLINEに少し手を加えてMAクロスでLINE通知が届くようにしました。ローソク足更新時にクロスが検知出来たらLINE通知します。
とりあえずダウンロード。
(2021/11/10 更新・追記)
実際使うには通知内容にシンボル名すらない不親切仕様だったので、シンボル名とタイムフレーム、自分で設定したテキストも追加で通知できるよう変更しました。
記事内記載のソースコードはできるだけシンプルな形にしておきたいので、変更してません。
(追記ここまで)
パラメータは見てもらえばなんとなくわかると思います。
なおLINE通知を使う関係で警告が出ます。あしからず。
LINEの設定は過去記事参照
使うだけならLINEの設部分のが手間取るかもしれません。LINE Notifyを使ったことがない方はまずはこっちを確認してください。
-
cTrader(cBot)からの通知をLINEで受け取る
(2021/10/11 注意点を追記) LINEで通知を受け取りたい! メッセージングアプリなに使ってますか?有名どころのWhatsApp、仕事ならSlack、cTrader情報用にTelegramと ...
続きを見る
ソースコード解説
「MAのクロスなんて使わないよ!〇〇と〇〇が××のときに通知してほしいんだよ!」みたいな人もたくさんいると思います。
そんな方は自分でソースコードいじって作ってみてください。変更部分を簡単に解説します。
宣言部分
冒頭部分です。
namespace cAlgo {
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class MANotifyAtLine : Indicator {
[Parameter(DefaultValue = "")]
public string AccessToken { get; set; }
// --- MAパラメータ
[Parameter(DefaultValue = 75)]
public int Period1 { get; set; }
[Parameter(DefaultValue = 200)]
public int Period2 { get; set; }
[Parameter(DefaultValue = MovingAverageType.Simple)]
public MovingAverageType MaType1 { get; set; }
[Parameter(DefaultValue = MovingAverageType.Simple)]
public MovingAverageType MaType2 { get; set; }
// --- MA表示用
[Output("MA1")]
public IndicatorDataSeries Ma1 { get; set; }
[Output("MA2")]
public IndicatorDataSeries Ma2 { get; set; }
// --- MAはフィールドに持っておく
private MovingAverage ma1;
private MovingAverage ma2;
// --- 最後にCalculateした時間保存用
private DateTime lastCalcTime;
28~36行目は2本のMAのパラメータですね。使うときに好きな値を設定できます。
39~42行目はMA表示用のバッファ。別にMAを表示しなくていいならいらないですが、MAクロスで通知するならMAも表示させておくのが普通だと思います。
46、47行目は通知判定に使うmaを保持しておくための変数です。MA以外のインジケーターを使う場合もその型の変数を用意しておいてください。
55行目はバー更新の検知用に最後にCalculateしたローソク足の開始時間を保存しておくための変数です。
初期化
protected override void Initialize(){
// --- MA初期化
ma1 = Indicators.MovingAverage(Bars.ClosePrices, Period1, MaType1);
ma2 = Indicators.MovingAverage(Bars.ClosePrices, Period2, MaType2);
// --- 現在足の開始時間を保存しておく
lastCalcTime = Bars.OpenTimes[Bars.Count - 1];
}
Initializeメソッド内で初期化します。
57,58行目の記述でma1,ma2変数に指定したパラメータの移動平均線が入ります。
MT4(MQL)に慣れてる方は「iMAでパラメータとインデックスを指定し、特定の時間の値を取得する」という形に慣れてると思いますが、cTraderではまずパラメータを指定して「指定パラメータの移動平均線オブジェクト」を取得します。
ma1に入るのは一つの数値ではなく「Perio期間のMaType移動平均線」そのものです。数値を取り出したいときはここにインデックスを指定しma.Result[index]というように取得します。
なお、組込インジケーターであればIndicatorsからだいたい同じように取得できます。
61行目はlastCalcTimeに現在足の開始時間を入れておいてるだけです。
計算処理全体
Calculateメソッド内で表示用MAに数値を設定し、LINE通知判定を行います。
public override void Calculate(int index) {
// --- MA表示部分
Ma1[index] = ma1.Result[index];
Ma2[index] = ma2.Result[index];
// --- Bar更新時のみ通知判定
if (IsLastBar && Bars.OpenTimes[index] > lastCalcTime) {
lastCalcTime = Bars.OpenTimes[index];
// --- 直前の値と2つ前の値を比べて通知判定
var ma1Now = ma1.Result[index - 1];
var ma1Ex = ma1.Result[index - 2];
var ma2Now = ma2.Result[index - 1];
var ma2Ex = ma2.Result[index - 2];
if (ma1Ex <= ma2Ex && ma1Now > ma2Now) {
var _ = SendLineAsync("Golden Cross!");
} else if (ma1Ex >= ma2Ex && ma1Now < ma2Now) {
var _ = SendLineAsync("Dead Cross!");
}
}
}
ここもMT4と異なる点なのですが、cTraderのインジケーターでは初期化後にCalculateメソッドがすでにあるローソク足の本数だけ呼ばれます。
つまり読み込まれているローソク足が300本あったら、まず最初にindexに0~299が入りCalculateが300回呼ばれるのです。
そのためMT4のように過去の足を計算する処理をここに書く必要はありません。表示用のMA設定は68,69行目だけでいいのです。用意しておいたバッファにma1,ma2の値を放り込むだけ。
で、初期化後はCalculateは毎Tick呼ばれます(ここはMT4と同じ)。今回はバーの更新時のみ通知判定するため、72行目で条件判定させてます。
IsLastBarは最新のローソク足の計算をしてるときだけTrueになるあらかじめIndicatorに用意されてるプロパティです。
LINE通知判定のような処理は過去の値を計算してるときにはスキップさせたいため、こんな感じで条件式を書きます。(実はこのコードではIsLastBarの条件はなくてもいいんですけどね。解説用です。)
クロス判定部分
前のコードのクロス判定部分だけ抜き出します。
// --- 直前の値と2つ前の値を比べて通知判定
var ma1Now = ma1.Result[index - 1];
var ma1Ex = ma1.Result[index - 2];
var ma2Now = ma2.Result[index - 1];
var ma2Ex = ma2.Result[index - 2];
if(ma1Ex <= ma2Ex && ma1Now > ma2Now) {
var _ = SendLineAsync("Golden Cross!");
}else if(ma1Ex >= ma2Ex && ma1Now < ma2Now) {
var _ = SendLineAsync("Dead Cross!");
}
76~79行目は比較しやすいようにそれぞれ1つ前と2つ前の値を取り出してるだけですね。
ここでの注意点としては1つ前の値と2つ前の値を比べるということ。
ma.Result[index]の値は今更新されたローソク足の未確定MA値なので使ってはいけません。確定した値でクロスを検知したいため、比較するのは一つ前(ma1Now)と二つ前(ma1Ex)です。
81~85行目で条件判定して、条件満たしたらラインでメッセージを送るメソッドを呼び出してるだけです。
呼び出し方が見慣れないかもしれませんが、別にSendLineAsync("Golden Cross!")だけでも大丈夫です。(警告は出ますが気にならなければ)
ちなみにこのように呼ぶ場合、何らかのエラーでLINEが送れなかった時でもなにごともなかったかのようにこのインジケーターは動き続けます。
重要な通知を受け取る場合には使えませんのでご注意ください。
プログラムに馴染みないとソースコードなんて見てもわけわからないかもしれませんが、一度慣れてしまえば簡単に自分好みいじれるようになると思います。
プログラムに興味ある方はぜひ改変に挑戦してみてください。