Среди многих торговых стратегий, стратегия Дончианского канала должна быть одной из самых классических прорывных стратегий. Она была известна еще в 1970 году. В то время иностранная компания проводила симуляционные испытания и исследования основных программных торговых стратегий. Результаты показали, что стратегия Дончианского канала была самой успешной из всех стратегических тестов.
Позже в Соединенных Штатах состоялось самое известное обучение трейдеров-черепах в истории торговли, которое имело большой успех.
Прорывная стратегия торговли подходит для торговли сортами с относительно плавным трендом. Наиболее распространенным методом торговли прорывом является использование относительной позиционной связи между ценой, поддержкой и сопротивлением для оценки конкретной торговой точки. Стратегия Дончианского канала в этой статье также основана на этом принципе.
Канал Дончиана - это индикатор тренда, и его внешний вид и сигнал несколько похожи на индикатор полосы Боллинджера. Однако ценовой канал Дончиана построен в соответствии с самой высокой ценой и самой низкой ценой в течение определенного периода. Например, максимальное значение самой высокой цены последних 50 K-линий рассчитывается, чтобы сформировать верхний трек; Вычислить минимальное значение самой низкой цены последних 50 K-линий, чтобы сформировать нижний трек.
Как показано на рисунке выше, этот индикатор состоит из трех кривых с разными цветами. По умолчанию для показа волатильности рыночных цен используются самые высокие и самые низкие цены в течение 20 периодов. Когда канал узкий, это означает, что волатильность рынка мала. Наоборот, когда канал широк, это означает, что волатильность рынка велика.
Если цена поднимается выше верхнего трека, это сигнал покупки; наоборот, если цена падает ниже нижнего трека, это сигнал продажи. Поскольку верхние и нижние треки рассчитываются по самым высоким и самым низким ценам, в целом цены редко поднимаются и падают ниже верхней и нижней линий канала одновременно. В большинстве случаев цена движется вдоль верхних или нижних треков в одностороннем порядке или между верхними и нижними треками.
Существует множество способов использования Дончианского канала, который можно использовать в одиночку или в сочетании с другими индикаторами. В этом уроке мы будем использовать самый простой метод. То есть, когда цена проходит через верхний трек снизу вверх, то есть выше линии давления, мы считаем, что сила многих сторон растет, волна растущего рынка сформирована, и был сгенерирован сигнал покупки открытой позиции; Когда цена падает ниже нижнего трек сверху вниз, то есть ниже линии поддержки, мы считаем, что сторону короткой позиции укрепляет, волна нисходящего тренда сформирована, и был сгенерирован сигнал открытия продажной позиции.
Если цена после покупки для открытия позиции опускается обратно на средний трек Дончянского канала, мы считаем, что сила многопартийных усилий ослабевает или сила группы коротких позиций укрепляется, и генерируется сигнал продажи и закрытия позиции; если цена поднимается обратно на средний трек Дончянского канала после открытия продажной позиции, мы считаем, что сторона короткой позиции ослабевает или силы многопартийных усилий укрепляются, и генерируется сигнал закрытия позиции покупки.
Условия покупки и продажи
Далее мы будем понимать эту стратегию по одному в исследовательской среде платформы FMZ Quant:
Введите исследовательскую среду платформы FMZ Quant, как показано ниже:
Стратегия канала Дончиана в Python version.ipynb В [1]:
from fmz import *
task = VCtx('''backtest
start: 2019-08-01 09:00:00
end: 2019-10-10 15:00:00
period: 5m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
''')
# Create a Backtesting Environment
# The example format of the backtest information in red above can be obtained by clicking "Save settings" on the strategy edting page of the FMZ Quant platform.
В [2]:
# First, we need to get the position information, and we define a mp() function to do this.
def mp():
positions = exchange.GetPosition() # Get position array
if len(positions) == 0: # If the length of the position array is 0
return 0 # Prove a short position, return 0
for i in range(len(positions)): # Iterate through the positions array
if (positions[i]['Type'] == PD_LONG) or (positions[i]['Type'] == PD_LONG_YD):
return 1 # If there are long position orders, return 1
elif (positions[i]['Type'] == PD_SHORT) or (positions[i]['Type'] == PD_SHORT_YD):
return -1 # If there are short position orders, return -1
print(positions)
mp() # Next, we execute this function to get the position information, and we can see that the result is 0, which means that the current position is short.
Выход[2]:0
В [3]:
# Let's start testing this strategy using the current main rebar contract as an example.
exchange.SetContractType("rb888") # Set the variety code, the main contract is the contract code followed by the number 888.
Выход[3]:
{
Далее мы получаем K-линейный массив, потому что в соответствии со стратегической логикой нам нужно, чтобы рынок работал в течение определенного периода времени, а затем делать логические суждения, чтобы наша стратегическая логика могла лучше адаптироваться к рынку. Здесь мы примем 50 K-линий в качестве исходного требования временно.https://www.fmz.com/api
В [4]:
# Next we define a variable to store the K-line array.
records = exchange.GetRecords() # Get the K-line array
В [5]:
# According to the strategy logic description, we use the closing price as the price to open a position, so we need to calculate the closing price of the latest K-line.
close = records[len(records) - 1].Close # Get the latest K-line closing price
close
Выход[5]: 3846,0
Затем нам нужно вычислить максимальное значение самой высокой цены и минимальное значение самой низкой цены в 50 K-линиях, используя цену закрытия в качестве стандарта.
В [6]:
upper = TA.Highest(records, 50, 'High') # Get the maximum value of the 50-period maximum price
upper
Выход[6]: 3903.0
В [7]:
lower = TA.Lowest(records, 50, 'Low') # Get the minimum value of the 50-period minimum price
lower
Выход[7]: 3856,0
Далее нам нужно вычислить среднее значение верхних и нижних путей этого канала.
В [8]:
middle = (upper + lower) / 2 # Calculate the average value of the upper and lower tracks.
middle
Вне[8]: 3879,5
Выше мы завершили все расчеты, необходимые для этой стратегии. Далее мы начнем логически судить о условиях открытия и выполним фактическую операцию открытия позиции в соответствии с результатами логического суждения. Здесь следует отметить, что нам нужно использовать домашний фьючерсный шаблон товара платформы FMZ Quant. Поскольку текущая исследовательская среда не может поддерживать этот шаблон, мы временно его напишем, но операция будет сообщать об ошибке, на странице написания стратегии платформы FMZ Quant для фактического кодирования импортируйте этот шаблон без каких-либо проблем, адрес шаблона:https://www.fmz.com/strategy/24288. Когда вы кодируете на странице редактирования стратегии платформы FMZ Quant, вам нужно сначала скопировать этот шаблон в свою собственную библиотеку стратегий, а затем проверить его при обратном тестировании.
В [ ]:
obj = ext.NewPositionManager() # When using the FMZ Quant trading class library, errors will be reported at runtime, which can be ignored. Now it is the research environment,
# This problem does not occur during the actual coding process, and the following is the same without further comment.
Следующим шагом является определение логики стратегии и открытие и закрытие позиций в соответствии с логикой.
В [ ]:
if positions > 0 and close < middle: # If you hold a long position order and the closing price falls below the middle track
obj.CoverAll() # Close all positions
if positions < 0 and close > middle: # If you hold a short position order and the closing price rises above the middle track
obj.CoverAll() # Close all positions
if positions == 0: # If it's a short position
if close > upper: # If the closing price rises above the upper track
obj.OpenLong("rb888", 1) # Buy opening positions
elif close < lower: # If the closing price falls below the lower track
obj.OpenShort("rb888", 1) # Sell opening positions
В [ ]:
# Complete strategy code:
def mp():
positions = exchange.GetPosition() # Get the position array
if len(positions) == 0: # If the length of the position array is 0
return 0 # It proved a short position, return 0
for i in range(len(positions)): # Iterate through the positions array
if (positions[i]['Type'] == PD_LONG) or (positions[i]['Type'] == PD_LONG_YD):
return 1 # If there are long position orders, return 1
elif (positions[i]['Type'] == PD_SHORT) or (positions[i]['Type'] == PD_SHORT_YD):
return -1 # If there are short position orders, return -1
def main(): # Main function
exchange.SetContractType("rb888") # Set the variety code, the main contract is the contract code followed by the number 888
while True: # Enter the loop
records = exchange.GetRecords() # Get the K-line array
if len(records) < 50: continue # If there are less than 50 K-lines, skip the loop
close = records[len(records) - 1].Close # Get the latest K-line closing price
positions = mp() # Get position information function
upper = TA.Highest(records, 50, 'High') # Get the maximum value of the 50-period maximum price
lower = TA.Lowest(records, 50, 'Low') # Get the minimum value of the 50-period minimum price
middle = (upper + lower) / 2 # Calculate the average value of the upper and lower tracks
obj = ext.NewPositionManager() # Use the Trading Library
if positions > 0 and close < middle: # If you hold a long position order and the closing price falls below the middle track
obj.CoverAll() # Close all positions
if positions < 0 and close > middle: # If you hold a short position order and the closing price rises above the middle track
obj.CoverAll() # Close all positions
if positions == 0: # If it's a short position
if close > upper: # If the closing price rises above the upper track
obj.OpenLong("rb888", 1) # Buy opening positions
elif close < lower: # If the closing price falls below the lower track
obj.OpenShort("rb888", 1) # Sell opening positions