В предыдущей статье мы вместе придумали и разработали простую многовидовую сетевую стратегию. Далее мы продолжим изучать и двигаться вперед по пути количественной торговли. В этой статье мы рассмотрим более сложный дизайн стратегии - дизайн стратегий хеджирования. В этой статье планируется разработать многовидовую межвременную стратегию хеджирования. Когда дело доходит до межвременных стратегий хеджирования, те, кто знаком с фьючерсной торговлей, должны быть знакомы с ней. Для новичков они могут не понимать эти концепции, поэтому давайте начнем с краткого объяснения концепции межвременного хеджирования.
Проще говоря, межвременное хеджирование - это длинный контракт, короткий контракт и ожидание трех ситуаций (длинный и короткий) для закрытия позиции одновременно:
В других случаях происходит плавающий убыток, переносящий или продолжающий масштабироваться в позиции (поскольку колебания спреда более умеренны, чем односторонние колебания, относительный риск меньше, обратите внимание, что только относительный!)
Let A1 be the price of contract A at moment 1, and set B1 to be the price of contract B at moment 1. At this time, short contract A, short price A1, long contract B, and long price B1.
Let A2 be the price of contract A at moment 2, and set B2 to be the price of contract B at moment 2. At this time, close the position contract A (short), close short A2, close the position B contract (long), and close long price B2.
Moment 1 difference:A1 - B1 = X
Moment 2 difference:A2 - B2 = Y
X - Y = A1 - B1 - (A2 - B2)
X - Y = A1 - B1 - A2 + B2
X - Y = A1 - A2 + B2 - B1
It can be seen that A1 - A2 is the profit difference in closing the position of contract A.
B2 - B1 is the profit spread of closing the position of contract B. As long as the two closed positions are overall positive, ie: A1 - A2 + B2 - B1 > 0 is profitable. That is, as long as X - Y > 0.
Because of: X - Y = A1 - A2 + B2 - B1
It is concluded that as long as the difference X of opening a position is greater than the difference Y of closing a position, it is profitable (note that it is short A, long B to open a position, the reverse will be the opposite), of course, this is theoretical, practical factors such as commission and slippage should also be considered.
Потому что криптовалютные биржи имеют как контракты на поставку, так и бессрочные контракты. И цена бессрочных контрактов всегда близка к спотной цене из-за ставки финансирования. Тогда мы выбираем использовать контракты на поставку и бессрочные контракты для хеджирования арбитража. Контракт на поставку выбирает более долгосрочный контракт, так что контракт на хеджирование не нужно часто устанавливать.
Как только вы узнаете основные принципы, вам не нужно торопиться с написанием стратегий. Прежде всего, вы можете получить статистику распространения, нарисовать график и наблюдать за распространением.
Мы разрабатываем на основеДоговор OKEX. Это очень просто нарисовать на FMZ. Это очень легко использовать упакованные функции для рисования. Библиотека графиков являетсяВысокие диаграммы. Описание чертежной функции в документации API:https://www.fmz.com/api#chart...
Поскольку это многовидовые, прежде всего, необходимо определить разницу в цене этих видов перед рисунком.
var arrSwapContractType = ["BTC-USDT-SWAP", "LTC-USDT-SWAP", "ETH-USDT-SWAP", "ETC-USDT-SWAP"] // Perpetual contracts
var arrDeliveryContractType = ["BTC-USDT-210924", "LTC-USDT-210924", "ETH-USDT-210924", "ETC-USDT-210924"] // Delivery contracts
Эта конфигурация диаграмма, конечно, не может быть жестко кодирована, потому что вы не знаете, какие виды и сколько видов делать (это определяется значениями arrDeliveryContractType и arrSwapContractType), поэтому конфигурация диаграмма возвращается функцией.
function createCfg(symbol) {
var cfg = {
extension: {
// No grouping, displayed separately, default is 'group'
layout: 'single',
// Specify the height, which can be set as a string, "300px", and the value 300 will be replaced with "300px" automatically
height: 300,
// The unit value of the specified width, the total value is 12
col: 6
},
title: {
text: symbol
},
xAxis: {
type: 'datetime'
},
series: [{
name: 'plus',
data: []
}]
}
return cfg
}
function main() {
// Declare arrCfg
var arrCfg = [] // Declare an array to store chart configuration information
_.each(arrSwapContractType, function(ct) { // Record the array of perpetual contract codes iteratively, pass the XXX-USDT part of the contract name as a parameter to the createCfg function, construct the chart configuration information, and return
arrCfg.push(createCfg(formatSymbol(ct)[0])) // The chart configuration information returned by createCfg is pushed into the arrCfg array
})
var objCharts = Chart(arrCfg) // Call the chart function Chart of the FMZ platform to create the chart control object objCharts
objCharts.reset() // Initialize chart content
// Hereafter omitted ...
}
Далее мы подготовим данные, используя агрегированный рыночный интерфейс контракта OKEX:
Вечные контракты в USDT:
https://www.okex.com/api/v5/market/tickers?instType=SWAP
Контракты на поставку в USDT:
https://www.okex.com/api/v5/market/tickers?instType=FUTURES
Мы пишем функцию для обработки вызовов этих двух интерфейсов и помещаем данные в формат:
function getTickers(url) {
var ret = []
try {
var arr = JSON.parse(HttpQuery(url)).data
_.each(arr, function(ele) {
ret.push({
bid1: parseFloat(ele.bidPx), // Price of stock buy order
bid1Vol: parseFloat(ele.bidSz), // Amount for the price of stock buy order
ask1: parseFloat(ele.askPx), // Price of stock sell order
ask1Vol: parseFloat(ele.askSz), // Amount for the price of stock sell order
symbol: formatSymbol(ele.instId)[0], // Formats into trading pairs
type: "Futures", // Type
originalSymbol: ele.instId // Original contract code
})
})
} catch (e) {
return null
}
return ret
}
Написать другую функцию для обработки кода контракта
function formatSymbol(originalSymbol) {
var arr = originalSymbol.split("-")
return [arr[0] + "_" + arr[1], arr[0], arr[1]]
}
Все, что осталось - это итеративно сочетать полученные данные, рассчитывать спреды, выводить графики и т.д. Тест здесь заключается в разнице между контрактом 210924 и контрактом "постоянный". Полный код:
// Temporary parameters
var arrSwapContractType = ["BTC-USDT-SWAP", "LTC-USDT-SWAP", "ETH-USDT-SWAP", "ETC-USDT-SWAP"]
var arrDeliveryContractType = ["BTC-USDT-210924", "LTC-USDT-210924", "ETH-USDT-210924", "ETC-USDT-210924"]
var interval = 2000
function createCfg(symbol) {
var cfg = {
extension: {
// No grouping, displayed separately, default is 'group'
layout: 'single',
// Specify the height, which can be set as a string, "300px", and the value 300 will be replaced with "300px" automatically
height: 300,
// The unit value of the specified width, the total value is 12
col: 6
},
title: {
text: symbol
},
xAxis: {
type: 'datetime'
},
series: [{
name: 'plus',
data: []
}]
}
return cfg
}
function formatSymbol(originalSymbol) {
var arr = originalSymbol.split("-")
return [arr[0] + "_" + arr[1], arr[0], arr[1]]
}
function getTickers(url) {
var ret = []
try {
var arr = JSON.parse(HttpQuery(url)).data
_.each(arr, function(ele) {
ret.push({
bid1: parseFloat(ele.bidPx),
bid1Vol: parseFloat(ele.bidSz),
ask1: parseFloat(ele.askPx),
ask1Vol: parseFloat(ele.askSz),
symbol: formatSymbol(ele.instId)[0],
type: "Futures",
originalSymbol: ele.instId
})
})
} catch (e) {
return null
}
return ret
}
function main() {
// Declare arrCfg
var arrCfg = []
_.each(arrSwapContractType, function(ct) {
arrCfg.push(createCfg(formatSymbol(ct)[0]))
})
var objCharts = Chart(arrCfg)
objCharts.reset()
while (true) {
// Obtain market data
var deliveryTickers = getTickers("https://www.okex.com/api/v5/market/tickers?instType=FUTURES")
var swapTickers = getTickers("https://www.okex.com/api/v5/market/tickers?instType=SWAP")
if (!deliveryTickers || !swapTickers) {
Sleep(2000)
continue
}
var tbl = {
type : "table",
title : "delivery - perpetual spread",
cols : ["trading pairs", "delivery", "perpetual", "positive hedging", "negative hedging"],
rows : []
}
var subscribeDeliveryTickers = []
var subscribeSwapTickers = []
_.each(deliveryTickers, function(deliveryTicker) {
_.each(arrDeliveryContractType, function(symbol) {
if (deliveryTicker.originalSymbol == symbol) {
subscribeDeliveryTickers.push(deliveryTicker)
}
})
})
_.each(swapTickers, function(swapTicker) {
_.each(arrSwapContractType, function(symbol) {
if (swapTicker.originalSymbol == symbol) {
subscribeSwapTickers.push(swapTicker)
}
})
})
var pairs = []
var ts = new Date().getTime()
_.each(subscribeDeliveryTickers, function(deliveryTicker) {
_.each(subscribeSwapTickers, function(swapTicker) {
if (deliveryTicker.symbol == swapTicker.symbol) {
var pair = {symbol: swapTicker.symbol, swapTicker: swapTicker, deliveryTicker: deliveryTicker, plusDiff: deliveryTicker.bid1 - swapTicker.ask1, minusDiff: deliveryTicker.ask1 - swapTicker.bid1}
pairs.push(pair)
tbl.rows.push([pair.symbol, deliveryTicker.originalSymbol, swapTicker.originalSymbol, pair.plusDiff, pair.minusDiff])
for (var i = 0 ; i < arrCfg.length ; i++) {
if (arrCfg[i].title.text == pair.symbol) {
objCharts.add([i, [ts, pair.plusDiff]])
}
}
}
})
})
LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`")
Sleep(interval)
}
}
Бегут некоторое время.
Наблюдайте за распространением, а потом говорите об этом!