
多くの取引戦略の中で、ドンチャンチャネル戦略は最も古典的な画期的な戦略の1つであるはずです。1970年代にはすでによく知られていました。当時、外国の会社が主流のプログラム取引戦略のシミュレーションテストと研究を実施しました。その結果は、すべての戦略テストの中で、ドンチャン チャネル戦略が最も成功したことがわかりました。
その後、トレード史上最も有名な「タートル」トレーダーのトレーニングが米国で行われ、大きな成功を収めました。当時、「タートルズ」の取引方法は秘密にされていたが、10年以上経って「タートルズ取引ルール」が公開されると、「タートルズ」がドンチャンチャネルの改良版を使用していたことが判明した。戦略。
ブレークスルー取引戦略は、比較的滑らかなトレンドを持つ商品の取引に適しています。最も一般的なブレークスルー取引方法は、価格とサポートおよびレジスタンスの相対的な位置関係を使用して、特定の取引の売買ポイントを決定することです。このセクションのドンチャン チャネル戦略はこの原則に基づいています。
ドンチャン チャネルはトレンド インジケーターであり、その外観とシグナルはボリンジャー バンド インジケーターに多少似ています。しかし、ドンチャンの価格チャネルは、一定期間内の最高価格と最低価格に基づいて構築されます。たとえば、最新の 50 本の K ラインの最高価格の最大値を計算して上部のトラックを形成し、最新の 50 本の K ラインの最低価格の最小値を計算して下部のトラックを形成します。

上の図に示すように、この指標は3つの異なる色の曲線で構成されています。デフォルトでは、20サイクル内の最高値と最低値で、市場価格の変動性を示します。チャネルが狭い場合、市場の変動性が小さいことを意味します。それ以外の場合、チャネルは狭くなります。範囲が広いほど、市場のボラティリティが高いことを示します。
価格が上限の線を上回った場合は買いシグナル、逆に価格が下限の線を下回った場合は売りシグナルとなります。上限と下限のトラックは最高値と最低値を使用して計算されるため、通常の状況では、価格が同時に上限チャネルラインと下限チャネルラインを下回って上昇したり下落したりすることはほとんどありません。ほとんどの場合、価格は上側または下側の軌道に沿って、または上側と下側の軌道間で一方的に動きます。
ドンチャン チャネルを使用する方法は多数あります。単独で使用することも、他のインジケーターと組み合わせて使用することもできます。このコースでは最も簡単な方法を使用します。つまり、価格が下から上へ上向きの軌道を突破すると、つまり上圧力線を突破すると、強気の力が強まり、上昇相場の波が形成され、買い開始のシグナルが現れると考えられます。が生成されます。価格が上から下に下落し、下側のトラックを突破した場合、つまりサポートラインを下回った場合、ショートサイドが強くなり、下降トレンドが形成され、売り開始となると考えられます。信号が生成されます。

