Лучшие инструменты делают хорошую работу - научитесь использовать исследовательскую среду для анализа принципов торговли

Автор:Лидия., Создано: 2022-12-27 16:33:51, Обновлено: 2023-09-20 09:17:27

img

Лучшие инструменты помогают работать учитесь использовать исследовательскую среду для анализа принципов торговли

Термин "хеджирование" является очень базовым понятием в области количественной торговли и программной торговли. В количественной торговле цифровой валютой часто используются стратегии хеджирования: фьючерс-спот хеджирование, кросс-период хеджирование и спот хеджирование, которые по сути являются операциями на ценовые различия. Может быть, когда дело доходит до концепции, принципа и деталей хеджирования, многие студенты, которые только начали заниматься количественной торговлей, все еще не очень понятны.

В панели FMZ Quant кликните на Analyze, чтобы перейти на страницу инструмента:

img

Здесь я загружаю файл анализа напрямую: Этот анализ представляет собой анализ процесса открытия и закрытия позиции хеджирования фьючерс-спота во время обратного тестирования.quarterСпотный обмен представляет собой транзакцию валют-валюты OKX, а торговая пара -BTC_USDT. Для анализа процесса работы фьючерс-спот хеджирования, вы можете увидеть следующий конкретный файл исследовательской среды, написанный в двух версиях: версия языка Python, версия языка JavaScript.

Исследовательская среда файл языка Python

Анализ принципа хеджирования фьючерсов на месте.ipynb В [1]:

from fmz import *
task = VCtx('''backtest
start: 2019-09-19 00:00:00
end: 2019-09-28 12:00:00
period: 15m
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD", "stocks":1}, {"eid":"OKX","currency":"BTC_USDT","balance":10000,"stocks":0}]
''')
# Create backtesting environment
import matplotlib.pyplot as plt
import numpy as np
# Import the plot library matplotlib and library numpy

В [2]:

exchanges[0].SetContractType("quarter")    # The first exchange object OKX Futures (eid: Futures_OKCoin) calls the function to set the current contract as a quarterly contract
initQuarterAcc = exchanges[0].GetAccount() # The initial account information of OKX Futures Exchange is recorded in the variable initQuarterAcc
initQuarterAcc

Выбыли[2]: {Ставка: 0,0, ЗамороженнаяСтавка: 0,0, Стоки: 1,0, ЗамороженныеСтоки: 0,0}

В [3]:

initSpotAcc = exchanges[1].GetAccount()    # The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc
initSpotAcc

Выход[3]: {Ставка: 10000.0, СмороженнаяСтавка: 0.0, Стоки: 0.0, СмороженныеСтоки: 0.0}

В [4]:

quarterTicker1 = exchanges[0].GetTicker()  # Get the futures exchange ticker, recorded in the variable quarterTicker1
quarterTicker1

Выход[4]: Время: 1568851210000, высокий : 10441.25002, Низкий : 10441.25, Продажа : 10441.25002, Купить: 10441.25, Последний : 10441.25001, Комплект: 1772.0, Открытый интерес: 0.0}

В [5]:

spotTicker1 = exchanges[1].GetTicker()     # Get the spot exchange ticker, recorded in the variable spotTicker1
spotTicker1

Выход[5]: Время: 1568851210000, высокий : 10156.60000002, Низкий : 10156.6, Продажа : 10156.60000002, Купить: 10156,6, Последний : 10156.60000001, Комплект: 7.4443, Открытый интерес: 0.0}

В [6]:

quarterTicker1.Buy - spotTicker1.Sell      # The price difference between going short on futures and going long on spot.

Выход[6]: 284.64999997999985

В [7]:

exchanges[0].SetDirection("sell")                       # Set up a futures exchange and trade in the direction of going short
quarterId1 = exchanges[0].Sell(quarterTicker1.Buy, 10)  # Futures go short to place orders. The order quantity is 10 contracts. The returned order ID is recorded in the variable quarterId1.
exchanges[0].GetOrder(quarterId1)                       # Check the details of the order with futures order ID quarterId1.

