戦略設計の初心者にとって,ヘッジ戦略は非常に良い練習戦略です. この記事では,シンプルで実用的なデジタル通貨の現金ヘッジ戦略を実装し,初心者にいくつかの設計経験を学ぶことを望みます.
まず,この策略がデジタル通貨現金ヘッジ戦略であることを明確にするために,我々は最も簡単なヘッジを設計し,二つの現金取引所の間で高い価格で取引所のみを売却し,低価格で取引所のみを購入し,差額を稼ぎます. 高価格の取引所はすべてコインであるときに (高価格のコインがすべて売られているため),低価格の取引所はすべてコインであるときに (低価格のコインがすべて購入されているため),ヘッジはできません.
ハージング時に下注する価格,数量,取引所には精度制限があり,最小下注量制限もある.最小下注量制限以外の戦略は,ヘッジング時に最大下注量も考慮し,下注量が大きすぎると十分な注文量も持たない.また,2つの取引所が異なる通貨を計算した場合の為替レートの変換方法も考慮する必要がある.
戦略は,いくつかのパラメータを設計する必要があります.
hedgeDiffPrice
この値を超えると,ヘッジ操作を誘発します.minHedgeAmount
負債の負債は,負債の負債の負債として,負債の負債として,負債の負債として,負債の負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として.maxHedgeAmount
負債の負債は,負債の負債の負債として,負債の負債として,負債の負債として,負債の負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として.pricePrecisionA
A取引所からの注文価格の精度 (小数値)amountPrecisionA
A取引所下位単位の精度 (小数位) 〔a〕pricePrecisionB
取引所Bの注文価格の精度 (小数値)amountPrecisionB
B取引所下位単位の精度 (小数位)rateA
,最初の追加された取引所のオブジェクトの為替換算は,デフォルトで1は変換されません.rateB
,第2の追加された取引所のオブジェクトの為替換,デフォルト1は変換されません.ヘッジ戦略は,両口座のコインの数を常に不変に保つ必要がある (すなわち,いかなる方向のポジションも保持せず,中立である) のため,戦略には,常にバランスを検知するバランス論理が必要である.バランスを検知する際には,両取引所の資産データを入手することから逃れる.我々はそれを使用するために関数を書く必要がある.
function updateAccs(arrEx) {
var ret = []
for (var i = 0 ; i < arrEx.length ; i++) {
var acc = arrEx[i].GetAccount()
if (!acc) {
return null
}
ret.push(acc)
}
return ret
}
オーダーが完成していない場合,オーダーを一時的に取り消す必要があります. この操作はバランスモジュールやヘッジロジックの両方で処理する必要があります. そのため,オーダーを完全に取り消す関数を設計する必要があります.
function cancelAll() {
_.each(exchanges, function(ex) {
while (true) {
var orders = _C(ex.GetOrders)
if (orders.length == 0) {
break
}
for (var i = 0 ; i < orders.length ; i++) {
ex.CancelOrder(orders[i].Id, orders[i])
Sleep(500)
}
}
})
}
平衡コイン数では,ある深度データの中で,あるコイン数に累積する価格を探さなければなりません.
function getDepthPrice(depth, side, amount) {
var arr = depth[side]
var sum = 0
var price = null
for (var i = 0 ; i < arr.length ; i++) {
var ele = arr[i]
sum += ele.Amount
if (sum >= amount) {
price = ele.Price
break
}
}
return price
}
特定のヘッジの下記の操作を設計し,並行下記の操作として設計する必要があります.
function hedge(buyEx, sellEx, price, amount) {
var buyRoutine = buyEx.Go("Buy", price, amount)
var sellRoutine = sellEx.Go("Sell", price, amount)
Sleep(500)
buyRoutine.wait()
sellRoutine.wait()
}
そして最後に,平衡関数の設計を完了します.
function keepBalance(initAccs, nowAccs, depths) {
var initSumStocks = 0
var nowSumStocks = 0
_.each(initAccs, function(acc) {
initSumStocks += acc.Stocks + acc.FrozenStocks
})
_.each(nowAccs, function(acc) {
nowSumStocks += acc.Stocks + acc.FrozenStocks
})
var diff = nowSumStocks - initSumStocks
// 计算币差
if (Math.abs(diff) > minHedgeAmount && initAccs.length == nowAccs.length && nowAccs.length == depths.length) {
var index = -1
var available = []
var side = diff > 0 ? "Bids" : "Asks"
for (var i = 0 ; i < nowAccs.length ; i++) {
var price = getDepthPrice(depths[i], side, Math.abs(diff))
if (side == "Bids" && nowAccs[i].Stocks > Math.abs(diff)) {
available.push(i)
} else if (price && nowAccs[i].Balance / price > Math.abs(diff)) {
available.push(i)
}
}
for (var i = 0 ; i < available.length ; i++) {
if (index == -1) {
index = available[i]
} else {
var priceIndex = getDepthPrice(depths[index], side, Math.abs(diff))
var priceI = getDepthPrice(depths[available[i]], side, Math.abs(diff))
if (side == "Bids" && priceIndex && priceI && priceI > priceIndex) {
index = available[i]
} else if (priceIndex && priceI && priceI < priceIndex) {
index = available[i]
}
}
}
if (index == -1) {
Log("无法平衡")
} else {
// 平衡下单
var price = getDepthPrice(depths[index], side, Math.abs(diff))
if (price) {
var tradeFunc = side == "Bids" ? exchanges[index].Sell : exchanges[index].Buy
tradeFunc(price, Math.abs(diff))
} else {
Log("价格无效", price)
}
}
return false
} else if (!(initAccs.length == nowAccs.length && nowAccs.length == depths.length)) {
Log("错误:", "initAccs.length:", initAccs.length, "nowAccs.length:", nowAccs.length, "depths.length:", depths.length)
return true
} else {
return true
}
}
戦略のニーズに応じてこれらの関数を設計し,以下は戦略のメイン関数です.
戦略は,FMZで,main
この関数は,この関数で実行されます.main
初期化する部分には,いくつかの手順があります.
取引所のオブジェクト名 戦略の多くの操作が取引所のオブジェクトに使用されるため,例えば市場を取得,注文を下ろすなど. だから,長い名前を使うのは面倒です. 小さなコツは,簡単な名前を使用することです.
var exA = exchanges[0]
var exB = exchanges[1]
後にコードを書くのは快適です.
通貨レート,精度に関する設計
// 精度,汇率设置
if (rateA != 1) {
// 设置汇率A
exA.SetRate(rateA)
Log("交易所A设置汇率:", rateA, "#FF0000")
}
if (rateB != 1) {
// 设置汇率B
exB.SetRate(rateB)
Log("交易所B设置汇率:", rateB, "#FF0000")
}
exA.SetPrecision(pricePrecisionA, amountPrecisionA)
exB.SetPrecision(pricePrecisionB, amountPrecisionB)
変数値がrateA
、rateB
設定が1である場合は,rateA != 1
あるいはrateB != 1
通貨の変換を設定しない.
すべてのデータをリセットします.
時には,ポリシー開始時にすべてのログ,空白記録のデータを削除する必要がある場合もあります. ポリシーインターフェースのパラメータをデザインできます.isReset
策略で初期化された部分の設計を再設定するコード,例えば:
if (isReset) { // 当isReset为真时重置数据
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("重置所有数据", "#FF0000")
}
初期アカウントデータを復元,現在のアカウントデータを更新
バランスを判断するために,戦略は,最初の口座資産の状況と現在の状況との対比を継続的に記録し,その状況と現在の状況との対比を記録する必要があります.nowAccs
この変数は,現在のアカウントのデータを記録するものです.updateAccs
取引所の口座情報を入手する.initAccs
取引所Aと取引所Bのコイン数,定価コイン数などのデータ) を記録する.initAccs
まず使用する_G()
機能復元 ((_G 機能は永続的にデータを記録し,記録されたデータを復元することができます.APIのドキュメントを参照してください:リンク検索ができない場合は,現在のアカウント情報で割り当てて使用してください._G
函数記録.
このコードは,
var nowAccs = _C(updateAccs, exchanges)
var initAccs = _G("initAccs")
if (!initAccs) {
initAccs = nowAccs
_G("initAccs", initAccs)
}
主回路内のコードは,戦略論理の各回合で実行されるプロセスであり,繰り返し実行されるプロセスが主回路を形成する.
市場データを入手し,市場データの有効性を判断する
var ts = new Date().getTime()
var depthARoutine = exA.Go("GetDepth")
var depthBRoutine = exB.Go("GetDepth")
var depthA = depthARoutine.wait()
var depthB = depthBRoutine.wait()
if (!depthA || !depthB || depthA.Asks.length == 0 || depthA.Bids.length == 0 || depthB.Asks.length == 0 || depthB.Bids.length == 0) {
Sleep(500)
continue
}
この FMZ プラットフォームを使って行われている並行関数ですexchange.Go
呼び出しを作成しましたGetDepth()
インタフェースの同期オブジェクトdepthARoutine
、depthBRoutine
│ この2つの対称オブジェクトが作成されたとき,呼び出しGetDepth()
インタフェースもすぐに発生し,この時点で2つの深度データ取得の要求が取引所に送信された.
呼び出しますdepthARoutine
、depthBRoutine
対象についてwait()
深いデータを得る方法.
深度データを取得した後に,深度データの有効性を検証する.データ異常の場合,実行を誘発する.continue
文は主回路を再実行します.
使用する价差值
参数か差价比例
パラメータは?
var targetDiffPrice = hedgeDiffPrice
if (diffAsPercentage) {
targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
}
FMZのパラメータは,あるパラメータに基づいて作れます.表示する可能性は隠れているこの式は,この式を,この式で定義します.价格差
ありがとうございました.差价比例
。
戦略インターフェースのパラメータにパラメータを追加しましたdiffAsPercentage
◎このパラメータに基づいて表示または隠す他の2つのパラメータは,以下のように設定されます:hedgeDiffPrice@!diffAsPercentage
どこにいるのかdiffAsPercentage
このパラメータを表示するには,hedgeDiffPercentage@diffAsPercentage
どこにいるのかdiffAsPercentage
このパラメータを表示するには,
デザインを重ねて 選んでみましたdiffAsPercentage
パラメータは,差値比率でヘッジを誘発する条件である.diffAsPercentage
価格差がヘッジとして引き起こす条件である.
ハードゲージを誘発する条件を判断する
if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPrice && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) { // A -> B 盘口条件满足
var price = (depthA.Bids[0].Price + depthB.Asks[0].Price) / 2
var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance / price > minHedgeAmount) {
amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance / price, maxHedgeAmount)
Log("触发A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, price, amount, nowAccs[1].Balance / price, nowAccs[0].Stocks) // 提示信息
hedge(exB, exA, price, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
} else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPrice && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) { // B -> A 盘口条件满足
var price = (depthB.Bids[0].Price + depthA.Asks[0].Price) / 2
var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance / price > minHedgeAmount) {
amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance / price, maxHedgeAmount)
Log("触发B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, price, amount, nowAccs[0].Balance / price, nowAccs[1].Stocks) // 提示信息
hedge(exA, exB, price, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
}
金融危機は,金融危機の初期段階から始まっています.
1、最初にヘッジ差を満たし,開口の差が設定された差のパラメータを満たす場合にのみヘッジすることができます.
2,取引可能なヘッジは,パラメータに設定された最小ヘッジを満たす必要がある.異なる取引所によって制限される最小単位の量が異なるため,両者の最小を取ることである.
3. 取引所での資産を売り,取引所での資産を買い,取引所での資産を売り,取引所での資産を買い.
これらの条件が満たされた場合,ヘッジ関数を実行すると,ヘッジオフ命令が実行されます. 主関数の前に変数を事前に宣言します.isTrade
この変数は,ヘッジが発生したかどうかを示すために使用されます.true
そして,グローバル変数をリセットします.lastKeepBalanceTS
0 (lastKeepBalanceTSは,最近のバランス操作のタイムラベルをマークするために使用され,0に設定すると,バランス操作は即座に起動します),そしてすべての挂列を削除します.
バランス操作
if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
nowAccs = _C(updateAccs, exchanges)
var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
cancelAll()
if (isBalance) {
lastKeepBalanceTS = ts
if (isTrade) {
var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
isTrade = false
}
}
}
負債の負債は,負債の負債の負債として,負債の負債として,負債の負債として,負債の負債として,負債の負債として,負債の負債として,lastKeepBalanceTS
0にリセットすると,バランス操作は即座に起動します.バランスが成功した後,収益を計算します.
ステータスバー情報
LogStatus(_D(), "A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, " B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, " targetDiffPrice:", targetDiffPrice, "\n",
"当前A,Stocks:", nowAccs[0].Stocks, "FrozenStocks:", nowAccs[0].FrozenStocks, "Balance:", nowAccs[0].Balance, "FrozenBalance", nowAccs[0].FrozenBalance, "\n",
"当前B,Stocks:", nowAccs[1].Stocks, "FrozenStocks:", nowAccs[1].FrozenStocks, "Balance:", nowAccs[1].Balance, "FrozenBalance", nowAccs[1].FrozenBalance, "\n",
"初始A,Stocks:", initAccs[0].Stocks, "FrozenStocks:", initAccs[0].FrozenStocks, "Balance:", initAccs[0].Balance, "FrozenBalance", initAccs[0].FrozenBalance, "\n",
"初始B,Stocks:", initAccs[1].Stocks, "FrozenStocks:", initAccs[1].FrozenStocks, "Balance:", initAccs[1].Balance, "FrozenBalance", initAccs[1].FrozenBalance)
ステータスバーは特に複雑な設計ではない.現在の時間を表示し,A取引所からB取引所への差とB取引所からA取引所への差を示します.現在のヘッジ目標差を示します.A取引所の口座資産データを表示し,B取引所の口座資産データを表示します.
戦略の初期には,この2つのパラメータを組み合わせました.main
この関数の初期操作の部分では, 換算を設計しました.SetRate
換算関数は最初に実行する必要があります.
この関数は2つの側面に影響します.
BTC_USDT
価格単位はUSDT
銀行口座の資産には,USDT
代入したい場合は,コードに設定します.exchange.SetRate(6.8)
簡単にexchange
この取引所のオブジェクトの下にあるすべての関数の取得データは,CNYに換算されます.
通貨の価格がSetRate
函数伝送現在の通貨対目標通貨の為替。海外のメディアは,異なる通貨の現金ヘッジ戦略 (教材)
松鼠の野放人 _ ウクライナの聖剣素晴らしい