ロングポジションが開かれた後、価格がドンチャンチャネルの中間軌道まで下落した場合、強気派が弱まっているか弱気派が強まっていると判断され、売りシグナルが生成されます。価格が中間軌道まで下落した場合、ショートポジションが開かれた後にドンチャンチャネルの軌道を外れた場合、強気派が弱まっているか弱気派が強まっているとみなされ、売りシグナルが生成されます。ドンチャンチャネルの中間軌道に戻った場合、弱気派の力が弱まっているか、強気派の力が強まっており、買い終値シグナルが生成されます。
取引条件
次に、Inventor Quantitative Platform の研究環境でこの戦略を段階的に理解していきます。
Inventor Quantitative Platform の研究環境に入るには、次の図を参照してください。

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"}]
''')
# 创建回测环境
# 以上红色部分内容的关于回测信息的范例格式,可以在发明者量化平台的策略编写页面中点击“保存回测设置”获取# 首先,我们需要获取持仓信息,我们定义一个mp()函数用来干这件事
def mp():
positions = exchange.GetPosition() # 获取持仓数组
if len(positions) == 0: # 如果持仓数组的长度是0
return 0 # 证明是空仓,返回0
for i in range(len(positions)): # 遍历持仓数组
if (positions[i]['Type'] == PD_LONG) or (positions[i]['Type'] == PD_LONG_YD):
return 1 # 如果有多单,返回1
elif (positions[i]['Type'] == PD_SHORT) or (positions[i]['Type'] == PD_SHORT_YD):
return -1 # 如果有空单,返回-1
print(positions)
mp() # 接下来,我们执行一下这个获取持仓信息函数,可以看到,结果为0,也就是目前为空仓状态0
# 我们以当前螺纹钢主力合约为例子,开始测试这个策略
exchange.SetContractType("rb888") # 设置品种代码,主力合约为合约代码后加数字888{'CombinationType': 0,
'CreateDate': 0,
'DeliveryMonth': 9,
'DeliveryYear': 0,
'EndDelivDate': 0,
'ExchangeID': 'SHFE',
'ExchangeInstID': 'rb888',
'ExpireDate': 0,
'InstLifePhase': 49,
'InstrumentID': 'rb888',
'InstrumentName': 'rb连续',
'IsTrading': 1,
'LongMarginRatio': 0.06,
'MaxLimitOrderVolume': 500,
'MaxMarginSideAlgorithm': 49,
'MaxMarketOrderVolume': 30,
'MinLimitOrderVolume': 1,
'MinMarketOrderVolume': 1,
'OpenDate': 0,
'OptionsType': 48,
'PositionDateType': 49,
'PositionType': 50,
'PriceTick': 1,
'ProductClass': 49,
'ProductID': 'rb',
'ShortMarginRatio': 0.06,
'StartDelivDate': 0,
'StrikePrice': 0,
'UnderlyingInstrID': 'rb',
'UnderlyingMultiple': 1,
'VolumeMultiple': 10}接下来我们获取k线数组,因为根据策略逻辑,我们需要行情运行了一段时间,再进行逻辑判断,这样有便于我们的策略逻辑更好的适应行情,这里我们就暂且把50根K线作为起始要求吧。发明者量化的K线信息是以数组的形式储存的,数组里包含最高价,最低价,开盘价,收盘价和成交量等等信息,关于这部分的内容请查看发明者量化的官方API文档:https://www.fmz.com/api
# 接下来我们定义一个变量,让它来存储K线数组 records = exchange.GetRecords() # 获取K线数组
# 按照策略逻辑描述,我们用收盘价来作为开仓的价格,所以我们需要计算最新K线的收盘价 close = records[len(records) - 1].Close # 获取最新K线收盘价 close
3846.0
然后,我们需要以收盘价为标准计算50根k线中最高价的最大值和最低价的最小值
upper = TA.Highest(records, 50, 'High') # 获取50周期最高价的最大值 upper
3903.0
lower = TA.Lowest(records, 50, 'Low') # 获取50周期最低价的最小值 lower
3856.0
接着,我们需要计算这条通道的上轨和下轨的均值
middle = (upper + lower) / 2 # 计算上轨和下轨的均值 middle
3879.5
以上,关于此策略需要计算的部分我们已经全部完成,接下来,我们就要开始逻辑判断开仓条件,以及根据逻辑判断的结果进行实际的开仓操作。这里需要注意的是,我们需要用到发明者量化平台的国内商品期货模版,由于当下是研究环境,无法支持这个模版,我们暂且写出来,但是运行会报错,在发明者量化平台的策略编写页面进行实际编码时,导入此模版没有任何问题,模版地址为:https://www.fmz.com/strategy/24288 各位在发明者量化策略编写页面进行编码时,需要把此模版先复制到自己的策略库,然后在回测时勾选上,这里请各位读者注意
obj = ext.NewPositionManager() # 使用发明者量化交易类库,这里运行时会报错,不用理会,当下是研究环境,
# 实际编码过程中不会出现此问题,以下同此,不再注释。接下来是策略的判断逻辑,并且根据逻辑进行开仓与平仓操作
if positions > 0 and close < middle: # 如果持多单,并且收盘价跌破中轨
obj.CoverAll() # 平掉所有仓位
if positions < 0 and close > middle: # 如果持空单,并且收盘价升破中轨
obj.CoverAll() # 平掉所有仓位
if positions == 0: # 如果是空仓
if close > upper: # 如果收盘价升破上轨
obj.OpenLong("rb888", 1) # 买开
elif close < lower: # 如果收盘价跌破下轨
obj.OpenShort("rb888", 1) # 卖开# 完整的策略代码:
def mp():
positions = exchange.GetPosition() # 获取持仓数组
if len(positions) == 0: # 如果持仓数组的长度是0
return 0 # 证明是空仓,返回0
for i in range(len(positions)): # 遍历持仓数组
if (positions[i]['Type'] == PD_LONG) or (positions[i]['Type'] == PD_LONG_YD):
return 1 # 如果有多单,返回1
elif (positions[i]['Type'] == PD_SHORT) or (positions[i]['Type'] == PD_SHORT_YD):
return -1 # 如果有空单,返回-1
def main(): # 主函数
exchange.SetContractType("rb888") # 设置品种代码,主力合约为合约代码后加数字888
while True: # 进入循环
records = exchange.GetRecords() # 获取K线数组
if len(records) < 50: continue # 如果K线少于50根,就跳过本次循环
close = records[len(records) - 1].Close # 获取最新K线收盘价
positions = mp() # 获取持仓信息函数
upper = TA.Highest(records, 50, 'High') # 获取50周期最高价的最大值
lower = TA.Lowest(records, 50, 'Low') # 获取50周期最低价的最小值
middle = (upper + lower) / 2 # 计算上轨和下轨的均值
obj = ext.NewPositionManager() # 使用交易类库
if positions > 0 and close < middle: # 如果持多单,并且收盘价跌破中轨
obj.CoverAll() # 平掉所有仓位
if positions < 0 and close > middle: # 如果持空单,并且收盘价升破中轨
obj.CoverAll() # 平掉所有仓位
if positions == 0: # 如果是空仓
if close > upper: # 如果收盘价升破上轨
obj.OpenLong("rb888", 1) # 买开
elif close < lower: # 如果收盘价跌破下轨
obj.OpenShort("rb888", 1) # 卖开