C#および.NETの基本

cBots (自動売買)

C#とは

C#は、さまざまな種類の拡張機能やアプリケーションを構築するために使用できるオブジェクト指向プログラミング言語です。オブジェクト指向言語として、C#はプログラミングの経験がなくても学びやすく、読みやすい言語です。また、コンパクトで再利用可能なコードを記述するための構造化された手段も提供します。

C#は以下の理由から、cBots、プラグイン、およびインディケーターの言語として選ばれています。

  • 浅い学習曲線。C#を使用したことがなくても、最初のボットインディケーターを作成して展開するのに数分しかかかりません。
  • 言語の効率性。C#は使いやすいため、このドキュメントのコードスニペットをすぐに自分のニーズに合わせて書き換えることができます。
  • 広範なクラスライブラリ。C#および.NETを使用すると、事前定義されたクラスとメソッドを含む多数のライブラリにアクセスできます。これらのメソッドは一般的なタスクを効率的に処理できるため、複雑な取引問題の解決に集中できます。
  • 同時実行操作のサポート。C#では、サーバースレッドをブロックせずにコードを記述できます。言い換えれば、特定のタスクを他のタスクと同時に開始することができます。

C#のソースコードを実行するには、中間言語(IL)にコンパイルする必要があります。ILコードは、国際的な共通言語基盤(CLI)仕様への準拠を確保するために必要です。実行中に、ILコードはネイティブマシン命令のセットにコンパイルされます。

.NETとは

.NETは、いくつかのクラスライブラリと共通言語ランタイムに基づく仮想実行システムであり、これはマイクロソフトのCLIの解釈です。技術的な詳細には立ち入りませんが、.NETは次の機能を果たします。

  • アプリケーションの開発と実行の促進.NET SDKにはすでにいくつかの組み込みコンパイラとビルドエンジンが含まれているため、カスタムソリューションを作成する必要はありません。
  • ランタイムライブラリの提供。特定のデータ型やコレクションをコードに追加したい場合、.NETにはすでに対応するクラスとメソッドのセットがある可能性が高いです。

.NETは、トレーディングボットやインディケーターを作成して実行するのに最適な環境だと考えています。

C#の基本

データ型と変数の宣言

データ型は、C#が変数やプロパティをどのように処理するかを正確に知るための手段です。変数やプロパティの宣言では、データ型が常に変数やプロパティ名の前にあります。

1
string developer = "I am developing cBots, plugins, and indicators!";

また、varキーワードを使用してデータ型の指定を省略することもできます。

1
var developer = "I am developing cBots, plugins, and indicators!";

オブジェクトとクラス

オブジェクトは、有形または無形のエンティティの抽象化と考えることができます。これらのエンティティには特定の特性(プロパティ)があり、さまざまな操作(メソッド)を実行できます。クラスはオブジェクトの作成のためのテンプレートとして機能します。

C#はオブジェクト指向言語であるため、クラスは他のクラスからプロパティやメソッドを継承することもできます。次の例では、NewBotクラスがRobotクラスを継承する新しいクラスを宣言し、新しいクラスプロパティを定義しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* クラス継承を指定するためにコロン記号を使用します。
さらに、四角括弧内の表現を使用して、クラス全体に適用されるパラメータを指定します */
[Robot(AccessRights = AccessRights.None)]
public class NewBot : Robot
{
    /* カスタムクラスプロパティを宣言し、読み取り専用にします。 */
    public string CustomProperty { get; }

    /* カスタムパラメータのデフォルト値を宣言します。 */
    [Parameter("BotName", DefaultValue = "Traders First!")]

    /* "BotName"パラメータを介して変更可能なBotNameプロパティを宣言します。 */
    public string BotName { get; }

    /* また、読み取りおよび設定可能なBotCommentパラメータも宣言します。 */
    [Parameter("BotComment", DefaultValue = "Our super-duper bot!")]
    public string BotComment { get; set; }
}

データ型

C#は強く型付けされた言語であるため、変数やクラスプロパティを宣言する際にデータ型を指定する必要があります。簡単に言うと、データ型は異なる一連の動作を持つユニークなクラスを構成します。以下の例では、さまざまなデータ型が異なるクラスプロパティおよび関連するパラメータに指定されています。

1
2
[Parameter("Price")]
public DataSeries Source { get; }

上記のコードでは、DataSeriesデータ型は読み取り専用の値リストを表し、市場価格を表すために一般的に使用されます。

複数のオプションパラメータを作成する必要がある場合は、以下のように組み込みのenumデータ型を使用できます。enumはさまざまな定数を含む特別なクラスと考えることができます。

1
2
3
4
5
6
7
8
9
public enum Option
{
    First,
    Second,
    Third
}
[Parameter("Option", DefaultValue = Option.Third)]
public Option SelectedOption { get; set; }

enumに含まれる定数にアクセスするには、以下の構文を使用します。

1
var newOption = Option.First;

パラメータやプロパティが数値である必要がある場合、int(整数)やdouble(小数)データ型を最も頻繁に使用します。double型はdecimal型よりも精度が低いですが、リソース消費が少ないです。

1
2
[Parameter("MA Periods", DefaultValue = 14, MinValue = 1, MaxValue = 20)]
public int Periods { get; set; }

最後に、bool型は通常「はい/いいえ」入力を表します。「はい」と「いいえ」はそれぞれtruefalseに対応します。

