コンテンツにスキップ

アルゴリズム取引のためのC#

C#とは

C#は、さまざまなサービスやアプリケーションを構築するために使用されるオブジェクト指向プログラミング言語です。 その明確で構造化された構文は、初心者でも学びやすく読みやすい一方で、コンパクトで再利用可能なコードを書くための構造化されたアプローチを提供します。

1分でC#アルゴリズム!

  • 以前にC#を使用したことがなくても、最初の取引ロボットインジケーターの作成とデプロイにはわずか数分しかかかりません。
  • C#は使いやすいため、このドキュメントのコードスニペットを迅速に書き換えてニーズに合わせることができます。
  • C#を使用すると、事前定義されたクラスとメソッドを含む多数のライブラリにアクセスできます。 これらのメソッドは一般的なタスクを効率的に処理するため、複雑な取引問題の解決に集中できます。
  • C#では、実行時にサーバースレッドをブロックしないコードを書くことができます。 言い換えると、他のタスクと同時に特定のタスクを開始できます。

.NETとは?

C#プログラムを実行するには、そのソースコードを中間言語(IL)にコンパイルする必要があります。 このILコードは共通言語基盤(CLI)仕様に従い、実行時にネイティブマシン命令にコンパイルされます。 .NETフレームワークは、広範なクラスライブラリと共通言語ランタイム(CLR)、MicrosoftのCLI実装に基づく仮想実行環境を提供します。

技術的な詳細に立ち入らずに、.NETは以下の機能を果たします:

  • アプリケーションの開発と実行を容易にする:.NET SDKには既にいくつかの組み込みコンパイラとビルドエンジンが含まれており、カスタムソリューションを作成する必要がありません。
  • ランタイムライブラリを提供する:新しいデータ型やコレクションをコードに追加する際、.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#はオブジェクト指向言語であるため、クラスは他のクラスからプロパティとメソッドを継承することもできます。 以下の例を考えてみましょう。ここでは、Robot クラスを継承する新しい NewBot クラスを宣言しています。 また、いくつかの新しいクラスプロパティも定義しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* We use the colon sign to designate inheritance.
Additionally, we used expressions in square brackets to
specify the parameters that apply to the entire class */
[Robot(AccessRights = AccessRights.None)]
public class NewBot : Robot
{
    /* We declare a custom class property and make it
    read-only. */
    public string CustomProperty { get; }

    /* In this declaration, we define the default value of a
    custom parameter. */
    [Parameter("BotName", DefaultValue = "Traders First!")]

    /* We declare the BotName property which is changeable via
    the "BotName" parameter. */
    public string BotName { get; }

    /* We also declare the BotComment parameter.
    It can be both read and set. */
    [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
    {
        // ... Defining the class parameters.

        // We declare the CustomTradeOperation method. 
        protected override void CustomTradeOperation(string symbolName, double volume)

        {
            // This space is for declaring the method logic. 
        }
    }
}

クラスライブラリ

クラスライブラリ(およびクラスメソッド)は、以下の例に示すように名前空間でアクセスできます。

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
    {
        // ... Defining the class parameters.

        protected override void CustomTradeOperation(string symbolName, double volume)
        {
            // We declare and initialize the 'result' variable.
            var result = Analytics.Action.EvaluateMarket();

            // We use a conditional statement based on the IsSuccessful property.
            if (result.IsSuccessful)
            {
                Print("Operation successful!")
            }
        }
    }
}

コレクション

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

コレクションは完全にインデックス可能であり、そのメンバーは角括弧内に特定のinteger値を渡すことでアクセスできます。 以下の例では、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拡張機能の作成

以下のスニペットでは、上記のセクションでカバーした知識のみを使用して基本的な取引ロボットを作成します。

 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
    {

        /* In the below method, we define the operation(s) that our bot should
        perform when it is launched. */
        protected override void OnStart()
        {
            var result = ExecuteMarketOrder(TradeType.Buy, symbolName, 10000);

            /* We use a conditional statement using the IsSuccessful property of the
            TradeResult object. */
            if (result.IsSuccessful)
            {
                var position = result.Position;
                Print ("Position entry price is {0}", position.EntryPrice);
            } 
        }
    }
}

同期および非同期操作

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

graph TD
    A(テクニカルシグナルに遭遇) ==> B(成行注文を実行) 
    B ==> C(利食い/損切りに到達) 
    C ==> D(ポジションを決済)
    D ==> A

同期実行には1つの重要な欠点があります。 上記の例では、市場注文を実行するアクションがすべてのサーバースレッドを完全に占有するため、この操作が完了する前に取引ロボットが他のことを行うことができません。

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

graph TD
    A([テクニカルシグナルを検出]) ==> B([買い注文を出す]) & C([ヘッジのために売り注文を出す]) ==> D([注文が利食い/損切りに到達]) 
    D ==> E([ポジションを決済])
    E ==> A

上記の例では、取引ロボットが両方向に注文を同時に配置してポジションをヘッジしました。 同期操作とは対照的に、1つの操作が完了するのを待ってから次の操作に進む必要はありません。 これにより、効率的で信頼性の高い取引ロボットを作成するための開発者の機会が大幅に拡大します。

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

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

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

Image title