Выход[7]: Идентификатор: 1, Цена : 10441.25, Стоимость: 10,0 Сумма сделки: 10,0 Средняя цена : 10441.25, Тип: 1, Оффсет: 0, Статус: 1, Контракт тип: bквартал}

В [8]:

spotAmount = 10 * 100 / quarterTicker1.Buy                 # Calculate the currency equivalent of 10 contracts as the order quantity of the spot.
spotId1 = exchanges[1].Buy(spotTicker1.Sell, spotAmount)   # Place orders on the spot exchange
exchanges[1].GetOrder(spotId1)                             # Check the order details of the spot order ID of spotId1

Вне[8]: Идентификатор: 1, Цена : 10156,60000002, Сумма : 0,0957, Сумма сделки: 0,0957, Средняя цена : 10156.60000002, Тип : 0, Оффсет: 0, Статус: 1, ContractType: bBTC_USDT_OKX}

Вы можете видеть, что заказы quarterId1 и spotId1 полностью выполнены, т.е. хеджирование открытых позиций завершено.

В [9]:

Sleep(1000 * 60 * 60 * 24 * 7)       # Hold the position for a while and wait for the price difference to become smaller to close the position.

После времени ожидания, приготовьтесь закрыть позицию.quarterTicker2, spotTicker2и распечатать их. Направление сделки объекта биржи фьючерсов настроено на закрытие короткой позиции:exchanges[0].SetDirection("closesell")разместить ордер на закрытие позиции. Напечатать данные ордера закрытия позиции, указывающие, что ордер закрытия завершен, позиция закрытия завершена.

В [10]:

quarterTicker2 = exchanges[0].GetTicker()     # Get the current futures exchange ticker, recorded in the variable quarterTicker2
quarterTicker2

Выход[10]: Время: 1569456010000, высокий: 8497.20002, Низкий : 8497.2, Продано: 8497.20002, Купить: 8497.2, Последний : 8497.20001, Объем : 4311.0, Открытый интерес: 0.0}

В [11]:

spotTicker2 = exchanges[1].GetTicker()       # Get the current ticker of the spot exchange, recorded in the variable spotTicker2
spotTicker2

Выход[11]: Время: 1569456114600, высокий: 8444.70000001, Низкий : 8444.69999999, Продажа: 8444.70000001, Купить: 8444.69999999, Последний : 8444,7, Объем : 78.6273, Открытый интерес: 0.0}

В [12]:

quarterTicker2.Sell - spotTicker2.Buy        # The price difference between closing a short futures position and closing a long spot position.

Выход[12]: 52.5000200100003

В [13]:

exchanges[0].SetDirection("closesell")                   # Set the current trading direction of the futures exchange to close short positions.
quarterId2 = exchanges[0].Buy(quarterTicker2.Sell, 10)   # The futures exchange places an order to close a position and records the order ID to the variable quarterId2.
exchanges[0].GetOrder(quarterId2)                        # Check futures close out order details

Выход[13]: Идентификатор: 2, Цена: 8497,20002, Стоимость: 10,0 Сумма сделки: 10,0 Средняя цена : 8493,95335, Тип : 0, Офсет: 1, Статус: 1, Контракт тип: bквартал}

В [14]:

spotId2 = exchanges[1].Sell(spotTicker2.Buy, spotAmount) # The spot exchange places an order to close a position and records the order ID, which is recorded to the variable spotId2.
exchanges[1].GetOrder(spotId2)      # Check spot close out order details

Выход[14]: Идентификатор: 2, Цена: 8444,69999999, Сумма : 0,0957, Сумма сделки: 0,0957, Средняя цена: 8444,69999999, Тип: 1, Оффсет: 0, Статус: 1, ContractType: bBTC_USDT_OKX}

В [15]:

nowQuarterAcc = exchanges[0].GetAccount()   # Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc

Выход[15]: {Бланк: 0,0, FrozenBalance: 0,0, Стоки: 1,021786026184, FrozenStocks: 0.0}

В [16]:

nowSpotAcc = exchanges[1].GetAccount()      # Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc

