리소스 로딩... 로딩...

연구 환경에서의 도치안 통로 전략 분석

저자:선함, 2019-10-11 16:11:17, 업데이트: 2023-10-18 19:57:41

img

전략 개요

수많은 거래 전략들 중 가장 고전적인 돌파구 전략 중 하나라고 할 수 있는 도치안 통로 전략은 1970년대에 이미 유명해졌으며, 외국 소유의 회사들이 주류적인 절차적 거래 전략에 대한 특화된 시뮬레이션 테스트와 연구를 수행했을 때 그 결과 도치안 통로 전략이 모든 전략 테스트 중에서 가장 성공적이었다는 것을 보여준다.

나중에 미국에서 거래 역사상 가장 유명한 해파리 거래자 훈련이 일어 났고, 엄청난 성공을 거두었습니다. 당시 해파리의 거래 방법은 기밀이었지만, 해파리 거래법이 공개된 지 10여 년이 지나서야 해파리들이 사용하는 것이 개선된 도치안 통로 전략이라는 것이 밝혀졌습니다.

파격형 거래 전략은 유동성이 비교적 높은 거래 종류에 적합하며, 가장 일반적인 파격형 거래 방법은 가격과 지지 및 저항의 상대적 위치 관계를 활용하여 특정 거래의 매각 지점을 결정하는 것입니다. 이 섹션의 도치안 통로 전략은 이 원칙에 기반합니다.

치안 통로 전략 규칙

돈치안 통로는 트렌드형 지표로, 그 외관과 신호는 브린밴드 지표와 약간 비슷하다. 그러나 돈치안의 가격 통로는 일정 기간 동안의 최고 가격과 최저 가격에 따라 구성된다. 예를 들어, 최근 50개의 K선 최고 가격의 최대 값을 계산할 때, 궤도를 형성한다. 최근 50개의 K선 최저 가격의 최저 값을 계산할 때, 궤도를 형성한다.

img

위 그림과 같이: 이 지표는 3개의 다른 색상의 곡선으로 구성되어 있으며, 20주기 동안의 최고 가격과 최저 가격으로 기본으로 시장 가격의 변동성을 나타냅니다. 그 통로가 좁으면 시장 변동성이 작고 그 통로가 넓으면 시장 변동성이 크다는 것을 나타냅니다.

가격이 상승하고 상승할 때 시그널을 구매하고, 상승하고 하락할 때 시그널을 판매한다. 상승과 하락이 최고와 최저로 계산되기 때문에 일반적으로 가격이 상승하고 하락하는 통로선을 동시에 상승하고 하락하는 경우는 거의 없다. 대부분의 경우 가격은 상승과 하락의 일방적인 움직임, 또는 상승과 하락의 움직임에 따라 움직인다.

전략적 논리

도치안 채널의 사용 방법은 여러 가지가 있으며, 단독으로 사용하거나 다른 지표와 함께 사용할 수 있습니다. 이 섹션에서는 가장 간단한 사용 방법을 사용하겠습니다. 즉, 가격이 아래에서 위로 경로를 돌파할 때, 즉 상위 압력선을 돌파할 때, 우리는 다자 세력이 강해지고 있다고 생각합니다.

img

만약 오픈 포지션을 구매한 후 가격이 다시 도안 통로 중간에 떨어지면, 우리는 다자력이 약해지고 있거나, 상공력이 강화되고 있다고 생각하고, 평형 신호를 판매하고, 만약 오픈 포지션을 판매하고, 가격이 다시 도안 통로 중간에 떨어지면, 우리는 상공력이 약해지고 있거나, 다자력이 강화되고 있다고 생각하고, 상공력이 약해지고, 상공력 신호를 구매하고, 평형 신호를 생성한다.

구매 및 판매 조건

  • 다중 포지션 개시: 포지션이 없으면 포지션이 열리고 마감 가격은 상위보다 높습니다.
  • 빈 포지션 개설: 포지션이 없으면 마감 가격이 하락합니다.
  • 다중 평형: 여러 개의 주문을 보유하고 중간에 있는 가격보다 낮은 마감값을 가진 경우
  • 빈 상금: 빈 지표가 있고, 중장보다 더 높은 종결값이 있다면

전략 코드 구현

다음으로 우리는 발명가들의 양적 플랫폼 연구 환경에서 이 전략을 배웁니다.

발명가 양적 플랫폼의 연구 환경에 대해 아래와 같은 그림을 참조하십시오.

img

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) # 卖开


관련

더 많은