cTrader インジケーターを自作する手順 — Indicator クラスの構成とC#コード全文
cTrader のインジケーターは cBot と同じく C# で記述します。発注を伴わない分だけ構造は単純で、自作の入り口としては cBot より取り組みやすい部類です。標準搭載のインジケーターを内部で呼び出せるため、ATR や移動平均の計算を自前で書き直す必要もありません。
本記事では、空のプロジェクトから描画されるインジケーターを1本作るまでを、コード全文とあわせて整理します。発注まで扱う場合は cTrader で cBot を作る手順 を参照してください。
cBot との構造上の違い
インジケーターと cBot は、基底クラスと呼び出され方が異なります。
| インジケーター | cBot | |
|---|---|---|
| 基底クラス | Indicator | Robot |
| 初期化 | Initialize() | OnStart() |
| 計算の入り口 | Calculate(int index) | OnTick() / OnBar() |
| 発注 | できない | できる |
| 出力 | IndicatorDataSeries に書く | 建玉として現れる |
最も大きな違いは、インジケーターの Calculate が「そのインデックスの値を求める関数」として呼ばれる点です。cBot のようにイベントごとに1回走るのではなく、チャート上の各足に対して呼び出され、さらに形成中の足については値が動くたびに繰り返し呼ばれます。
Indicator クラスの骨格
必要な要素は次の4つです。
[Indicator(...)]属性 — チャートに重ねるか、別ウィンドウに出すかを指定[Parameter(...)]— 利用者が調整できる設定値[Output(...)]— 描画する系列Initialize()とCalculate(int index)— 準備と計算
IsOverlay = true を指定すると価格チャートに重ねて描画され、指定しなければ下部の別ウィンドウに表示されます。価格と同じ単位の線を引くなら true、オシレーターのように異なる尺度なら false を選びます。
動くインジケーターの全文
移動平均を中心線とし、その上下に ATR の倍数でバンドを描く構成です。そのままビルドできます。
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
public class AtrBands : Indicator
{
[Parameter("MA Period", DefaultValue = 20, MinValue = 2, Group = "Center")]
public int MaPeriod { get; set; }
[Parameter("ATR Period", DefaultValue = 14, MinValue = 1, Group = "Band")]
public int AtrPeriod { get; set; }
[Parameter("ATR Multiplier", DefaultValue = 2.0, MinValue = 0.1, Group = "Band")]
public double Multiplier { get; set; }
[Output("Middle", LineColor = "Gray")]
public IndicatorDataSeries Middle { get; set; }
[Output("Upper", LineColor = "DodgerBlue")]
public IndicatorDataSeries Upper { get; set; }
[Output("Lower", LineColor = "Tomato")]
public IndicatorDataSeries Lower { get; set; }
private MovingAverage _ma;
private AverageTrueRange _atr;
protected override void Initialize()
{
_ma = Indicators.MovingAverage(Bars.ClosePrices, MaPeriod, MovingAverageType.Simple);
_atr = Indicators.AverageTrueRange(AtrPeriod, MovingAverageType.Exponential);
}
public override void Calculate(int index)
{
// 計算に必要な本数が揃うまでは書き込まない
if (index < Math.Max(MaPeriod, AtrPeriod)) return;
double mid = _ma.Result[index];
double band = _atr.Result[index] * Multiplier;
if (double.IsNaN(mid) || double.IsNaN(band)) return;
Middle[index] = mid;
Upper[index] = mid + band;
Lower[index] = mid - band;
}
}
}
標準インジケーターを内部で呼ぶ
Initialize() の中で Indicators.MovingAverage(...) や Indicators.AverageTrueRange(...) を呼び出すと、cTrader 標準の計算をそのまま利用できます。ATR の計算式を自分で実装する必要はありません。
呼び出しで注意したいのは引数の形です。移動平均は計算対象の系列を第1引数に取りますが、ATR は高値・安値・終値をすべて使うため、系列を渡さず期間と平滑化方式だけを指定します。
_ma = Indicators.MovingAverage(Bars.ClosePrices, MaPeriod, MovingAverageType.Simple);
_atr = Indicators.AverageTrueRange(AtrPeriod, MovingAverageType.Exponential);
平滑化方式によって ATR の値は変わります。既存の他ツールと数字を突き合わせるときは、方式が揃っているかを先に確認してください。ATR そのものの読み方は ATR とボラティリティの基本 で整理しています。
Calculate が繰り返し呼ばれることの意味
インジケーターで最も誤解されやすいのが、Calculate の呼ばれ方です。
過去の確定した足に対しては原則1回ですが、チャート右端の形成中の足に対しては、値が動くたびに同じインデックスで何度も呼ばれます。したがって Calculate の中で状態を書き換える処理を持つと、同じ足で何度も加算されるといった不整合が起きます。
// 避けたい書き方: 同じ index で何度も加算されうる
_counter++;
カウンタや履歴を持ちたい場合は、インデックスごとに値を確定させる形にします。
// index を鍵にして書く。何度呼ばれても同じ結果になる
_series[index] = _series[index - 1] + (condition ? 1 : 0);
同じ入力に対して常に同じ結果を返すように書いておけば、再計算されても値がずれません。これは cBot 側で OnBar() を使って確定足だけを読むのとは異なる考え方で、インジケーター特有の作法です。
出力の設定
[Output(...)] は描画の指定を兼ねています。線の色は文字列で指定でき、破線や太さも属性で調整できます。
[Output("Upper", LineColor = "DodgerBlue", LineStyle = LineStyle.Dots, Thickness = 2)]
public IndicatorDataSeries Upper { get; set; }
値を書き込まなかったインデックスは描画されません。計算に必要な本数が揃うまで return している区間は自動的に空白になるため、初期区間を無理に埋める必要はありません。
つまずきやすい点
| 症状 | 多い原因 |
|---|---|
| 線が一切表示されない | IsOverlay の指定が用途と逆 / 値を書き込んでいない |
| チャート左端で線が乱れる | 必要本数が揃う前に計算している |
| 値が他ツールと合わない | 平滑化方式やソース系列が異なる |
| 右端だけ値が揺れる | 形成中の足を見ている(仕様どおりの挙動) |
| 数えた回数が合わない | Calculate 内で状態を加算している |
右端の値が確定しないのは不具合ではなく、足が閉じるまで値が動き続けるという性質によるものです。確定値だけを扱いたい場合は、参照側でひとつ前のインデックスを読みます。
まとめ
インジケーターの自作は、Initialize で標準インジケーターを組み立て、Calculate でインデックスごとの値を確定させるという型を覚えれば、あとは計算内容を差し替えるだけで応用が利きます。
作った判定を発注まで自動化する段階になったら、同じロジックを cBot 側へ移すことになります。その際は、インジケーターでは許容される「形成中の足を読む」挙動が、cBot では検証結果を歪める原因になる点に注意してください。詳しくは cTrader バックテストの実行手順 で扱っています。
cTrader 向けインジケーターの開発相談や完成品ツールについては ai-programming.xyz をご覧ください。
本記事は一般的な情報提供を目的としています。投資助言ではありません。 取引判断はご自身の責任で行ってください。