Выход[16]: (Ставка: 9834.74705446, FrozenBalance: 0,0, Стоки: 0,0, FrozenStocks: 0.0}

При сравнении первоначального счета с текущим счетом рассчитывается прибыль и убыток операции хеджирования.

В [17]:

diffStocks = abs(nowQuarterAcc.Stocks - initQuarterAcc.Stocks)
diffBalance = nowSpotAcc.Balance - initSpotAcc.Balance
if nowQuarterAcc.Stocks - initQuarterAcc.Stocks > 0 :
    print("profits:", diffStocks * spotTicker2.Buy + diffBalance)
else :
    print("profits:", diffBalance - diffStocks * spotTicker2.Buy)

Выход[17]: Прибыль: 18,72350977580652

Теперь давайте посмотрим, почему хеджирование выгодно. Мы можем увидеть рисунок. Цена фьючерса - синяя линия, а спотовая цена - оранжевая линия. Обе цены падают. Цена фьючерса падает быстрее, чем спотовая цена.

В [18]:

xQuarter = [1, 2]
yQuarter = [quarterTicker1.Buy, quarterTicker2.Sell]

xSpot = [1, 2]
ySpot = [spotTicker1.Sell, spotTicker2.Buy]
plt.plot(xQuarter, yQuarter, linewidth=5)
plt.plot(xSpot, ySpot, linewidth=5)
plt.show()

Выход[18]:

img

Давайте посмотрим на изменение ценовой разницы. Ценовая разница варьируется от 284 в момент хеджирования открывающей позиции (т.е. фьючерсы становятся короткими, а спот длинными) до 52 в момент закрытия позиции (фьючерсы короткие позиции закрываются, спот длинные позиции закрываются).

В [19]:

xDiff = [1, 2]
yDiff = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plt.plot(xDiff, yDiff, linewidth=5)
plt.show()

Выход[19]:

img

Например, a1 - это цена фьючерса в момент 1, а b1 - спотовая цена в момент 1. A2 - это цена фьючерса в момент 2, а b2 - спотовая цена в момент 2.До тех пор, пока разница спотовой цены фьючерсов в момент 1 (a1-b1) больше, чем разница спотовой цены фьючерсов в момент 2 (a2-b2), может быть введена a1 - a2>b1 - b2. Существует три ситуации: (количество фьючерсных и спотовых позиций одинаковое)

  1. a1 - a2 больше 0, b1 - b2 больше 0 a1 - a2 относится к ценовой разнице прибыли фьючерсов, а b1 - b2 относится к ценовой разнице спотовых потерь (поскольку спот ушел в длинный, цена начала покупки выше цены продажи для закрытия позиции, поэтому деньги теряются), но прибыли фьючерсов больше, чем спотовые убытки. Таким образом, это прибыльно в целом. Эта ситуация соответствует графику в шаге В [8].

  2. a1 - a2 больше 0, b1 - b2 меньше 0 a1 - a2 - ценовая разница прибыли от фьючерсов, а b1 - b2 - ценовая разница прибыли от спотов (b1 - b2 меньше 0, что указывает на то, что b2 больше, чем b1, то есть цена открытия и покупки позиции низкая, а цена продажи и закрытия высокая, поэтому она прибыльна).

  3. a1 - a2 меньше 0, b1 - b2 меньше 0 a1 - a2 - это ценовая разница фьючерсных убытков, а b1 - b2 - ценовая разница спотовых прибылей. Поскольку a1 - a2 > b1 - b2, абсолютная стоимость a1 - a2 меньше абсолютной стоимости b1 - b2, и спотовые прибыли больше, чем фьючерсные убытки.

Нет случая, когда a1 - a2 меньше 0, а b1 - b2 больше 0, потому что a1 - a2 > b1 - b2 было определено. Аналогично, если a1 - a2 равна 0, так как a1 - a2 > b1 - b2 определено, b1 - b2 должно быть меньше 0, поэтому, пока метод хеджирования коротких фьючерсов и длинных спотов отвечает условиям a1 - b1 > a2 - b2, операции по открытию и закрытию позиций являются хеджированием прибыли.

