Номер 1 В книге "Финансовая алхимия", написанной Соросом в 1987 году, было выдвинуто важное предложение: я считаю, что рыночные цены всегда ошибочны в том смысле, что они представляют собой предвзятое представление о будущем. Гипотеза о действительности рынка является лишь теоретическим предположением. На самом деле участники рынка не всегда рациональны, и в каждый момент времени участники не могут полностью приобрести и объективно интерпретировать всю информацию. Даже если это одна и та же информация, обратная связь каждого человека отличается.
Другими словами, сама цена уже содержит неверные ожидания участников рынка, поэтому по сути рыночная цена всегда неверна.
No 2 Исходя из вышеперечисленных принципов, мы также знаем, что на неэффективном фьючерсном рынке влияние контрактов на поставку в разные периоды не всегда синхронизировано, и ценообразование не является причиной полной эффективности.
Затем, основываясь на цене контракта поставки в разное время одной и той же цели сделки, если между двумя ценами существует большой спред, можно одновременно торговать фьючерсными контрактами разных периодов и осуществлять межвременный арбитраж. Как и товарные фьючерсы, цифровые валюты также имеют портфель межвременных арбитражных контрактов, связанных с ними.
Например, предположим, что спред между неделей ETC и кварталом ETC сохраняется около 5 в течение длительного времени. Если спред достигнет 7, мы ожидаем, что спред вернется к 5 в какой-то момент в будущем. Тогда вы можете продать неделю ETC и купить квартал ETC, чтобы сократить спред. и наоборот.
No 3 Несмотря на то, что этот спред существует, в ручном арбитраже часто существует много неопределенности из-за трудоемкости, плохой точности ручных операций и влияния изменения цен.
Через количественную модель для захвата возможностей арбитража и разработки стратегий арбитражной торговли, а также программные алгоритмы автоматически выпускают торговые заказы на биржу, чтобы быстро и точно захватывать возможности и эффективно зарабатывать доход, что является прелестью количественного арбитража.
В этой статье вы узнаете, как использовать квантитативную торговую платформу FMZ и фьючерсный контракт ETC на бирже OkEX в торговле цифровой валютой, с простой стратегией арбитража, чтобы продемонстрировать, как использовать мгновенные возможности арбитража и извлечь любую видимую прибыль, одновременно хеджируя риски, с которыми можно столкнуться.
No 4 Создать стратегию межвременного арбитража цифровой валюты Сложность: средний уровень Стратегическая среда: Цель сделки: Ethereum classic (ETC) Спродные данные: ЕТК еженедельно - ЕТК квартально Период торговли: 5 минут Совпадение позиций: 1:1 Тип сделки: одно и то же соотношение Логика стратегии: Условия покупки позиции с длинным спредом: если на текущем счете нет позиций, а спред меньше, чем снижение показателя Boll, разместите спредовый ордер, который заключается в следующем: покупать длинный ETC еженедельно, продавать короткий ETC ежеквартально.
Условия позиции на короткую продажу: если на текущем счете нет позиций, а спред выше, чем вверх по индикатору Boll, разместите спредовый ордер, который заключается в следующем: продажа короткой ETC еженедельно, покупка длинной ETC ежеквартально.
Закрытие условия позиции покупки длинного спреда: если текущий счет имеет длинную еженедельную позицию ETC и короткую квартальную позицию ETC, и спред выше средней рельсы индикатора Boll, разместите ордер на закрытие спреда, который заключается в следующем: продажа ETC еженедельно, покупка для покрытия ETC ежеквартально.
Закрытие условий позиции короткой продажи спреда: если текущий счет имеет короткую еженедельную позицию ETC и длинную квартальную позицию ETC, а спред ниже средней рельсы индикатора Boll, разместите ордер на закрытие спреда, который заключается в следующем: покупать для покрытия ETC еженедельно, продавать ETC квартально.
No 5 Выше приведено простое описание логики стратегии интервременного арбитража цифровой валюты, то как реализовать свои собственные идеи в программе? Рамочная стратегия:
Стратегическую структуру можно легко выстроить в соответствии со стратегическим мышлением и процессом транзакций.
No 6 Далее нам нужно заполнить необходимые детали в рамках стратегии на основе фактического процесса сделки и деталей сделки.
Во-первых, предварительная обработка перед транзакцией Шаг 1: В глобальной среде декларировать необходимые глобальные переменные. Объявить объект диаграмма, который конфигурирует диаграмму Карта вар = { } Вызвать функцию Chart для инициализации диаграммы Var ObjChart = График (графика) Декларировать пустой массив для хранения последовательности распространения Var bars = [ ] Заявление переменной временной метки, которая записывает исторические данные Var oldTime = 0 Шаг 2: настройка внешних параметров для стратегии.
Шаг 3: Определение функции обработки данных Функция базовых данных: Данные ()) Создать конструктор Данные и определить его внутренние свойства, включая: данные счета, данные позиции, K-линейные данные временной отметки, последняя цена покупки/продажи арбитражного контракта A/B, положительный/обратный спред арбитража
Получить функцию положения: mp ()) Проверьте весь массив позиций, верните указанный контракт и количество позиций в указанном направлении.
Линия K и функция индикатора: boll ()) Синтезируйте новую последовательность K-линий на основе данных положительного/обратного арбитражного спрэда и верните данные вверх/в середину/вниз, рассчитанные по индикатору Boll.
Функция заказа: торговля ()) Введите название контракта заказа и тип сделки, затем разместите заказ по последней цене покупки/продажи и верните результат после размещения заказа.
Функция отмены заказа: cancelOrders ()) Получите массив всех ожидаемых заказов и отмените их один за другим, и если есть ожидаемый заказ, верните ложный, а если нет, верните истинный.
Процесс сдерживания единого контракта: isEven ()) В случае с ситуацией с одной ногой в арбитражной торговле, она напрямую обрабатывается, просто закрывая все позиции.
Функция чертежного диаграмма: чертежная графика ()) Метод Call ObjChart.add ( ) для получения необходимых рыночных данных и данных показателей в графике: вверх, в середину, вниз рельсы, положительный/обратный арбитражный спред.
Шаг 4: В функции ввода main (), выполните код предварительной обработки перед транзакцией, который выполняется только один раз после запуска программы, включая:
отфильтровать не очень важную информацию в консоли SetErrorFilter ()) Установка типа цифровой валюты для торговлиexchange.IO()) Очистить рисованные диаграммы перед запуском программы ObjChart.reset ()) Очистить информацию строки состояния перед запуском программы LogProfitReset ())
NO.7 После определения вышеуказанной предварительной обработки до транзакции необходимо перейти к следующему шагу, войти в режим опроса и повторить функцию onTick (). И установить время сна при опросе, потому что некоторые из цифровых валютных бирж API имеет встроенное ограничение доступа на определенный период времени.
Во-вторых, получить и рассчитать данные Шаг 1: Получить базовый объект данных, баланс счета и данные индикатора boll для логики торговли.
В-третьих, разместить заказ и последующие действия Шаг 1: Выполните операцию покупки и продажи в соответствии с вышеуказанной логикой стратегии. Во-первых, проверьте, являются ли условия цены и индикатора верными, а затем проверьте, являются ли условия позиции верными, и, наконец, выполните функцию торгового заказа ().
Шаг 2: После размещения заказа необходимо справиться с ненормальными ситуациями, такими как ожидание заказов и проведение единого контракта, и составить графики.
Номер 8 Выше мы создали простую стратегию межвременного арбитража цифровой валюты с более чем 200 строками.
No 9 Настоящий рынок не так прост, но вы можете использовать этот пример, чтобы поиграть со своим воображением.
Необходимо напомнить, что, основываясь на моем ограниченном опыте, стратегия чистого периода арбитража в основном не стоит использовать в текущей ситуации на рынке цифровой валюты, будь то треугольный арбитраж без риска или арбитраж между рынками.
Причина заключается в том, что независимо от того, на каком рынке фьючерсов цифровой валюты обмена, маржа не фиатная. Почти все цифровые валюты упали примерно на 70% с начала года. Другими словами, стратегия всегда делает валюту, но цена валюты падает.
Если взглянуть в широком смысле, рынок цифровой валюты уже покинул блокчейн.
Вот полный код:
// global variable
// Declare a chart object that configures the chart
var chart = {
__isStock: true,
tooltip: {
xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
},
title: {
text: 'Profit and loss chart(detail)'
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'hour',
count: 2,
text: '3h'
}, {
type: 'hour',
count: 8,
text: '8h'
}, {
type: 'all',
text: 'All'
}],
selected: 0,
inputEnabled: false
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'spread'
},
opposite: false,
},
series: [{
name: "up",
id: "line1,up",
data: []
}, {
name: "middle",
id: "line2,middle",
data: []
}, {
name: "down",
id: "line3,down",
data: []
}, {
name: "basb",
id: "line4,basb",
data: []
}, {
name: "sabb",
id: "line5,sabb",
data: []
}]
};
var ObjChart = Chart(chart); // Drawing object
var bars = []; // Store spread sequence
var oldTime = 0; // Record historical data timestamp
// Parameter
var tradeTypeA = "this_week"; // Arbitrage contract A
var tradeTypeB = "quarter"; // Arbitrage contract B
var dataLength = 10; //Length of indicator cycle
var timeCycle = 1; // The cycle of K-line
var name = "ETC"; // Currency type
var unit = 1; // Quantity of orders
// Basic data
function Data(tradeTypeA, tradeTypeB) { // input arbitrage contract A&B
this.accountData = _C(exchange.GetAccount); // get account data
this.positionData = _C(exchange.GetPosition); // get position data
var recordsData = _C(exchange.GetRecords); //get k-line data
exchange.SetContractType(tradeTypeA); // subscribe arbitrage contract A
var depthDataA = _C(exchange.GetDepth); // deep data of arbitrage contract A
exchange.SetContractType(tradeTypeB); // subscribe arbitrage contract B
var depthDataB = _C(exchange.GetDepth); // deep data of arbitrage contract B
this.time = recordsData[recordsData.length - 1].Time; // get the latest time data
this.askA = depthDataA.Asks[0].Price; // the latest selling price of arbitrage contract A
this.bidA = depthDataA.Bids[0].Price; // the latest buying price of arbitrage contract A
this.askB = depthDataB.Asks[0].Price; // the latest selling price of arbitrage contract B
this.bidB = depthDataB.Bids[0].Price; // the latest buying price of arbitrage contract B
// Positive arbitrage spread(the latest selling price of contract A -the latest buying price of contract B )
this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
// Reverse arbitrage spread(the latest buying price of contract A -the latest selling price of contract B )
this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}
// get position information
Data.prototype.mp = function (tradeType, type) {
var positionData = this.positionData; // get position data
for (var i = 0; i < positionData.length; i++) {
if (positionData[i].ContractType == tradeType) {
if (positionData[i].Type == type) {
if (positionData[i].Amount > 0) {
return positionData[i].Amount;
}
}
}
}
return false;
}
// Synthetize new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
var self = {}; // Temporary object
// the median of Positive arbitrage spread and reverse arbitrage spread
self.Close = (this.basb + this.sabb) / 2;
if (this.timeA == this.timeB) {
self.Time = this.time;
} // Comparing two depth data timestamps
if (this.time - oldTime > timeCycle * 60000) {
bars.push(self);
oldTime = this.time;
} // According to the specified time period, insert the spread data object in the K-line array.
if (bars.length > num * 2) {
bars.shift(); // Control K-line array length
} else {
return;
}
var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the Talib Library
return {
up: boll[0][boll[0].length - 1], // up rail of boll indicator
middle: boll[1][boll[1].length - 1], // middle rail of boll indicator
down: boll[2][boll[2].length - 1] // down rail of boll indicator
} // Return a processed boll indicator data.
}
// place order
Data.prototype.trade = function (tradeType, type) {
exchange.SetContractType(tradeType); // Resubscribe contract before placing order
var askPrice, bidPrice;
if (tradeType == tradeTypeA) { // if it's contract A
askPrice = this.askA; // set askPrice
bidPrice = this.bidA; // set bidPrice
} else if (tradeType == tradeTypeB) { // if it's contract B
askPrice = this.askB; // set askPrice
bidPrice = this.bidB; // set bidPrice
}
switch (type) { // Match order mode
case "buy":
exchange.SetDirection(type); // Set order mode
return exchange.Buy(askPrice, unit);
case "sell":
exchange.SetDirection(type); // Set order mode
return exchange.Sell(bidPrice, unit);
case "closebuy":
exchange.SetDirection(type); // Set order mode
return exchange.Sell(bidPrice, unit);
case "closesell":
exchange.SetDirection(type); // Set order mode
return exchange.Buy(askPrice, unit);
default:
return false;
}
}
// cancel order
Data.prototype.cancelOrders = function () {
Sleep(500); // delay before canceling, because some exchanges you know...
var orders = _C(exchange.GetOrders); // Get the array of pending orders
if (orders.length > 0) { // if there is pending order
for (var i = 0; i < orders.length; i++) { //check through the array of pending orders
exchange.CancelOrder(orders[i].Id); //cancel pending orders one by one
Sleep(500); //Delay 0.5 seconds
}
return false; // return false if pending orders have been cancelled
}
return true; //return true if there is no pending order
}
// handle holding single contract
Data.prototype.isEven = function () {
var positionData = this.positionData; // get position data
var type = null; // converse position direction
// If the length of the position array divided by some number and the remainder is 2, the result is not equal to 0 or the length of the position array is not equal to 2
if (positionData.length % 2 != 0 || positionData.length != 2) {
for (var i = 0; i < positionData.length; i++) { // check through the array of positions
if (positionData[i].Type == 0) { // if it's long position
type = 10; // Set order parameters
} else if (positionData[i].Type == 1) { // if it's short position
type = -10; // Set order parameters
}
// close all positions
this.trade(positionData[i].ContractType, type, positionData[i].Amount);
}
}
}
// drawing chart
Data.prototype.drawingChart = function (boll) {
var nowTime = new Date().getTime();
ObjChart.add([0, [nowTime, boll.up]]);
ObjChart.add([1, [nowTime, boll.middle]]);
ObjChart.add([2, [nowTime, boll.down]]);
ObjChart.add([3, [nowTime, this.basb]]);
ObjChart.add([4, [nowTime, this.sabb]]);
ObjChart.update(chart);
}
// trading condition
function onTick() {
var data = new Data(tradeTypeA, tradeTypeB); // Create a base data object
var accountStocks = data.accountData.Stocks; // account balance
var boll = data.boll(dataLength, timeCycle); // get boll indicator data
if (!boll) return; // return if there is no boll data
// Spread description
// basb = (the latest selling price of contract A - the latest buying price of contract B)
// sabb = (the latest buying price of contract A - the latest selling price of contract B)
if (data.sabb > boll.middle && data.sabb < boll.up) { // if sabb is higher than the middle rail
if (data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
data.trade(tradeTypeA, "closebuy"); // close long position of contract A
}
if (data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
data.trade(tradeTypeB, "closesell"); // close short position of contract B
}
} else if (data.basb < boll.middle && data.basb > boll.down) { // if basb is lower than the middle rail
if (data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
data.trade(tradeTypeA, "closesell"); // close short position of contract A
}
if (data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
data.trade(tradeTypeB, "closebuy"); // close long position of contract B
}
}
if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
if (data.basb < boll.down) { // if basb spread is lower than the down rail
if (!data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
data.trade(tradeTypeA, "buy"); // open long position of contract A
}
if (!data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
data.trade(tradeTypeB, "sell"); // open short position of contract B
}
} else if (data.sabb > boll.up) { // if sabb spread is higher than the up rail
if (!data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
data.trade(tradeTypeA, "sell"); // open short position of contract A
}
if (!data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
data.trade(tradeTypeB, "buy"); // open long position of contract B
}
}
}
data.cancelOrders(); // cancel orders
data.drawingChart(boll); // drawing chart
data.isEven(); // process holding single contract
}
//enter function
function main() {
// filter the information that is not very important in the console
SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
exchange.IO("currency", name + '_USDT'); //Set the cryptocurrency type to be traded
ObjChart.reset(); //Empty the drawn charts before the program starts
LogProfitReset(); //Empty the status bar information before the program starts
while (true) { // Enter polling mode
onTick(); // Execute onTick function
Sleep(500); // sleep for o.5 seconds
}
}
Изобретатели количественного измерения - мечтыХорошо!