暗号通貨の詳細な高周波取引戦略の紹介

作者: リン・ハーン発明者の量化, 作成日:2023-03-19 19:56:11, 更新日:2023-09-18 19:55:58

img

高周波取引戦略を紹介する記事を書きました (https://www.fmz.com/digest-topic/6228) にもかかわらず,少しの注目を集めましたが,あまり深くありませんでした.それ以来2年半が経過し,市場は変わりました.私がその記事を掲載した後,私の高周波戦略は長い間安定した利益を得ることができましたが,利益は徐々に低下し,一度停止しました.最近数ヶ月間,私はそれをリニューアルするのに時間を費やし,まだいくつかの小さな利益を得ることができます.この記事は私の高周波取引戦略といくつかの簡易化されたコードについてより詳細な紹介を提供し,議論とフィードバックの出発点として機能します.

高周波取引の条件

割引口座

Binanceを例として挙げると,現在取引される10万ユニットごとに0.05%のメーカーの割引を提供しています. 日々の取引量が1億Uであれば,割引は5,000Uです. もちろん,テイカー料金は依然としてVIPレートに依存しているため,戦略が注文を受け入れる必要がない場合,VIPレベルは高周波戦略にほとんど影響しません. 異なる取引所で異なるレベルの割引が利用可能で,高い取引量が求められます. 初期には,割引なしで利益を得ることはまだありましたが,競争が激化するにつれて,割引は利益の大きな割合を占め,高周波トレーダーはトップレートを追求しました.

スピード

高周波取引は,高速な速度のためにそう呼ばれている.取引取引所のコロケーションサーバに加わり,最も低い遅延と最も安定した接続を得ることは競争条件の1つになった.戦略の内部処理時間もできるだけ短くする必要があります.この記事では,同時実行を使用する私が使用したWebSocketフレームワークを紹介します.

適した市場

高周波取引は定量取引の宝石とみなされ,多くのアルゴリズムトレーダーは試したと思いますが,ほとんどの人はお金を稼げず,改善する方法を見つけることができなかったため,やめるべきだったと思います.主な理由はおそらく間違った取引市場を選んだからです.戦略の初期段階では,比較的簡単な市場が利益を得るために取引をターゲットにされ,改善のためのフィードバックを受けなければなりません.これは戦略の進歩に有利です.あなたが最も激烈な競争力のある市場でスタートし,多くのライバルと競争するなら,あなたがどれだけ努力してもお金を失うでしょう.そしてあなたはすぐに諦めます.私は,比較的大きな取引量を持つ競争者が少ない,特に取引量が少ない,お金を稼ぐことを容易にする,新しく開始された永続契約取引ペアから始めることをお勧めします. BTCとETHは最も高い取引量と最も活発ですが,生存することも最も困難です.

競争相手と対決する

取引の市場は常に変化しており,取引戦略は一度の解決策であることはできません.これは,市場に入ることは最も賢くて勤勉なトレーダーと直接競争することを意味する高周波取引において,さらに明らかです.ゼロサムゲーム市場で,あなたが稼ぐほど,他の人々が稼ぐほど少なくなります.あなたが遅く入るほど,それは難しくなり,すでに市場に入っている人は常に改善し,いつでも排除される必要があります. 3〜4年前はおそらく最高の機会でしたが,デジタル通貨市場の活動が最近全体的に減少しているため,初心者が高周波取引を始めることは非常に困難になりました.

高周波取引の原則

高周波トレード戦略には,このまたは他の取引所を通じて仲介機会を見つけ,他の取引所よりも先に注文を食べ,スピードメリットで利益を得る機会を掴むことを含む高周波仲介などいくつかの高頻度トレード戦略があります.短期トレンドから利益を得ることを含む高頻度トレンドトレード,および売買取引の両側に注文を置き,ポジションを適切に制御し,佣金割引を通じて利益を得ることを含むマーケットメーキングがあります.私の戦略はトレンドとマーケットメーキングを組み合わせ,まずトレンドを特定し,その後注文を配置し,実行後にすぐに販売し,在庫ポジションを保持しません.以下は戦略コードの紹介です.

戦略建築

次のコードは,バイナンス永久契約の基本アーキテクチャに基づい,主にwebsocketの深度オーダーフロー取引とポジション情報にサブスクリプトしている.市場データとアカウント情報が別々にサブスクリプトされているため,最新の情報が取得されているかどうかを判断するために,読み (-1) を継続的に使用する必要があります.ここで,EventLoop (1000) は直接デッドループを回避し,システム負荷を削減するために使用されます.EventLoop (1000) は1000msのタイムアウトでwssまたは同時タスクリートがあるまでブロックします.

var datastream = null
var tickerstream = null
var update_listenKey_time = 0

function ConncetWss(){
    if (Date.now() - update_listenKey_time < 50*60*1000) {
        return
    }
    if(datastream || tickerstream){
        datastream.close()
        tickerstream.close()
    }
    // need APIKEY
    let req = HttpQuery(Base+'/fapi/v1/listenKey', {method: 'POST',data: ''}, null, 'X-MBX-APIKEY:' + APIKEY) 
    let listenKey = JSON.parse(req).listenKey
    datastream = Dial("wss://fstream.binance.com/ws/" + listenKey + '|reconnect=true', 60)
    // Symbols is the pair of symbol
    let trade_symbols_string = Symbols.toLowerCase().split(',')
    let wss_url = "wss://fstream.binance.com/stream?streams="+trade_symbols_string.join(Quote.toLowerCase()+"@aggTrade/")+Quote.toLowerCase()+"@aggTrade/"+trade_symbols_string.join(Quote.toLowerCase()+"@depth20@100ms/")+Quote.toLowerCase()+"@depth20@100ms"
    tickerstream = Dial(wss_url+"|reconnect=true", 60)
    update_listenKey_time = Date.now()
}

function ReadWss(){
    let data = datastream.read(-1)
    let ticker = tickerstream.read(-1)
    while(data){
        data = JSON.parse(data)
        if (data.e == 'ACCOUNT_UPDATE') {
            updateWsPosition(data)
        }
        if (data.e == 'ORDER_TRADE_UPDATE'){
            updateWsOrder(data)
        }        
        data = datastream.read(-1)
    }
    while(ticker){
        ticker = JSON.parse(ticker).data
        if(ticker.e == 'aggTrade'){
            updateWsTrades(ticker)
        }
        if(ticker.e == 'depthUpdate'){
            updateWsDepth(ticker)
        }
        ticker = tickerstream.read(-1)
    }
    makerOrder()
}

function main() {
    while(true){
        ConncetWss()
        ReadWss()
        worker()
        updateStatus()
        EventLoop(1000)
    }
}

戦略指標

先ほど述べたように,私の高周波戦略は,まず買い売り取引を実行する前にトレンドを特定する必要があります.短期トレンドを判断するのは,主に取引データ,すなわち,方向,価格,量,取引時間を含むアグトレードサブスクリプトに基づいています.買い売り取引は主に深さと取引量を指します.以下の詳細な指標は考慮する必要があります.その多くは買い売りのために2つのグループに分けられ,特定の時間枠内で動的にカウントされます.私の戦略の時間枠は10秒以内です.

  • トランザクション1回の平均取引量は,同じ方向,価格,および100ms以内に異なるオーダーの取引の集合である.これは購入および販売オーダーのサイズを反映し,高い重量を持っています.購入オーダーの取引量が販売オーダーの量よりも大きい場合,市場は買い手によって支配されていると仮定することができます.
  • オーダー頻度またはオーダー間隔,また取引データに基づいている.以前の平均取引量は時間概念を考慮していないため,完全に正確ではありません.一方向のオーダーは平均取引量が小さいが頻度が高い場合,その方向の強さに貢献します.平均取引量は * 注文頻度は,一定の間隔で全体の取引量を表現し,直接比較するために使用できます.オーダー到着イベントは,特定の時間間隔内で総注文価値がどのくらいに達するかを推定するために使用できるポイソン分布に従います.
  • 平均的なスプレッド,これは販売価格と購入価格の差です.現在のスプレッドは主に1つのティックで,スプレッドが増加すると,傾向があることを示します. 平均的な買取価格と販売価格,それぞれの買取と販売取引の平均価格を計算し,最新の価格と比較する.最新の買取注文価格が平均的な買取注文価格よりも高い場合,突破は予備的に判断することができます.

戦略の論理

短期 的 な 傾向 を 判断 する

let bull =  last_sell_price > avg_sell_price && last_buy_price > avg_buy_price &&
            avg_buy_amount / avg_buy_time > avg_sell_amount / avg_sell_time;
let bear =  last_sell_price < avg_sell_price && last_buy_price < avg_buy_price && 
            avg_buy_amount / avg_buy_time < avg_sell_amount / avg_sell_time;

最新のオード価格が平均オード価格より高く, 最新のオード価格が平均オード価格より高く, 決まった間隔で購入オーダーの価値が販売オーダーの価値より高くなった場合, 短期的な上昇市場と判断されます.

オーダーを出すこと

function updatePrice(depth, bid_amount, ask_amount) {

    let buy_price = 0
    let sell_price = 0
    let acc_bid_amount = 0
    let acc_ask_amount = 0

    for (let i = 0; i < Math.min(depth.asks.length, depth.bids.length); i++) {
        acc_bid_amount += parseFloat(depth.bids[i][1])
        acc_ask_amount += parseFloat(depth.asks[i][1])
        if (acc_bid_amount > bid_amount  && buy_price == 0) {
            buy_price = parseFloat(depth.bids[i][0]) + tick_size
        }
        if (acc_ask_amount > ask_amount  && sell_price == 0) {
            sell_price = parseFloat(depth.asks[i][0]) - tick_size
        }
        if (buy_price > 0 && sell_price > 0) {
            break
        }
    }
    return [buy_price, sell_price]
}

ここで,必要な量に深さを繰り返す古い方法はまだ使用されています. 1秒以内に10コインで実行できる購入注文を仮定し,新しい注文の状況を考慮せずに,販売価格は購入注文が実行される位置に設定されます.

特定の時間ウィンドウのサイズを自分で設定する必要があります.

注文量

let buy_amount = Ratio * avg_sell_amount / avg_sell_time
let sell_amount = Ratio * avg_buy_amount / avg_buy_time

この比率は,最新の販売注文量に対する固定比率を表し,購入注文量に対する最新の販売注文量に対する固定比率を表します.これは,戦略が現在の購入および販売活動に応じて注文サイズを調整することを可能にします.

注文条件

if(bull && (sell_price-buy_price) > N * avg_diff) {
    trade('buy', buy_price, buy_amount)
}else if(position.amount < 0){
    trade('buy', buy_price, -position.amount)
}
if(bear && (sell_price-buy_price) >  N * avg_diff) {
    trade('sell', sell_price, sell_amount)
}else if(position.amount > 0){
    trade('sell', sell_price, position.amount)
}

Avg_diffは,スプレッドの平均差であり,購入と販売の差がこの値の一定倍数よりも大きく,市場が上昇している場合にのみ,購入オーダーが表示されます.ショートポジションを保持した場合,ポジションを長期にわたって保持しないためにポジションも閉鎖されます.オーダーが満たされることを保証するために,オーダーメーカーのオーダーのみを配置することができ,オーダーリターンの待機を避けるためにカスタムオーダーIDを使用できます.

同期建築

var tasks = []
var jobs = []

function worker(){
    let new_jobs = []
    for(let i=0; i<tasks.length; i++){
        let task = tasks[i]
        jobs.push(exchange.Go.apply(this, task.param))
    }
    _.each(jobs, function(t){
        let ret = t.wait(-1)
        if(ret === undefined){
            new_jobs.push(t)//未返回的任务下次继续等待
        }
    })
    jobs = new_jobs
    tasks = []
}

/*
tasks.push({'type':'order','param': ["IO", "api", "POST","/fapi/v1/order",
        "symbol="+symbol+Quote+"&side="+side+"&type=LIMIT&timeInForce=GTX&quantity="+
        amount+"&price="+price+"&newClientOrderId=" + UUID() +"&timestamp="+Date.now()]})
*/

監視データ

  • 遅延:高周波取引戦略のスピードの重要性が強調されている.戦略は,注文の提出,注文のキャンセル,返済ポジション,深さ,注文流量,全体的なサイクルなど,さまざまな遅延を監視し記録する必要があります.異常な遅延は直ちに調査され,全体的な戦略の遅延を短縮する方法を見つけなければなりません.
  • 取引量の比率: 統計によると,取引量の比率は,取引総量に相当する.その比率が低い場合,改善の余地がある.ピーク時に,戦略の比率は,取引総量の10%以上に達する可能性があります.
  • 決済利回り: 統計は決済利回りの平均を示し,戦略の有効性を判断する上で最も重要な基準です.
  • 割引比率: 統計は,割引が総収益に占める割合を示し,戦略が割引に依存する程度を反映する. 異なる取引所は割引レベルが異なります.利益を得ない戦略は,より高い割引レベルで利益を得ることができます. オーダー失敗率:オーダーのみを配達し,完了するが,配達が遅れるため,完了しない可能性がある.この比率が高くなった場合,戦略のスピードが最適ではないことを示している.
  • オーダー実行比:プラットフォームにはしばしばオーダー実行比の要件があります.低すぎると,戦略がオーダーを頻繁にキャンセルしていることを示し,解決する必要があります. 平均的な買取・販売注文距離:このデータは,戦略の注文の配置と市場深さの距離を反映しており,ほとんどの注文はまだ買取・販売注文の位置を占めています.

他 の 提案

  • 複数の通貨を取引する:この記事における高周波戦略は,単一の取引所,単一の通貨ペア,および単一の市場条件に限定されており,適用可能性が限られている.ほとんどの通貨は利益を得ることはできないが,将来的にどの通貨が利益を得るか予測することは不可能であるため,機会を逃さないために複数の通貨またはすべての通貨を取引することを推奨する.交換の頻度制限の下でさえ,単一のロボットは複数の取引ペアを取引することができます.もちろん,最高の速度のために,1つのサブアカウントは1つの取引ペア,1つのサーバーは1つのロボットに対応しますが,このアプローチははるかに高いコストを伴います.
  • 収益性に基づいて注文サイズと条件を決定する.複数の通貨の取引は,試すコストがあまりにも高くなる可能性があるため,モニタリングが収益性がないことを示している場合は,取引頻度を減らして,戦略が動的にポジティブな利益率を検出するまで最小取引量を使用し,収益性を向上させるために徐々に取引量を増加します.
  • より多くの情報を取得する:高周波取引のもう一つの特徴は,より多くのデータを処理し,より多くの情報を使用することです.単一の取引所および通貨ペアのすべての市場データが考慮されるべきであり,永続データはまた,他の取引所または他の通貨の同じ通貨ペアのスポットデータまたはデータにも言及することができます.より多くのデータ,対応するメリットが大きいほどです.例えば,Binanceは,Binanceの取引サイトを購読することができます.

関連性

もっと