Например, следующая модель является одним из случаев:

В [20]:

a1 = 10
b1 = 5
a2 = 11
b2 = 9

# a1 - b1 > a2 - b2 launches: a1 - a2 > b1 - b2

xA = [1, 2]
yA = [a1, a2]

xB = [1, 2]
yB = [b1, b2]
plt.plot(xA, yA, linewidth=5)
plt.plot(xB, yB, linewidth=5)
plt.show()

Выход[20]:

img

Исследовательская среда Файл языка JavaScript

Исследовательская среда поддерживает не только Python, но и JavaScript Я также приведу пример исследовательской среды JavaScript:

Анализ принципа хеджирования фьючерсных спотов (JavaScript).ipynb В [1]:

// Import the required package, click "Save settings" on the FMZ's "Strategy editing page" to get the string configuration and convert it to an object.
var fmz = require("fmz")                           // Import the talib, TA, and plot libraries automatically after import
var task = fmz.VCtx({
start: '2019-09-19 00:00:00',
end: '2019-09-28 12:00:00',
period: '15m',
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD","stocks":1},{"eid":"OKX","currency":"BTC_USDT","balance":10000,"stocks":0}]
})

В [2]:

exchanges[0].SetContractType("quarter")  // The first exchange object OKX Futures (eid: Futures_OKCoin) calls the function to set the current contract as a quarterly contract.
var initQuarterAcc = exchanges[0].GetAccount()  // The initial account information of OKX Futures Exchange is recorded in the variable initQuarterAcc.
initQuarterAcc

Выход[2]: { Баланс: 0, FrozenBalance: 0, Запасы: 1, FrozenStocks: 0 }

В [3]:

var initSpotAcc = exchanges[1].GetAccount()     // The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc.
initSpotAcc

Выход[3]: { Баланс: 10000, FrozenBalance: 0, Запасы: 0, FrozenStocks: 0 }

В [4]:

var quarterTicker1 = exchanges[0].GetTicker()   // Get the futures exchange ticker, recorded in the variable quarterTicker1.
quarterTicker1

