Для новичков в разработке стратегии, стратегии хеджирования являются очень хорошими практическими стратегиями. Эта статья реализует простую, но действенную стратегию хеджирования цифровых валют.
Прежде всего, мы разработали стратегию цифрового валютного дешевого хеджирования. Мы разработали самый простой вариант хеджирования, который предполагает продажу только на более высокой цене между двумя дешевыми биржами, а покупку на более низкой цене, чтобы получить разницу.
При хеджировании существуют ограничения на точность, количество, цены и минимальное количество заказов. В дополнение к минимальным ограничениям стратегия хеджирования также учитывает максимальное количество заказов, которые могут быть заложены за один раз, а также недостаточное количество заказов. Также необходимо учитывать, как конвертировать валютные курсы, если две купленные валюты отличаются друг от друга.
На основе этих соображений стратегии должны быть разработаны несколько параметров:
hedgeDiffPrice
, когда разница превышает это значение, запускается операция хеджирования.minHedgeAmount
Минимальная сумма, которую можно хеджировать.maxHedgeAmount
, максимальный размер хеджировки в одном экземпляре ((число монет) ).pricePrecisionA
, точность цены, размещенной на бирже A ((дешевые цифры)).amountPrecisionA
, A - точность единиц (плохие цифры) на бирже.pricePrecisionB
, точность цены, размещенной на бирже B ((небольшие цифры)).amountPrecisionB
В этом случае, если вы хотите, чтобы вы были в курсе, вы должны быть готовы к тому, что вы будете делать.rateA
, первая добавленная обменная точка конвертируется, по умолчанию 1 не конвертируется.rateB
Второй добавленный объект обмена конвертируется, по умолчанию 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 ((по умолчанию это 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
│ При создании этих двух параллельных объектов, призывGetDepth()
Также произошел интерфейс, когда два запроса на получение глубоких данных были отправлены на биржу в прошлом.
Затем позвоните.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
❖ Два других параметра, которые могут быть показаны или скрыты на основе этого параметра, настроены так: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.
В параметрах мы разработали параметры для преобразования валютных курсов.main
Мы также разработали часть первоначальных операций функции, которая называется конвертация курсов.SetRate
Функция конвертации валютных курсов должна быть выполнена сначала.
В результате, мы получаем больше информации о том, что мы делаем, чем делаем.
BTC_USDT
В целом,USDT
В частности, в банковских счетах используются валюты, которые могут быть использованы в качестве средств.USDT
Если я хочу конвертировать их в CNY, я могу установить это в кодеexchange.SetRate(6.8)
Вы должныexchange
Все данные, полученные функциями под объектом этой биржи, обмениваются в CNY.
В обмен на то, почему мы даем монетыSetRate
Функция вводаКурс текущей валюты к целевой валюте。Полная стратегия:Стратегии хеджирования наличности в различных валютах
Скорпионы-разногласные_ украинский фехтовальщикОтлично.