В предыдущей статье мы вместе реализовали простую стратегию хеджирования, а затем узнаем, как обновить эту стратегию. Изменения в стратегии не являются большими, но детали изменений требуют внимания.
A exchange -> B exchange
, B exchange -> A exchange
, и рисуем горизонтальную линию, которая запускает распространение.line drawing class library
Для того, чтобы иметь дело с непосредственно, преимущество заключается в том, что это легко использовать, здесь мы также учимся, как использоватьtemplate class library
функция FMZ.Далее, давайте реализуем эти проекты один за другим.
Возьмите Binance место реального бота в качестве примера, переключитесь на место рычагов режима, используйте кодexchanges[i].IO
, введите параметрtrade_normal
перейти к позиции с рычагом воздействия по позициям и вводуtrade_super_margin
для переключения на полную позицию рычага, обратное тестирование не поддерживается.
Добавьте к фазе подготовки в началеmain
Функция:
// Switch leverage mode
for (var i = 0 ; i < exchanges.length ; i++) { // Traverse and detect all added exchange objects
if (exchanges[i].GetName() == "Binance" && marginType != 0) { //If the exchange object represented by the current i-index is Binance spot, and the parameter marginType of the strategy interface is not the option of "common currency", execute the switch operation
if (marginType == 1) {
Log(exchanges[i].GetName(), "Set to leveraged position-by-position")
exchanges[i].IO("trade_normal")
} else if (marginType == 2) {
Log(exchanges[i].GetName(), "Set to leveraged full position")
exchanges[i].IO("trade_super_margin")
}
}
}
Стратегия здесь добавляет только код для переключения режима рычагов на Binance spot, поэтому настройка переключателя на параметрах стратегии действительна только для Binance spot.
Это очень легко использовать уже завернутый шаблон рисунка.Line Drawing Library
Его можно получить, поиск прямо на площадке стратегии платформы FMZ.
Или нажмите на ссылку прямо:https://www.fmz.com/strategy/27293чтобы перейти на страницу копирования этого шаблона.
Нажмите на кнопку, чтобы скопировать библиотеку шаблона класса в свою собственную библиотеку стратегии.
Затем вы можете проверить библиотеку класса шаблона, которая будет использоваться в столбце шаблона на странице редактирования стратегии. Сохранить стратегию после проверки, и стратегия будет относиться к этому шаблону. Это просто краткое описание использования библиотеки класса шаблона. Эта стратегия уже ссылается на этот шаблон, поэтому нет необходимости повторять операцию. Когда вы копируете эту стратегию в поле стратегии, вы можете увидеть, чтоLine Drawing Library
был упомянут в строке шаблона на странице редактирования стратегии.
В основном мы узнаем, как использовать функцииLine Drawing Library
чтобы нарисовать диаграмму.
Мы планируем нарисовать распространениеA->B
, распространениеB->A
Нам нужно нарисовать две кривые (текущий A к B, B к A), две горизонтальные линии (линия триггера), как показано на рисунке выше.
Потому что мы хотим разработать одностороннее хеджирование, триггерные линии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
- Да.
Следующий шаг - нарисовать эти данные на графике, используя функцию чертежной линии библиотеки чертежных линий.
// drawing
$.PlotHLine(targetDiffPriceA2B, "A->B") // The first parameter of this 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) // Draw real-time spread curves
$.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price) // The first parameter is the name of the curve, and the second parameter is the value of the curve 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 conditions are met
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("trigger A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks) // Tips
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 conditions are met
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("trigger B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks) //Tips
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
Проектируйте интерактивный код обнаружения и обработки в коде стратегии.
// interact
var cmd = GetCommand() // Every time the loop is executed here, it checks whether there is an interactive command, and returns to an empty string if not.
if (cmd) { // An interactive command was detected, such as A2B:123
Log("command received:", cmd)
var arr = cmd.split(":") // Split out the interactive control name and the value in the input box, arr[0] is A2B, arr[1] is 123
if (arr[0] == "A2B") { // Determine whether the triggered interactive control is A2B
Log("Modify the parameters of A2B, ", diffAsPercentage ? "The parameter is the difference percentage" : "The parameter is the difference:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageB2A = parseFloat(arr[1]) // Modify the trigger spread line
} else {
hedgeDiffPriceA2B = parseFloat(arr[1]) // Modify the trigger spread line
}
} else if (arr[0] == "B2A") { // Triggered control detected is B2A
Log("Modify the parameters of B2A, ", diffAsPercentage ? "The parameter is the difference percentage" : "The parameter is the difference:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageA2B = parseFloat(arr[1])
} else {
hedgeDiffPriceB2A = parseFloat(arr[1])
}
}
}
Сделайте отображение данных строки состояния более организованным и простым для наблюдения.
var tbl = {
"type" : "table",
"title" : "data",
"cols" : ["exchange", "coin", "freeze coin", "denominated currency", "freeze denominated currency", "trigger spread", "current spread"],
"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) + "`")
Backtesting - это только стратегия тестирования, функция предварительного обнаружения, и многие ошибки могут быть протестированы на стадии backtesting на самом деле.
Источник стратегии:https://www.fmz.com/strategy/302834