В предыдущей статье мы вместе реализовали простую стратегию хеджирования, а затем мы узнаем, как обновить стратегию. В стратегию не вносится много изменений, но подробности этих изменений требуют внимания.
A->B
иB->A
, а также горизонтальных расширения триггер линий, мы можем напрямую использоватьchart plot library
; преимущество заключается в простоте и простоте использования.template library
together.Далее, давайте реализуем эти дизайнерские идеи по одному.
Возьмите Binance спот бота в качестве примера.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
Вы можете искать его непосредственно на площади ФМЗ.
Или вы можете прямо нажать на ссылку:https://www.fmz.com/strategy/27293перейти на страницу копирования шаблона.
Нажмите на кнопку и вы можете легко скопировать шаблон в свою собственную библиотеку стратегии.
Затем, на странице редактирования стратегии, вы можете проверить библиотеку шаблонов, которая будет использоваться в столбце шаблона. Сохранить стратегию после ее проверки, и стратегия будет использовать этот шаблон. Это просто краткое описание использования библиотеки шаблонов. Поскольку стратегия уже ссылается на этот шаблон, нет необходимости повторять операцию. Когда вы копируете код стратегии в Square, вы можете увидеть, чтоchart plot Library
был упомянут в строке шаблона на странице редактирования стратегии.
Здесь мы в основном узнаем, как использовать функцииchart plot library
чтобы составить план.
Мы планируем составить график распространенияA->B
иB->A
Мы должны составить графику двух кривых (в настоящее время, кривые от A до B и B до A) и двух горизонтальных линий (кривые от spread), как показано на рисунке выше.
Потому что мы хотим спроектировать односторонний жидкий хребет, триггерные линии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
на два, а именно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")
Когда стратегия будет выполнена, график будет отображаться вот так.
Далее, нарисуйте кривую распределения в реальном времени; чтобы избежать перетягивания, поместите код, изображающий кривые распределения в реальном времени, в детектор баланса. с
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 строки, чтобы позволить стратегии с графиком отображения во время выполнения.
Как уже упоминалось выше, число триггер-линий с спредом было изменено на два, которые соответственно контролируют триггер хеджирования на: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
}
}
Поскольку цены покупки и продажи разделены на две части данных,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. После ввода значения в поле ввода управления, нажмите кнопку справа от поля ввода. Команда будет отправлена в стратегию немедленно, например: введите значение123
в поле ввода, нажмите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