1
2
[Parameter("Message", DefaultValue = true)]
public bool DisplayChartMessage { get; set; }

名前空間

名前空間はクラスの指定されたコレクションとして機能します。一度クラスを名前空間に割り当てると、Namespace.ClassName表記を使用して後でアクセスできます。次の例では、NewBotCoolTradingBots名前空間に割り当てます。

1
2
3
4
5
6
7
8
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ...
    }
}

クラスメソッド

クラスメソッドはクラス宣言に続いて定義されます。NewBotクラスのすべてのオブジェクトはCustomTradeOperation()メソッドを呼び出すことができます。このメソッドはSymbolオブジェクトとdoubleオブジェクトの2つの引数を取ります。このメソッドは、指定されたボリュームでシンボルを取り、何らかの取引アクションを実行することを目的としています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ... クラスパラメータの定義。

        // CustomTradeOperationメソッドを宣言します。
        protected override void CustomTradeOperation(string symbolName, double volume)

        {
            // メソッドロジックの宣言用スペース。
        }
    }
}

クラスライブラリ

クラスライブラリ(およびそれに続くクラスメソッド)は、次の例のように名前空間によってアクセスできます。

1
CoolTradingBots.NewBot.CustomTradeOperation(symbolName, 10000)

また、コードの冒頭にusingキーワードを入力して特定の名前空間を指定し、冗長性を避けることもできます。次のコードスニペットを考えてみてください。

1
2
3
using CoolTradingBots;
NewBot.CustomTradeOperation(symbolName, 10000)

条件文

条件文を使用するには、キーワードの後に丸括弧内に式を記述します。次の例では、ifキーワードを使用してCustomTradingOperation()メソッドを完成させています。これを行うために、Analytics.Actions名前空間で定義されたEvaluateMarket()メソッドを使用しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ... クラスパラメータの定義。

        protected override void CustomTradeOperation(string symbolName, double volume)
        {
            // 'result'変数を宣言して初期化します。
            var result = Analytics.Action.EvaluateMarket();

            // IsSuccessfulプロパティに基づいた条件文を使用します。
            if (result.IsSuccessful)
            {
                Print("Operation successful!")
            }
        }
    }
}

コレクション

コレクションは特定のクラスの1つ以上のオブジェクトを格納できる「コンテナ」として定義されます。

コレクションは完全にインデックス可能であり、整数値を角括弧に渡すことでそのメンバーにアクセスできます。次の例では、Calculate()メソッドがインデックスを介してアクセスされたバーのプロパティを印刷しています。

1
2
3
4
5
public override void Calculate(int index)
{
       var bar = Bars[index];
       Print($"{bar.Open} | {bar.High} | {bar.Low} | {bar.Close}");
}

cTrader拡張機能の作成

以下のスニペットでは、上記のセクションで説明した知識のみを使用して基本的なcBotを作成しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System; 

namespace Spotware.cBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class SuperAwesomeBot : Robot
    {

        /* 以下のメソッドでは、ボットが起動したときに実行する操作を定義します。 */
        protected override void OnStart()
        {
            var result = ExecuteMarketOrder(TradeType.Buy, symbolName, 10000);

            /* TradeResultオブジェクトのIsSuccessfulプロパティを使用して条件文を使用します。 */
            if (result.IsSuccessful)
            {
                var position = result.Position;
                Print ("Position entry price is {0}", position.EntryPrice);
            } 
        }
    }
}

同期および非同期操作

前述のとおり、C#は非同期操作を完全にサポートしています。以下の図は、同期実行で取引活動がどのように行われるかの基本的な例を定義しています。

 
 
 
 
Encounter a Technical Signal
Execute a Market Order
Take Profit/Stop Loss Reached
Close the Position

同期実行には1つの重要な欠点があります。上記の例では、マーケットオーダーの実行操作がすべてのサーバースレッドを完全に占有し、この操作が完了するまでボットが他の何もできなくなります。

これは、市場イベントやボラティリティに迅速に対応したい場合には理想的ではありません。理想的には、ボットはさまざまなアクションを「保存」したり、他の緊急性の高い活動に取り組むために特定のタスクを「保留」することができるべきです。非同期操作がどのように実行されるかをよりよく反映するために、例を拡張します。

 
 
 
 
 
 
Encounter a Technical Signal
Place a ‘Buy’ Order
Place a ‘Sell’ Order for Hedging
An Order Hits Its Take Profit/Stop Loss
Close the Position

上記の例では、ボットは同時に両方向に注文を出し、ポジションのヘッジを行いました。同期操作とは異なり、1つの操作が完了するのを待つ必要はありません。これにより、開発者は効率的で信頼性の高いcBotを作成するための機会が大幅に拡大されます。

非同期実行はマルチスレッドとは異なることに注意してください。

  • 非同期実行では、すべてのタスクが同じスレッドで開始されます。「保存」または「保留」にされると、このスレッドを解放し、後で実行が再開されると、スレッドプールから選択された別のスレッドで実行が行われます。
  • マルチスレッドの場合、すべてのタスクが異なるスレッドで開始され、初期スレッドで実行が継続されます。スレッドの「シャッフル」はありません。

cTraderはメソッドを並行して呼び出すことはないため、マルチスレッドの問題について心配する必要はありません。