Выход[4]: { Время: 1568851210000, Высокий: 10441,25002, Низкий уровень: 10441,25. Продать: 10441.25002, Купить: 10441.25, Последнее: 10441.25001, Объем: 1772 Открытый интерес:

В [5]:

var spotTicker1 = exchanges[1].GetTicker()     // Get the spot exchange ticker, recorded in the variable spotTicker1.
spotTicker1

Выход[5]: Время: 1568851210000, Высокий: 10156.60000002, Низкий уровень: 10156,6. Продать: 10156.60000002, Купить: 10156.6, Последнее: 10156.60000001, Объем: 7.4443, Открытый интерес:

В [6]:

quarterTicker1.Buy - spotTicker1.Sell         // The price difference between going short on futures and going long on spot.

Выход[6]: 284.64999997999985 В [7]:

exchanges[0].SetDirection("sell")             // Set up a futures exchange and trade in the direction of going short
var quarterId1 = exchanges[0].Sell(quarterTicker1.Buy, 10)  // Go short futures to place orders. The order quantity is 10 contracts. The returned order ID is recorded in the variable quarterId1.
exchanges[0].GetOrder(quarterId1)                           // Check the details of the order with futures order ID quarterId1.

Выход[7]: { Идентификатор: 1, Цена: 10441.25, Сумма: 10 Сумма сделки: 10, Средняя цена: 10441,25. Тип: 1, Сдвиг: 0, Статус: 1, Контракт тип: квартал }

В [8]:

var spotAmount = 10 * 100 / quarterTicker1.Buy                  // Calculate the currency equivalent of 10 contracts as the order quantity of the spot.
var spotId1 = exchanges[1].Buy(spotTicker1.Sell, spotAmount)    // Place orders on the spot exchange.
exchanges[1].GetOrder(spotId1)                                  // Check the order details of the spot order ID of spotId1.

Вне[8]: { Идентификатор: 1, Цена: 10156,60000002, Сумма: 0,0957, Сумма сделки: 0,0957, Средняя цена: 10156.60000002, Тип: 0, Сдвиг: 0, Статус: 1, Контракт тип: BTC_USDT_OKX }

Вы можете видеть, что заказы quarterId1 и spotId1 полностью выполнены, т.е. хеджирование открытых позиций завершено.

В [9]:

Sleep(1000 * 60 * 60 * 24 * 7)            // Hold the position for a while and wait for the price difference to become smaller to close the position.

После времени ожидания, приготовьтесь закрыть позицию.quarterTicker2, spotTicker2и распечатать их. Направление сделки объекта биржи фьючерсов настроено на закрытие короткой позиции:exchanges[0].SetDirection("closesell")разместить ордер на закрытие позиции. Напечатать данные ордера закрытия позиции, указывающие, что ордер закрытия завершен, позиция закрытия завершена.

В [10]:

var quarterTicker2 = exchanges[0].GetTicker()    // Get the current futures exchange ticker, recorded in the variable quarterTicker2.
quarterTicker2

Выход[10]: Время: 1569456010000, Высокий: 8497.20002, Низкий показатель: 8497,2. Продать: 8497.20002, Купить: 8497.2, Последний: 8497.20001, Объем: 4311, Открытый интерес:

В [11]:

var spotTicker2 = exchanges[1].GetTicker()       // Get the current ticker of the spot exchange, recorded in the variable spotTicker2.
spotTicker2

Выход[11]: { Время: 1569456114600, Высокий: 8444.70000001, Низкий уровень: 8444,69999999, Продать: 8444.70000001, Купить: 8444.69999999, Последнее: 8444,7, Объем: 78.6273, Открытый интерес:

В [12]:

quarterTicker2.Sell - spotTicker2.Buy            // The price difference between closing short position of futures and closing long position of spot.

Выход[12]: 52.5000200100003

В [13]:

exchanges[0].SetDirection("closesell")           // Set the current trading direction of the futures exchange to close short positions.
var quarterId2 = exchanges[0].Buy(quarterTicker2.Sell, 10)       // The futures exchange places an order to close the position, and records the order ID to the variable quarterId2.
exchanges[0].GetOrder(quarterId2)                                // Check futures closing position order details.

Выход[13]: Идентификатор: 2, Цена: 8497,20002, Сумма: 10 Сумма сделки: 10, Средняя цена: 8493,95335, Тип: 0, Замещение: 1, Статус: 1, Контракт тип: квартал }

В [14]:

var spotId2 = exchanges[1].Sell(spotTicker2.Buy, spotAmount)     // The spot exchange places an order to close the position, and records the order ID to the variable spotId2.
exchanges[1].GetOrder(spotId2)                                   // Check spot closing position order details.

Выход[14]: Идентификатор: 2, Цена: 8444,69999999, Сумма: 0,0957, Сумма сделки: 0,0957, Средняя цена: 8444,69999999, Тип: 1, Сдвиг: 0, Статус: 1, Контракт тип: BTC_USDT_OKX }

В [15]:

var nowQuarterAcc = exchanges[0].GetAccount()     // Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc                                     

Выход[15]: { Сальдо: 0, Замороженный баланс: 0, Запасы: 1,021786026184, ФрозенСтокс: 0 }

В [16]:

var nowSpotAcc = exchanges[1].GetAccount()        // Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc

