高周波戦略を紹介する記事を書きましたhttps://www.fmz.com/bbs-topic/9750. 注目が集まっていたが,あまり深くなかった. それ以来2年以上経ち,市場は変化している. その記事が発表された後,私の高周波戦略は長い間安定した利益を得ることができましたが,徐々に利益は低下し,ある時点で停止しました. 最近数ヶ月間,それをリニューアルするためにいくつかの努力を費やし,現在まだいくつかの利益を得ることができます. この記事では,私の高周波戦略のアイデアといくつかの簡略化されたコードを議論の出発点としてより詳細な紹介を提供します. 意見は歓迎されています.
割引口座は,Binanceを例として挙げると,現在,メーカーの割引額は0.0005%である.日々の取引額が1億円である場合,割引額は5000円になります.もちろん,テイカー料金は依然としてVIP料金をベースにしているため,戦略にテイカーが必要でない場合,VIPレベルは高頻度戦略にほとんど影響しません.異なるレベルの取引所には一般的に異なる割引額があり,高い取引額を維持する必要があります.一部の通貨市場が大きく変動した初期には,割引なしでも利益がありました.競争が激化するにつれて,割引金は利益の大きな割合を占めたり,またはそれらにのみ依存していたりします.高頻度トレーダーはトップレベルの手数料を追求しました.
スピード.高周波戦略が高周波と呼ばれる理由は,非常に高速であるためです. 交換のコロサーバーに接続し,最低のレイテンシーと最も安定した接続を取得することは,内部競争の条件の一つになりました. 戦略の内部消費時間はできるだけ少なくなければなりません. この記事では,同時実行を採用する私が使用するwebsocketフレームワークを紹介します.
適正な市場.高周波取引は定量的な取引の真珠として知られており,多くのプログラムトレーダーは試してきたが,ほとんどの人は利益を得ることができず,改善の方向性を見つけられないため停止した.主な理由は,間違った取引市場を選んだことにあるはずです.戦略開発の初期段階では,取引で利益を得るために比較的簡単な市場を選ばなければなりません.それによって利益と改善のためのフィードバックがあり,戦略の進展に有利です.あなたが多くの潜在的なライバルと最も競争力のある市場で競争し始めると,あなたがどれだけ努力してもすぐにお金を失うし,諦めるでしょう.競合他者がそれほど多くないとき,特に取引額が比較的大きいとき,新しい永続契約取引ペアを推奨します.これが利益を得ることが最も簡単です. BTCとETHは取引額が最も多く,取引が最も活発ですが,生き残るのは難しいです.
競争に直面する.どんな取引も市場が絶えず変化しており,特に高周波取引では,いかなる取引戦略も永遠に続くことはできません.この市場に参入することは,最も賢くて勤勉なトレーダーと直接競争することを意味します.ゼロサムゲーム市場で,あなたが稼ぐほど,他の人々が稼ぐほど少なくなります.あなたが遅く入るほど,難易度は高くなります.すでに市場にいる人も継続的に改善する必要があります. 3-4年前はおそらく最高の機会でした.最近,デジタル通貨市場の全体的な活動は減少しており,新規参入者が現在高周波取引を開始することは非常に困難です.
高周波の戦略には様々な種類があります.
次のコードは,ベナンス永久契約の基本的なフレームワークに基づいています.主にwebソケット深さ,深度オーダーフロー取引市場データ,位置情報に購読しています.市場データとアカウント情報が別々に購読されているため,最新の情報が取得されているかどうかを確認するために継続的にread ((-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 are the set trading pairs
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)
}
}
先ほど述べたように,私の高周波戦略は,買い物・販売を実行する前にトレンドを決定する必要があります. 短期トレンドは主に,取引方向,価格,量,取引時間などを含む購読中のaggTrade,ティック・バイ・ティック取引データに基づいて判断されます. 買い物・販売は主に深さと取引額を指します. 以下は,懸念すべき指標の詳細な紹介です. ほとんどの指標は買い物・販売グループに分かれ,一定の時間枠内で動的にカウントされます. 私の戦略の時間枠は10秒以内です.
//bull represents short-term bullish, bear represents short-term bearish
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コインが取引可能であると仮定して,販売価格は10コインが購入される位置に設定されます. 時間の窓の特定のサイズは自分で設定する必要があります.
let buy_amount = Ratio * avg_sell_amount / avg_sell_time
let sell_amount = Ratio * avg_buy_amount / avg_buy_time
Ratio は固定比例を表す.つまり,購入注文量は,最近の販売注文量の固定比例である.この方法により,戦略は,現在の購入および販売活動に応じて順応的に注文サイズを調整することができます.
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 は平均市場価格の差であり,バイド・アスク・スプレッドがこの値の一定倍数よりも大きく,上昇傾向にある場合にのみ購入オーダーが行われます.ショートポジションを保持すると,長期にわたって保持を避けるため,ポジションも閉鎖されます.オーダーが実行されることを保証するために,単一のメーカーオーダーとして配置できます.さらに,Binance
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)//Unreturned tasks will continue to wait next time
}
})
jobs = new_jobs
tasks = []
}
/*
Write the required task parameters in param
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() +"×tamp="+Date.now()]})
*/