インジケーターの作成

cBots (自動売買)

アクションマップ

次の図は、カスタムインジケーターの作成と実装のアクションフローを示しています。

新しいインジケーターを追加
インジケーターコードを編集
インジケーターを保存してビルド
インジケーターインスタンスを作成してカスタマイズ

新しいインジケーターを追加

検索バーの右側にある「新規」ボタンをクリックします。次のウィンドウが開きます。

インジケーター名を入力し、2つのオプションから選択します。

  • 空白」。このオプションを選択すると、新しいインジケーターには基本的なテンプレートのみが含まれます。
  • リストから」。このオプションを選択し、以下のリストからインジケーターを選択すると、新しいインジケーターには選択されたアルゴリズムの全コードが含まれます。リストにある既製のインジケーターは、幅広いテクニカル分析パターンと視覚的な出力をカバーしています。

サンプルリポジトリ

リストから」オプションのコードサンプルは、git@github.com:spotware/ctrader-automate-samples.gitリポジトリから取得されています。アクセスするには、こちらをクリックしてください。

作成」をクリックしてインジケーターの設定を完了します。

注意

類似のアルゴリズムを異なる名前で作成したい場合は、複製機能を使用することができます。

サンプルコードの編集

新しいインジケーターをクリックしてコードエディタウィンドウを開きます。前のステップで「空白」を選択した場合、次のコードが含まれます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        [Parameter(DefaultValue = "Hello world!")]
        public string Message { get; set; }

        [Output("Main")]
        public IndicatorDataSeries Result { get; set; }

        protected override void Initialize()
        {
            // cTrader Algoについて詳しく知りたい場合は、ヘルプセンターを参照してください。
            // https://help.ctrader.com/ctrader-automate

            Print(Message);
        }

        public override void Calculate(int index)
        {
            // 指定されたインデックスの値を計算する
            // Result[index] = 
        }
    }
}

注意

前のステップで「リストから」を選択した場合、インジケーターはすぐに使用可能な状態になります。出力計算ロジックとカスタムパラメータが含まれます。

前述の通り、インジケーター属性 (Indicator) とそのオプションプロパティ (例: TimeZone および AccessRights) はインジケータークラス (NewIndicator) 宣言の前に配置されます。

[Output("OutputName")] 宣言は、インジケーターが表示する内容を定義します。これを使用した後、次に宣言するプロパティが IndicatorDataSeries タイプであることを確認してください。インジケーター出力のデフォルトの外観をカスタマイズするには、[Output("OutputName")] 宣言にもう1つのパラメータを追加することができます。

1
2
3
/* "Main"は出力名であり、"Orange"はラインの色として選択されます。 */
[Output("Main", LineColor = "Orange")]

Initialize() メソッドは、インジケーターが起動されるときに呼び出されます。通常、このメソッドは変数やシリーズの初期化に使用され、ネストされたインジケーターなどが含まれます。一般的に、このメソッドには、インジケーターの起動時に計算する必要があるすべての変数が含まれているべきであり、不要なリソースの消費を避けるためです。

次に、Calculate() メソッドは、表示したい特定のインデックスの値を計算するために使用されます。このメソッドは、各ヒストリカルバーごとに自動的に呼び出され、リアルタイムでは各受信ティックごとに呼び出されます。マルチシンボル/マルチタイムフレームの実装の場合、インジケーターが分析する各シンボルの各ティックごとに呼び出されます。Calculate() メソッドは、実際のインジケーターの計算式を実装する場所として考えてください。例えば、ハーフトレンドインジケーターの計算式を使用する場合、移動平均の交差を定義するために Calculate() メソッドを使用します。

これらの2つのメソッドは、すべてのインジケーターの「基本」であり、省略することはできません。コード化する際に使用できるクラス、メソッド、およびプロパティについては、リファレンスライブラリを参照してください。さらに、C# および .NET の紹介で示したように、カスタムメソッドを書くことも常に可能です。

学んだことと、他のドキュメントで提供されたを考慮して、インジケーターのコードを自分の要件に合わせて編集してください。

Image title

上の例では、Calculate() メソッドは、各バーの高値と安値の差を決定します。バー自体は、index を使用して Bars コレクションにアクセスして取得されます。

以下のコードをコピーして、名前空間宣言のすぐ下に貼り付けると、同じインジケーターを作成できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class HighMinusLow : Indicator
{
  [Output("Main", LineColor = "Orange")]
  public IndicatorDataSeries Result { get; set; }

  public override void Calculate(int index)
  {
    Result[index] = Bars.HighPrices[<span="n">index] - Bars.LowPrices[index];
  }
}

インジケーターを保存してビルド

コードエディタウィンドウの左上にある「保存」ボタンをクリックしてコードを保存します。代わりに、Ctrl+Sを押します。コードエディタ内の任意の場所を右クリックして、新しく開いたメニューから「保存」を選択することもできます。

Image title

cBotsと同様に、インジケーターも展開する前にビルドする必要があります。インジケーターをビルドするには、コードエディタの上部またはcBotメニューで「ビルド」アイコンをクリックします。この操作のキーボードショートカットはCtrl+Bです。