Выход[16]: { Остаток: 9834.74705446, Замороженный баланс: 0, Запасы: 0, Замороженные запасы: При сравнении первоначального счета с текущим счетом рассчитывается прибыль и убыток операции хеджирования.

В [17]:

var diffStocks = Math.abs(nowQuarterAcc.Stocks - initQuarterAcc.Stocks)
var diffBalance = nowSpotAcc.Balance - initSpotAcc.Balance
if (nowQuarterAcc.Stocks - initQuarterAcc.Stocks > 0) {
    console.log("profits:", diffStocks * spotTicker2.Buy + diffBalance)
} else {
    console.log("profits:", diffBalance - diffStocks * spotTicker2.Buy)
}

Выход[17]: Прибыль: 18,72350977580652

Теперь давайте посмотрим, почему хеджирование выгодно. Мы можем увидеть рисунок. Цена фьючерса - синяя линия, а спотовая цена - оранжевая линия. Обе цены падают. Цена фьючерса падает быстрее, чем спотовая цена.

В [18]:

var objQuarter = {
    "index" : [1, 2],                                          // The index is 1, that is, the first time, the opening time, and 2 is the closing time.
    "arrPrice" : [quarterTicker1.Buy, quarterTicker2.Sell],
}
var objSpot = {
    "index" : [1, 2],
    "arrPrice" : [spotTicker1.Sell, spotTicker2.Buy],
}
plot([{name: 'quarter', x: objQuarter.index, y: objQuarter.arrPrice}, {name: 'spot', x: objSpot.index, y: objSpot.arrPrice}])

Выход[18]: Давайте посмотрим на изменение ценовой разницы. Ценовая разница варьируется от 284 в момент хеджирования открывающихся позиций (то есть фьючерсы шли коротко, а спот шел длинно) до 52 в момент закрытия (закрытие короткой позиции фьючерсов и закрытие длинной позиции спота).

В [19]:

var arrDiffPrice = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plot(arrDiffPrice)

Выход[19]:Например, a1 - это цена фьючерса в момент 1, а b1 - спотовая цена в момент 1. A2 - это цена фьючерса в момент 2, а b2 - спотовая цена в момент 2.До тех пор, пока разница спотовой цены фьючерсов в момент 1 (a1-b1) больше, чем разница спотовой цены фьючерсов в момент 2 (a2-b2), может быть введена a1 - a2>b1 - b2. Существует три ситуации: (количество фьючерсных и спотовых позиций одинаковое)

  1. a1 - a2 больше 0, b1 - b2 больше 0 a1 - a2 относится к ценовой разнице прибыли фьючерсов, а b1 - b2 относится к ценовой разнице спотовых потерь (поскольку спот ушел в длинный, цена начала покупки выше цены продажи для закрытия позиции, поэтому деньги теряются), но прибыли фьючерсов больше, чем спотовые убытки. Таким образом, это прибыльно в целом. Эта ситуация соответствует графику в шаге В [8].

  2. a1 - a2 больше 0, b1 - b2 меньше 0 a1 - a2 - ценовая разница прибыли от фьючерсов, а b1 - b2 - ценовая разница прибыли от спотов (b1 - b2 меньше 0, что указывает на то, что b2 больше, чем b1, то есть цена открытия и покупки позиции низкая, а цена продажи и закрытия высокая, поэтому она прибыльна).

  3. a1 - a2 меньше 0, b1 - b2 меньше 0 a1 - a2 - это ценовая разница фьючерсных убытков, а b1 - b2 - ценовая разница спотовых прибылей. Поскольку a1 - a2 > b1 - b2, абсолютная стоимость a1 - a2 меньше абсолютной стоимости b1 - b2, и спотовые прибыли больше, чем фьючерсные убытки.

Нет случая, когда a1 - a2 меньше 0, а b1 - b2 больше 0, потому что a1 - a2 > b1 - b2 было определено. Аналогично, если a1 - a2 равна 0, так как a1 - a2 > b1 - b2 определено, b1 - b2 должно быть меньше 0, поэтому, пока метод хеджирования коротких фьючерсов и длинных спотов отвечает условиям a1 - b1 > a2 - b2, операции по открытию и закрытию позиций являются хеджированием прибыли.

Например, следующая модель является одним из случаев:

В [20]:

var a1 = 10
var b1 = 5
var a2 = 11
var b2 = 9

// a1 - b1 > a2 - b2 launches: a1 - a2 > b1 - b2

var objA = {
    "index" : [1, 2],
    "arrPrice" : [a1, a2],
}
var objB = {
    "index" : [1, 2],
    "arrPrice" : [b1, b2],
}
plot([{name : "a", x : objA.index, y : objA.arrPrice}, {name : "b", x : objB.index, y : objB.arrPrice}])

Выход[20]:

Попробуйте, ребята!


Связанные

Больше