簡単なヘッジ戦略を実装し 戦略のアップグレード方法を学びます 戦略には多くの変更はありませんが,変更の詳細には注意が必要です.コードのいくつかの場所の定義は,前回と比較して変更されています.
A->B
そしてB->A
横軸のスプレッドトリガーラインと同様に,我々は直接使用することができますchart plot library
FMZの機能を使用する方法も学びます.template library
together.次は デザインのアイデアを一つずつ 実現しましょう
コードを使用します. このコードは,このコードを入力します.exchanges[i].IO
パラメータをインポートtrade_normal
単一の利益率に移行し,輸入trade_super_margin
バックテストではサポートされません. それはボットでのみ使用できます.
準備の過程で,main
機能,追加:
// switch the margin mode
for (var i = 0 ; i < exchanges.length ; i++) { // traverse and detect all exchange objects added
if (exchanges[i].GetName() == "Binance" && marginType != 0) { // if the exchange object represented by the current index i is Binance Spot, and the parameter marginType on the strategy interface is not selected as the "common spot" option, execute the switch
if (marginType == 1) {
Log(exchanges[i].GetName(), "set to isolated margin")
exchanges[i].IO("trade_normal")
} else if (marginType == 2) {
Log(exchanges[i].GetName(), "set to cross margin")
exchanges[i].IO("trade_super_margin")
}
}
}
この戦略は,Binance Spotのスポット・マージンモードを切り替えるためのコードのみを追加します. したがって,戦略パラメータのスイッチ設定は,Binance Spotのみで動作します.
模板の名前は,ここでは,この模板の名前ですchart plot Library
FMZの広場で直接検索できます.
直接リンクをクリックすることもできますhttps://www.fmz.com/strategy/27293テンプレートのコピーページに跳ね込む.
簡単に自分の戦略ライブラリにテンプレートをコピーできます.
次に,戦略編集ページでは,テンプレート列で使用するテンプレートライブラリを確認できます. チェックした後,戦略を保存し,戦略はこのテンプレートライブラリを使用します. これはテンプレートライブラリの使用の簡潔な説明だけです. 戦略がすでにこのテンプレートを参照しているため,操作を繰り返す必要はありません. 戦略コードをスクエアにコピーすると,chart plot Library
戦略編集ページのテンプレートバーで参照されています.
基本的には,コンピュータの機能をchart plot library
計画する
拡大を計画していますA->B
そしてB->A
2つの曲線 (現在,AからBへ,BからAへのスプレッド) と2つの水平線 (スプレッドのスプレッドライン) を図に描く必要があります.
引き金線は,この線が,この線が,A->B
そしてB->A
前回の記事では デザインは使えません
前回の記事では
var targetDiffPrice = hedgeDiffPrice
if (diffAsPercentage) {
targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
}
引き起こすのは"つだけtargetDiffPrice
- わかった
まずパラメータを修正する必要があります. この場合は,
次にコードを変更します:
var targetDiffPriceA2B = hedgeDiffPriceA2B
var targetDiffPriceB2A = hedgeDiffPriceB2A
if (diffAsPercentage) {
targetDiffPriceA2B = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageA2B
targetDiffPriceB2A = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageB2A
}
引き金線は前線から変わっています.targetDiffPrice
2つ,つまりtargetDiffPriceA2B
そしてtargetDiffPriceB2A
- わかった
グラフの図面図書室のグラフプロット機能を使用して グラフ上のデータを描くことができます
// plot
$.PlotHLine(targetDiffPriceA2B, "A->B") // the first parameter of the function is the value of the horizontal line in the Y-axis direction, and the second parameter is the display text
$.PlotHLine(targetDiffPriceB2A, "B->A")
戦略を実行すると,チャートはこのように表示されます.
次に,リアルタイム・スプレッド・カーブを描いてください.過剰に描かれないようにするために,リアルタイム・スプレッド・カーブを描いたコードを バランス検出に入れます. s
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
}
}
$.PlotLine("A2B", depthA.Bids[0].Price - depthB.Asks[0].Price) // plot real-time spread curves
$.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price) // the first parameter is the curve name, and the second parameter is the curve value at the current moment, that is, the value in the Y-axis direction at the current moment
}
走行中にチャート表示の戦略を可能にするために,プロットコードは4行だけです.
上記のように,スプレッドトリガーラインの番号は2つに変更され,それぞれヘッジトリガーを制御しています.A->B
そしてB->A
この方法では,以前の注文価格アルゴリズムを使用することはできません.代わりにスライド価格を市場価格に追加する方法を使用します.
if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPriceA2B && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) { // A->B market condition satisfied
var priceSell = depthA.Bids[0].Price - slidePrice
var priceBuy = depthB.Asks[0].Price + slidePrice
var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance * 0.8 / priceSell > minHedgeAmount) {
amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance * 0.8 / priceSell, maxHedgeAmount)
Log("triggerA->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks) // prompt message
hedge(exB, exA, priceBuy, priceSell, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
} else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPriceB2A && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) { // B->A market condition satisfied
var priceBuy = depthA.Asks[0].Price + slidePrice
var priceSell = depthB.Bids[0].Price - slidePrice
var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance * 0.8 / priceBuy > minHedgeAmount) {
amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance * 0.8 / priceBuy, maxHedgeAmount)
Log("triggerB->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks) // prompt message
hedge(exA, exB, priceBuy, priceSell, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
}
購入価格と販売価格が2つのデータに分割されているため,hedge
機能も変更する必要があります.
function hedge(buyEx, sellEx, priceBuy, priceSell, amount) {
var buyRoutine = buyEx.Go("Buy", priceBuy, amount)
var sellRoutine = sellEx.Go("Sell", priceSell, amount)
Sleep(500)
buyRoutine.wait()
sellRoutine.wait()
}
これらの変更に基づいて,いくつかの小さな調整もあります. ここでは説明されません.詳細についてはコードを見ることができます.
戦略にインタラクションを追加して,戦略がリアルタイムでスプレッドトリガーラインを修正できるようにします. これはまた,ここで教学デモとして実装される半自動戦略の設計要件です. 戦略のインタラクションデザインも非常にシンプルです.まず,戦略編集ページの戦略にインタラクティブなコントロールを追加します.
A2B と B2A と呼ばれる2つのコントロールが追加されました. コントロール入力ボックスに値を入力した後,入力ボックス右側のボタンをクリックします. 命令はすぐに戦略に送られます.例えば: enter the value123
入力ボックスで,クリックしますA2B
命令がすぐに戦略に送られます
A2B:123
戦略コードに インタラクティブな検出と処理コードを 設計する
// interaction
var cmd = GetCommand() // every time when the loop is operated here, it will detect whether an interactive command is sent; if no, return null string
if (cmd) { // interactive command detected, such as A2B:123
Log("received command:", cmd)
var arr = cmd.split(":") // split out the interactive control name and the value in the input box; arr[0] means A2B, and arr[1] means 123
if (arr[0] == "A2B") { // judge whether the triggered interactive control is A2B
Log("modify parameterA2B,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageB2A = parseFloat(arr[1]) // modify the spread trigger line
} else {
hedgeDiffPriceA2B = parseFloat(arr[1]) // modify the spread trigger line
}
} else if (arr[0] == "B2A") { // detected the triggered control is B2A
Log("modify parameterB2A,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageA2B = parseFloat(arr[1])
} else {
hedgeDiffPriceB2A = parseFloat(arr[1])
}
}
}
ステータスバーのデータ表示を より規制され 観察しやすくします
var tbl = {
"type" : "table",
"title" : "data",
"cols" : ["platform", "Currency", "frozenCurrrency", "quoteCurrency", "frozenQuoteCurrency", "triggerSpread", "currentSpread"],
"rows" : [],
}
tbl.rows.push(["A:" + exA.GetName(), nowAccs[0].Stocks, nowAccs[0].FrozenStocks, nowAccs[0].Balance, nowAccs[0].FrozenBalance, "A->B:" + targetDiffPriceA2B, "A->B:" + (depthA.Bids[0].Price - depthB.Asks[0].Price)])
tbl.rows.push(["B:" + exB.GetName(), nowAccs[1].Stocks, nowAccs[1].FrozenStocks, nowAccs[1].Balance, nowAccs[1].FrozenBalance, "B->A:" + targetDiffPriceB2A, "B->A:" + (depthB.Bids[0].Price - depthA.Asks[0].Price)])
LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
バックテストは,初期検出機能として戦略のテストに過ぎない.多くのバグは実際にバックテスト段階でテストすることができます.バックテストの結果についてあまり心配する必要はありません.最終的には,戦略は実際の環境で実際のボットでテストする必要があります.
戦略のソースコード:https://www.fmz.com/strategy/302834