このチュートリアルでは、JSONメッセージの送受信方法について説明します。
TCPとWebSocket
JSONを使用する場合、TCP接続またはWebSocket接続のいずれかを使用できます。
JSONの送信¶
統合でJSONを使用する場合、有効なJSONを含む文字列をcTraderバックエンドに送信する必要があります。これらの文字列として渡されるJSONオブジェクトには、次のキーを含める必要があります。
キー | 値のデータ型 | 定義 |
---|---|---|
"clientMsgId" | string | メッセージの一意のID。このIDはクライアント側で生成および割り当てる必要があります。 |
"payloadType" | integer | メッセージのメッセージを表す整数。有効なペイロードタイプの完全なリストはProtoOAPayloadType に含まれています。 |
"payload" | JSONオブジェクト | メッセージの実際の内容を含むネストされたJSONオブジェクト。 |
有効な文字列の例(ProtoOAApplicationAuthReq
メッセージを表す)は以下に示されています。
"{"clientMsgId": "cm_id_2", "payloadType": 2100, "payload": {"clientId": "34Rsd_T098asHkl","clientSecret": "validClientSecret"}}"
正しいJSON文字列を送信するには、選択したプログラミング言語で独自のシリアル化メカニズムを作成する必要があります。
以下の例では、シリアル化の処理方法をいくつか定義しています。好みのプログラミング言語や設計パターンに応じて、独自の方法を実装することができます(またはすべきです)。
以下では、2つの基本クラスを定義し、次にProtoOAApplicationAuthReq
メッセージのカスタム表現を作成します。
public abstract class OpenAPIMessageBase
{
public string ClientMsgId { get; set; }
public abstract int PayloadType { get; }
}
public abstract class OpenAPIMessagePayloadBase { }
public class ApplicationAuthReq : OpenAPIMessageBase
{
public ApplicationAuthReq() { }
public ApplicationAuthReq(string clientId, string clientSecret)
{
this.Payload = new ApplicationAuthReqPayload(clientId, clientSecret);
this.ClientMsgId = Guid.NewGuid().ToString();
}
public override int PayloadType => 2100;
public ApplicationAuthReqPayload? Payload { get; set; }
}
public class ApplicationAuthReqPayload : OpenAPIMessagePayloadBase
{
public ApplicationAuthReqPayload() { }
public ApplicationAuthReqPayload(string clientId, string clientSecret)
{
this.ClientId = clientId;
this.ClientSecret = clientSecret;
}
public string ClientId { get; set; } = string.Empty;
public string ClientSecret { get; set; } = string.Empty;
}
すべてのOpen APIメッセージ用の基本クラスを作成し、デモンストレーション目的でProtoOAApplicationAuthReq
のクラスを定義します。
import uuid
import json
class OpenAPIMessage:
def payloadType(self):
pass
def payload(self):
pass
def clientMsgId(self):
pass
def asJsonString(self):
pass
class ApplicationAuthReq(OpenAPIMessage):
def __init__(self, clientId, clientSecret, clientMsgId = str(uuid.uuid4())):
self.clientId = clientId
self.clientSecret = client_secret
self.payloadType = 2100
self.clientMsgId = clientMsgId
self.payload = {"clientId": self.clientId, "clientSecret": self.clientSecret}
def asJsonString(self):
return json.dumps({"clientMsgId": self.clientMsgId, "payloadType": self.payloadType, "payload": self.payload})
必要なロジックを実装した後、新しいメッセージをcTraderバックエンドに送信するには、これらのメッセージを表すクラスの新しいインスタンスを作成し、それらを選択したTCPまたはWebSocketクライアントに渡す必要があります。
JSONの受信¶
JSONメッセージを受信して処理するには、JSON文字列をOpen APIメッセージの表現にデシリアライズするメソッドを実装する必要があります。
このメソッドを実装する際には、ペイロードタイプをキーとし、メッセージを表すクラスの名前を値として持つマップ(または辞書)を初期化すると便利です。例外処理の目的で、受信したメッセージのペイロードタイプがこのマップまたは辞書のキーであるかどうかを検証することが望ましい場合があります。そのようなキーが存在する場合は、適切なロジックを使用してメッセージをデシリアライズできます。
このようなメソッドを実装した後は、新しいメッセージを受信するたびにトリガーされるコールバックとして使用できます。
以下の例では、TMessage
はジェネリック型であることに注意してください。
public static class MessageReceivedCallbacks
{
public static Dictionary messages = new Dictionary
{
{2100, typeof(ApplicationAuthReq) },
};
public static TMessage ReadMessage(string jsonString) where TMessage : OpenAPIMessageBase
{
JsonDocument doc = JsonDocument.Parse(jsonString);
int payloadType = doc.RootElement.GetProperty("payloadType").GetInt32();
if (!messages.TryGetValue(payloadType, out var type))
throw new Exception("This payload type is not supported");
var result = JsonSerializer.Deserialize(jsonString, type) as TMessage;
return result;
}
}
ダウンキャスト
ReadMessage()()
メソッドは実際には特定のメッセージクラスを返しません。メッセージを受信する際には、ダウンキャストを個別に処理する必要があります。
次に、ApplicationAuthReq
クラスに以下のメソッドを追加します。
@staticmethod
def fromJson(jsonDct):
return ApplicationAuthReq(clientId=jsonDct['payload']['clientId'], clientSecret=jsonDct['payload']['clientSecret'], clientMsgId=jsonDct['clientMsgId'])
次に、readMessage
コールバックを追加し、辞書からペイロードを取得します。
class MessageReceivedCallbacks:
messagesDict = {2100: ApplicationAuthReq}
@staticmethod
def readMessage(jsonString):
json_dct = json.loads(jsonString)
payloadType = jsonDct['payloadType']
return MessageReceivedCallbacks.messagesDict[payloadType].fromJson(jsonDct)
ダウンキャスト
Pythonはダックタイピングを採用しているため、ダウンキャストを個別に処理する必要はありません。受信時にJSON文字列を必要な型に直接デシリアライズできます。