ビルドが成功すると、「ビルド結果」ビューアに新しいメッセージが表示されます。ビルドが失敗した場合、このウィンドウには、ビルドプロセス中に発生したすべてのエラーの概要が表示されます。「ビルド結果」ビューアのエラー説明をクリックすると、エラーが発生したコードの正確な場所が表示されます。

最後のビルド以来コードに変更があった場合は、「**ビルド*」アイコンの横に赤い「’‘」記号が表示されます。この場合、再度インジケーターをビルドしてから実行します。

インジケーターインスタンスを作成してカスタマイズ

上記のすべてのアクションを正常に完了した場合、インジケーターは展開の準備が整っているはずです。使用を開始するには、次のいずれかのアクションを実行して新しいインスタンスを作成します。

  • 拡張名の右側にある「+」アイコンをクリックします。表示されるメニューで、トレードしたいシンボルを選択します。

Image title

  • cBot名の右側にある「3つのドット」アイコンをクリックし、「インスタンスを追加」を選択します。cTraderは、EURUSDシンボルを使用してh1のタイムフレームで新しいインスタンスを自動的に作成します。

新しいインスタンスがインジケーターのすぐ下に表示されます。

Image title

注意

ライン」パラメータは、明示的にインジケーターコードに宣言されていなくても、すべてのインジケーターに共通です。

NaNの算術演算

インジケーターは、特定の視覚的な出力を生成するために計算を行います。したがって、コードが出力計算における境界条件や極端なケースを正確に処理することが重要です。

以下のコードは、価格乖離オシレーターを出力するインジケーターからの抜粋です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private MovingAverage movingAverage;
protected override void Initialize()
{
    movingAverage = Indicators.SimpleMovingAverage(Source, Periods);
}
public override void Calculate(int index)
{
    Result[index] = Source[<span="n">index] - movingAverage.Result[index - Periods / 2 - 1];
}

上記のコードは、一般的な計算ルールを含んでいますが、境界条件は明示的には示されていません。

例えば、Periods の値が 10 で、index の値が 0-9 の範囲にある場合、計算結果は NaN (Not a Number) になります。インジケーターは、負のインデックスを持つバーのチャートに対して必要な値を計算することができません。この問題に対処するために、次の条件を追加することができます。

1
2
3
4
5
6
7
public override void Calculate<span="p">(int index)
{
    if (index >= Periods + Periods / 2 + 1)
    {
        Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1<span="p">];
    }
}

単純移動平均のコードもまた、index >= Periodsであることを確認する必要があります。さらに、ネストされたインジケーター (例えば、別の種類の移動平均) を使用する場合、この条件は新しい計算を考慮するために異なる必要があります。

境界条件を指定し、極端なケースを探求することができますが、C# ではこの問題を完全に回避する簡単な手段が提供されています。

具体的には、double データタイプはNaN (Not a Number) の算術演算を完全にサポートしています。以下の例を使用してこれを示すことができます。

1
double.NaN + 1.4 == double.NaN

言い換えれば、計算で少なくとも1つの変数がNaNタイプである場合、これらの計算の結果は常にNaNになります。

幸いなことに、すべてのカスタム cTrader インジケーターは DataSeries タイプのデータで動作します。負のインデックスを持つ №DataSeries リストの要素の値を要求する場合、常に NaN を受け取り、その値はトレーディングチャートには表示されません。

インジケーターは例外をスローすることなく正常に動作し続けます。つまり、多くの場合、境界条件を無視して一般的な計算ルールを単に実装することができます。

再帰的インジケーター

NaN の算術演算は境界条件の取り扱いを簡素化しますが、NaN 値を明示的に処理する必要がある状況もあります。再帰的インジケーターはその一例です。

再帰的インジケーターは、特定の値を計算する際に、前の期間に計算された値に基づいて計算を行います。以下は、指数移動平均の計算例です。

 1
 2
 3
<span="normal"> 4
 5
 6
 7
 8
 9
10
11
12
13
public override void Calculate(int index<span="p">)
{
    var previousValue = Result[index - 1<span="p">];

    if (double.IsNaN(previousValue<spanのp">))
    {
        Result<spanのp">[<spanのn">index<spanのp">] <spanのo">= <spanのn">Source<spanのp">[<spanのn">index<spanのp">];
    <spanのp">}
    <spanのk">else
    <spanのp">{
        <spanのn">Result<spanのp">[<spanのn">index<spanのp">] <spanのo">= <spanのn">Source<spanのp">[<spanのn">index<spanのp">] <spanのo">* <spanのn">_exp <spanのo">+ <spanのn">previousValue <spanのo">* <spanのp">(<spanのm">1 <spanのo">- <spanのn">_exp<spanのp">);
    <spanのp">}
<spanのp">}

インジケーターが最初の期間の値を計算する場合、明示的に NaN 以外のタイプに設定する必要があります。そうしないと、今後のすべての期間の計算が NaN となり、インジケーターが無用になります。

上記のコードでは、double.IsNaN(previousValue) メソッドを使用してこれを実現しています。== 演算子 (previousValue == double.IsNan) を使用できないことに注意してください。これは、NaN == x 式が常に false を返すためです。x が NaN である場合でも。

このページについて