
デジタル通貨の定量取引戦略の設計を始めたばかりのときは、さまざまな戦略要件があることがよくあります。使用する言語やプラットフォームに関係なく、さまざまな状況での戦略設計要件に遭遇することになります。たとえば、複数の品種をローテーションする必要がある場合や、複数のプラットフォームをヘッジする必要がある場合、異なる品種を同時に取引する必要がある場合などがあります。戦略的要件を実装する際の設計経験をいくつか共有しましょう。 学習プラットフォームでは引き続き Inventor Quantitative Trading Platform (https://www.fmz.com) が使用され、選択された市場はデジタル通貨市場です。
この種の需要では、多くの場合、多種多様なトレンド戦略、多種多様なグリッド戦略などを作成する必要があり、さまざまな取引ペアを使用して戦略ロジックを繰り返し実行する必要があります。 通常は次のように設計されます。
function Process (symbol) {
exchange.IO("currency", symbol)
var ticker = _C(exchange.GetTicker)
Log("已经切换交易对,按照策略逻辑处理交易对 :", symbol, "行情:", ticker)
// ...
// ..
// .
}
function main(){
var symbols = ["BTC_USDT", "LTC_USDT", "ETH_USDT"]
while (true) {
for (var i = 0 ; i < symbols.length; i++) {
Process(symbols[i])
Sleep(500)
}
}
}
ロボットを設定します。


ご覧のとおり、これにより、ロボット上で交換オブジェクトを構成し、取引ペアを切り替え、さまざまな取引ペアの市場状況を取得し、多種多様な市場状況を実施し、戦略ロジックに従って実行することが可能になります。 定義した3つの取引ペア、BTC_USDT、LTC_USDT、ETH_USDTが、市場情報を取得するためにループ内で順番に反復されていることがわかります。市場情報を取得した後、市場情報を具体的に検出し、設計された取引ロジックをトリガーできます。戦略によって。
生徒の中には、「取引ペアを切り替えるのは好きではありません。少し面倒な感じがするし、戦略設計が明確ではありません。」と言う人もいるかもしれません。 実は他にも設計方法はあるのですが、それは以下で紹介する別の方法です。
複数の取引オブジェクトを通じてさまざまな取引ペアの市場データを取得し、反復戦略ロジックで実行します。
たとえば、ロボットを次のように構成します。ロボットに 3 つの交換オブジェクトを構成し、取引ペアをそれぞれ BTC_USDT、LTC_USDT、ETH_USDT に設定します。

「OKEX Spot V3 Test」という名前の交換オブジェクトは、コントロール センターの交換設定ページにあります。
すでに設定済みです。
今回はロボットに複数の取引所オブジェクト、つまり BTC_USDT、LTC_USDT、ETH_USDT の取引ペアを持つ取引所オブジェクトを追加したので、コードを変更します。
function Process (e) {
var ticker = _C(e.GetTicker)
Log("交易所", e.GetName(), "按照策略逻辑处理交易对 :", e.GetCurrency(), "行情:", ticker)
// ...
// ..
// .
}
function main(){
while (true) {
for (var i = 0 ; i < exchanges.length; i++) {
Process(exchanges[i])
Sleep(500)
}
}
}
ロボットを実行します:

上記の例は、取引ペアを切り替えること、または複数の異なる取引ペアを持つ交換オブジェクトを構成されたアカウントに追加することについてです。 すべては、1 つの Exchange アカウント (構成された Exchange を使用) を使用して構成されます。では、1 つの戦略で複数の取引所アカウントをどのように使用するのでしょうか?
特定の戦略には、たとえば、複数の取引所にまたがるクロスマーケットヘッジ、単一の取引所内でのマルチアカウント戦略などが含まれます。
複数の取引所が設定されていますが、それらは異なる取引所です。
たとえば、コントロール センター -> Exchange -> Exchange の追加ページで 2 つの Exchange を構成しました。
戦略では、これら 2 つの取引所に設定されているアカウントの資産情報にアクセスできます。

function main(){
Log(exchanges[0].GetAccount()) // 打印第一个 交易所对象的账户资产信息,即火币期货 这个交易所的资产信息。
Log(exchanges[1].GetAccount()) // ... 打印Bit-Z这个交易所的资产信息
}
もちろん、2番目と3番目のアカウントの交換設定を交換に追加することもできます。
複数の交換構成は同じ交換です。
たとえば、別のHuobi Futuresアカウントを追加してみましょう。

ご覧のとおり、「Huobi Futures」取引所のアカウントが 2 つ設定されています。

戦略を作成すると、ロボットの「構成の変更」オプションに Huobi Futures Exchange オブジェクトが表示され、選択できるようになります。

たとえば、先に売って後で買うグリッド戦略 (上昇) を使用するアカウントと、先に買って後で売るグリッド戦略 (下降) を使用するアカウントの 2 つを持つことができます。
ロボット上で複数の交換オブジェクトを構成することと、同じ交換アカウントを持つロボットに対して複数の交換オブジェクトを構成することの違いは次のとおりです。
一見すると、これは上で説明した「同じ Exchange アカウントを持つロボットに複数の Exchange オブジェクトを構成する」の例と多少似ていますが、違いもあります。 違いは、上記の例が Exchange 構成であることです。つまり、次のようになります。

ロボットで交換オブジェクトを構成するときは、常に以下を使用します。
この構成。
ただ、取引所オブジェクトを追加する場合、取引ペアの設定が異なります。 GetAccount 関数を呼び出すと、常に同じアカウントの資産情報にアクセスします。
しかし:
このように構成された 2 つの Huobi Futures Exchange オブジェクトは、どちらも Huobi Futures ですが、異なる取引所アカウントを表します。
デジタル通貨契約のヘッジ戦略を実装する場合、一時的な取引機会を捉えるために、多くのシナリオで同時注文が必要になることがあります。ただし、契約内容が異なるため、相場情報を取得したり注文をする際には、対応する契約内容に切り替える必要があります。 exchange.Go 関数を使用して注文機能を同時に実行したり、市場情報を取得したりする場合、同期の問題により速度が遅くなります。また、スイッチング契約の設計により、ロジックはそれほど単純ではないように見えます。では、もっと良い方法はあるのでしょうか?
もちろん方法はあります!上記の「同じ Exchange アカウントを持つロボットに複数の Exchange オブジェクトを構成する」の説明に従って、ロボットに 2 つの Exchange オブジェクトを追加できます。
次に、この交換構成を引き続き使用して、別の交換オブジェクトを追加します。
この時点でプロンプトボックスがポップアップ表示されます。
交換アカウント設定では、同じ通貨と取引ペアを持つ交換オブジェクトを追加できません。
この場合どうすればいいでしょうか?戦略ロボットに 2 つの交換オブジェクトを使用させ、その交換オブジェクトを 1 つの交換アカウント コードにバインドすることはできないようです。 まだ方法はあります!
「コントロール センター」->「取引所」に移動し、OKEX 先物取引所の設定を追加します。

設定後、「保存」をクリックします。

### 「ハイライト」現在、2 つの交換構成がありますが、同じ API KEY 構成情報が使用されています。

これの利点は何ですか? もちろん、戦略を書くときの設計は非常にシンプルです!
function main(){
exchanges[0].SetContractType("quarter") // 设置第一个添加的交易所对象 当前的合约为季度合约
exchanges[1].SetContractType("this_week") // 设置第二个添加的交易所对象,当前的合约为当周合约
while (true) {
var beginTime = new Date().getTime() // 记录这次获取行情时起始的时间戳。
var rA = exchanges[0].Go("GetTicker") // 创建并发 线程去获取 第一个交易所对象,也就是季度合约的行情数据。
var rB = exchanges[1].Go("GetTicker") // 创建并发 线程去获取 第二个交易所对象,也就是当周合约的行情数据。
var tickerA = rA.wait() // 并发的两个线程各自执行自己的任务,这里等待获取数据,A 等待时,B任务也在执行。
var tickerB = rB.wait() // 所以这里看似是顺序执行,实际在底层是并发的。只不过获取的时候是顺序先获取A,在获取B。
var endTime = new Date().getTime() // 记录并发获取两个合约行情结束时的时间戳。
if (tickerA && tickerB) { // 如果获取的数据没有问题,执行以下逻辑。
var diff = tickerA.Last - tickerB.Last // 计算差价
$.PlotLine("diff", diff) // 使用画线类库把差价画在图表上。
if (diff > 500) { // 如果差价大于500, 对冲套利(当然设置500 的差价是比较大的,很少见。)
// 对冲
rA = exchanges[0].Go("Sell", tickerA.Buy, 1) // 并发线程创建 季度合约下卖单
rB = exchanges[1].Go("Buy", tickerB.Sell, 1) // 并发线程创建 当周合约下买单
var idA = rA.wait() // 等待 返回下单结果,返回的是订单ID
var idB = rB.wait() // ...
}
// ...
}
LogStatus(_D(), "并发获取两个合约行情耗时:", endTime - beginTime, "毫秒。") // 显示在状态栏上时间,以便知道程序在执行。
Sleep(500)
}
}
この設計戦略ははるかにシンプルで、アイデアははるかに明確であると感じますか?
実際のディスク操作:

2 つの契約の市場情報を毎回同時に取得するのにかかる時間はわずか 50 ミリ秒程度であることがわかります。