Example #1
0
    def __init__(self,
                 account_id,
                 symbol,
                 donchian_channel_open_position=20,
                 donchian_channel_stop_profit=10,
                 atr_day_length=20):
        self.account_id = account_id
        self.symbol = symbol  # 合约代码
        self.donchian_channel_open_position = donchian_channel_open_position  # 唐奇安通道的天数周期(开仓)
        self.donchian_channel_stop_profit = donchian_channel_stop_profit  # 唐奇安通道的天数周期(止盈)
        self.atr_day_length = atr_day_length  # ATR计算所用天数
        self.state = {
            "position": 0,  # 本策略净持仓数(正数表示多头,负数表示空头,0表示空仓)
            "last_price": float("nan"),  # 上次调仓价
        }

        self.n = 0
        self.unit = 0
        self.donchian_channel_high = 0
        self.donchian_channel_low = 0

        self.api = TqApi(self.account_id)
        self.quote = self.api.get_quote(self.symbol)
        # 由于ATR是路径依赖函数,因此使用更长的数据序列进行计算以便使其值稳定下来
        kline_length = max(donchian_channel_open_position + 1,
                           donchian_channel_stop_profit + 1,
                           atr_day_length * 5)
        self.klines = self.api.get_kline_serial(self.symbol,
                                                24 * 60 * 60,
                                                data_length=kline_length)
        self.account = self.api.get_account()
        self.target_pos = TargetPosTask(self.api,
                                        self.symbol,
                                        init_pos=self.state["position"])
Example #2
0
 def parity_quote_task(self, opt: dict, future_id: str, future_target_pos):
     call_quote = self.api.get_quote(opt['c'])
     put_quote = self.api.get_quote(opt['p'])
     future_quote = self.api.get_quote(future_id)
     #future_target_pos = TargetPosTask(self.api, future_id)
     call_target_pos = TargetPosTask(self.api, opt['c'])
     put_target_pos = TargetPosTask(self.api, opt['p'])
     put_position = self.api.get_position(opt['p'])
     self._put_vols[opt['K']] = put_position.pos
     self.api.create_task(
         self.quote_watcher(future_quote, opt['K'], call_quote, put_quote,
                            future_target_pos, call_target_pos,
                            put_target_pos))
     print('Quote subscribed ' + str(opt))
Example #3
0
def subscribe_main_parity(
    api,
    future_symbol,
    future_product_id,
    option_product_id,
    long_call,
    short_call,
    min_strike,
    max_strike,
    return_threshold=0.1,
    max_margin=4000,
):
    """
        对某个基础资产进行put-call parity异步套利。
    """

    # 取主力合约的信息
    kq_m = api.get_quote("KQ.m@" + future_symbol)
    # 用主力合约的symbol订阅报价
    future = api.get_quote(kq_m.underlying_symbol)
    # 初始化期货-期权信息
    opt_api = TqOption(
        api,
        underlying_future_id=kq_m.underlying_symbol,
        option_product_id=option_product_id,
    )
    # 按照行权价范围,选择需要的期权合约组合
    _, opts = opt_api.get_future_opt_symbols(
        strike_year=future.delivery_year,  #行权年
        strike_month=future.delivery_month,  #行权月
        min_strike=min_strike,  #最小行权价
        max_strike=max_strike,  #最大行权价
    )
    # 设定开仓信号:put-call parity residual的开仓临界值
    trade = OptionTrade(
        api,
        opt_api,
        kq_m.underlying_symbol,  #主力合约的symbol
        opts,
        can_trade=True,  #是否支持交易
        save_data=False,  #是否存储数据
        long_call_threshold=long_call,  #开仓方案一:买call、卖put、空期货的开仓临界值,可None
        long_put_threshold=short_call,  #开仓方案一:买put、卖call、多期货的开仓临界值,可None
        return_threshold=return_threshold,  #开仓方案二:按照理论收益率(=残差/保证金占用)来开仓,可None
        max_margin=max_margin,  #最大保证金占用,可None
    )
    global trade_dict
    # 使用future_symbol可以查询这组put-call parity arbitrage对象
    trade_dict[future_product_id] = trade
    print("期货代码:" + kq_m.underlying_symbol)
    future_target_pos = TargetPosTask(api, kq_m.underlying_symbol)
    # 订阅所有的期权合约套利组
    for opt in opts.values():
        trade.parity_quote_task(opt, kq_m.underlying_symbol, future_target_pos)
Example #4
0
    def trade_group(self, strike_price: float, future_vol: int,
                    future: TargetPosTask, call: TargetPosTask,
                    put: TargetPosTask):
        """
            交易期权、期货组合套利

            Args:

                future_vol > 0, 对应long call + short put + short期货

        """
        call.set_target_volume(future_vol * self._option_multiplier)
        put.set_target_volume(-future_vol * self._option_multiplier)
        self._put_vols[strike_price] = -future_vol * self._option_multiplier
        future_target_vol = int(
            sum(self._put_vols.values()) / self._option_multiplier)
        future.set_target_volume(future_target_vol)
Example #5
0
__author__ = 'yanqiong'

from tqsdk.api import TqApi
from tqsdk.lib import TargetPosTask

'''
连续3根阴线就做空,连续3根阳线就做多,否则空仓
'''

api = TqApi("SIM")
# 设定连续多少根阳线/阴线
length = 3
# 获得 rb1901 10秒K线的引用, 长度为 length+1
klines = api.get_kline_serial("SHFE.rb1901", 10, data_length = length + 1)
# 创建 rb1901 的目标持仓 task,该 task 负责调整 rb1901 的仓位到指定的目标仓位, offset_priority的用法详见文档
target_pos = TargetPosTask(api, "SHFE.rb1901", offset_priority="今昨开")

while True:
    api.wait_update()
    # 只有在新创建出K线时才判断开平仓条件
    if api.is_changing(klines[-1], "datetime"):
        # 将K线转为pandas.DataFrame, 跳过最后一根刚生成的K线
        df = klines.to_dataframe()[:-1]
        # 比较收盘价和开盘价,判断是阳线还是阴线
        # df["close"] 为收盘价序列, df["open"] 为开盘价序列, ">"(pandas.Series.gt) 返回收盘价是否大于开盘价的一个新序列
        up = df["close"] > df["open"]
        down = df["close"] < df["open"]
        if all(up):
            print("连续阳线: 目标持仓 多头1手")
            # 设置目标持仓为正数表示多头,负数表示空头,0表示空仓
            target_pos.set_target_volume(1)
Example #6
0
class Turtle:
    def __init__(self,
                 account_id,
                 symbol,
                 donchian_channel_open_position=20,
                 donchian_channel_stop_profit=10,
                 atr_day_length=20):
        self.account_id = account_id
        self.symbol = symbol  # 合约代码
        self.donchian_channel_open_position = donchian_channel_open_position  # 唐奇安通道的天数周期(开仓)
        self.donchian_channel_stop_profit = donchian_channel_stop_profit  # 唐奇安通道的天数周期(止盈)
        self.atr_day_length = atr_day_length  # ATR计算所用天数
        self.state = {
            "position": 0,  # 本策略净持仓数(正数表示多头,负数表示空头,0表示空仓)
            "last_price": float("nan"),  # 上次调仓价
        }

        self.n = 0
        self.unit = 0
        self.donchian_channel_high = 0
        self.donchian_channel_low = 0

        self.api = TqApi(self.account_id)
        self.quote = self.api.get_quote(self.symbol)
        # 由于ATR是路径依赖函数,因此使用更长的数据序列进行计算以便使其值稳定下来
        kline_length = max(donchian_channel_open_position + 1,
                           donchian_channel_stop_profit + 1,
                           atr_day_length * 5)
        self.klines = self.api.get_kline_serial(self.symbol,
                                                24 * 60 * 60,
                                                data_length=kline_length)
        self.account = self.api.get_account()
        self.target_pos = TargetPosTask(self.api,
                                        self.symbol,
                                        init_pos=self.state["position"])

    def recalc_paramter(self):
        try:
            df = self.klines.to_dataframe()
            # 本交易日的平均真实波幅(N值)
            self.n = talib.ATR(df["high"],
                               df["low"],
                               df["close"],
                               timeperiod=self.atr_day_length).iloc[-1]
            # 买卖单位
            self.unit = int((self.account["balance"] * 0.01) /
                            (self.quote["volume_multiple"] * self.n))
            print('atr:', self.n, "  unit:", self.unit)

            # 唐奇安通道上轨:前N个交易日的最高价
            self.donchian_channel_high = max(
                self.klines.high[-self.donchian_channel_open_position - 1:-1])
            # 唐奇安通道下轨:前N个交易日的最低价
            self.donchian_channel_low = min(
                self.klines.low[-self.donchian_channel_open_position - 1:-1])
            print("唐其安通道上下轨:", self.donchian_channel_high,
                  self.donchian_channel_low)
        except Exception:  # 若尚未接收到数据, 即数据为NaN, 则在ATR或unit计算时会报错
            return False
        return True

    def set_position(self, pos):
        self.state["position"] = pos
        self.state["last_price"] = self.quote["last_price"]
        self.target_pos.set_target_volume(self.state["position"])

    def try_open(self):
        """开仓策略"""
        while self.state["position"] == 0:
            self.api.wait_update()
            if self.api.is_changing(self.klines[-1],
                                    "datetime"):  # 如果产生新k线,则重新计算唐奇安通道及买卖单位
                self.recalc_paramter()
            if self.api.is_changing(self.quote, "last_price"):
                print("最新价: ", self.quote["last_price"])
                if self.quote[
                        "last_price"] > self.donchian_channel_high:  # 当前价>唐奇安通道上轨,买入1个Unit;(持多仓)
                    print("当前价>唐奇安通道上轨,买入1个Unit(持多仓):", self.unit, "手")
                    self.set_position(self.state["position"] + self.unit)
                elif self.quote[
                        "last_price"] < self.donchian_channel_low:  # 当前价<唐奇安通道下轨,卖出1个Unit;(持空仓)
                    print("当前价<唐奇安通道下轨,卖出1个Unit(持空仓):", self.unit, "手")
                    self.set_position(self.state["position"] - self.unit)

    def try_close(self):
        """交易策略"""
        while self.state["position"] != 0:
            self.api.wait_update()
            if self.api.is_changing(self.quote, "last_price"):
                print("最新价: ", self.quote["last_price"])

                if self.state["position"] > 0:  # 持多单
                    # 加仓策略: 如果是多仓且资产的价格在上一次建仓(或者加仓)的基础上又上涨了0.5N,就再加一个Unit的多仓
                    if self.quote["last_price"] >= self.state[
                            "last_price"] + 0.5 * self.n:
                        print("加仓:加1个Unit的多仓")
                        self.set_position(self.state["position"] + self.unit)
                    # 止损策略: 如果是多仓且资产的价格在上一次建仓(或者加仓)的基础上又下跌了2N,就卖出全部头寸止损
                    elif self.quote["last_price"] <= self.state[
                            "last_price"] - 2 * self.n:
                        print("止损:卖出全部头寸")
                        self.set_position(0)
                    # 止盈策略: 如果是多仓且当前资产价格跌破了10日唐奇安通道的下轨,就清空所有头寸结束策略,离场
                    if self.quote["last_price"] <= min(
                            self.klines.
                            low[-self.donchian_channel_stop_profit - 1:-1]):
                        print("止盈:清空所有头寸结束策略,离场")
                        self.set_position(0)

                elif self.state["position"] < 0:  # 持空单
                    # 加仓策略: 如果是空仓且资产的价格在上一次建仓(或者加仓)的基础上又下跌了0.5N,就再加一个Unit的空仓
                    if self.quote["last_price"] <= self.state[
                            "last_price"] - 0.5 * self.n:
                        print("加仓:加1个Unit的空仓")
                        self.set_position(self.state["position"] - self.unit)
                    # 止损策略: 如果是空仓且资产的价格在上一次建仓(或者加仓)的基础上又上涨了2N,就平仓止损
                    elif self.quote["last_price"] >= self.state[
                            "last_price"] + 2 * self.n:
                        print("止损:卖出全部头寸")
                        self.set_position(0)
                    # 止盈策略: 如果是空仓且当前资产价格升破了10日唐奇安通道的上轨,就清空所有头寸结束策略,离场
                    if self.quote["last_price"] >= max(
                            self.klines.
                            high[-self.donchian_channel_stop_profit - 1:-1]):
                        print("止盈:清空所有头寸结束策略,离场")
                        self.set_position(0)

    def strategy(self):
        """海龟策略"""
        print("等待K线及账户数据...")
        deadline = time.time() + 5
        while not self.recalc_paramter():
            if not self.api.wait_update(deadline=deadline):
                raise Exception("获取数据失败,请确认行情连接正常并已经登录交易账户")
        while True:
            self.try_open()
            self.try_close()
Example #7
0
    sSetup = pivot + (high - low)  # 观察卖出价
    sEnter = 2 * pivot - low  # 反转卖出价
    bEnter = 2 * pivot - high  # 反转买入价
    bSetup = pivot - (high - low)  # 观察买入价
    sBreak = low - 2 * (high - pivot)  # 突破卖出价

    print("已计算新标志线: ", "\n枢轴点", pivot, "\n突破买入价", bBreak, "\n观察卖出价", sSetup,
          "\n反转卖出价", sEnter, "\n反转买入价", bEnter, "\n观察买入价", bSetup, "\n突破卖出价", sBreak)
    return pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak


api = TqApi("SIM")
quote = api.get_quote(symbol)
klines = api.get_kline_serial(symbol, 24*60*60)  # 86400: 使用日线
position = api.get_position(symbol)
target_pos = TargetPosTask(api, symbol)
target_pos_value = position["volume_long"] - position["volume_short"]  # 净目标净持仓数
open_position_price = position["open_price_long"] if target_pos_value > 0 else position["open_price_short"]  # 开仓价
pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak = get_index_line(klines)  # 七条标准线

while True:
    target_pos.set_target_volume(target_pos_value)
    api.wait_update()
    if api.is_changing(klines[-1], "datetime"):  # 产生新k线,则重新计算7条指标线
        pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak = get_index_line(klines)

    nowTime = quote["datetime"].split()[1].split(":")  # 当前行情时间: [时,分,秒]
    if int(nowTime[0]) == close_hour and int(nowTime[1]) >= close_minute:  # 到达平仓时间: 平仓
        break

    '''交易规则'''
Example #8
0
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = 'chengzhi'

from tqsdk.api import TqApi
from tqsdk.lib import TargetPosTask
'''
价差回归
当近月-远月的价差大于200时做空近月,做多远月
当价差小于150时平仓
'''
api = TqApi("SIM")
quote_near = api.get_quote("SHFE.rb1810")
quote_deferred = api.get_quote("SHFE.rb1901")
# 创建 rb1810 的目标持仓 task,该 task 负责调整 rb1810 的仓位到指定的目标仓位
target_pos_near = TargetPosTask(api, "SHFE.rb1810")
# 创建 rb1901 的目标持仓 task,该 task 负责调整 rb1901 的仓位到指定的目标仓位
target_pos_deferred = TargetPosTask(api, "SHFE.rb1901")

while True:
    api.wait_update()
    if api.is_changing(quote_near) or api.is_changing(quote_deferred):
        spread = quote_near["last_price"] - quote_deferred["last_price"]
        print("当前价差:", spread)
        if spread > 200:
            print("目标持仓: 空近月,多远月")
            # 设置目标持仓为正数表示多头,负数表示空头,0表示空仓
            target_pos_near.set_target_volume(-1)
            target_pos_deferred.set_target_volume(1)
        elif spread < 150:
            print("目标持仓: 空仓")
· MA120 之下:
 - MA10 下穿 MA20 ,死叉,做空
 - MA10 上穿 MA20 ,金叉,平空
"""

# 实盘交易
# api =  TqApi(TqAccount("G光大期货","[账号]","[密码]"), web_gui=True)
# 回测模式
from datetime import date
api = TqApi(backtest=TqBacktest(date(2019, 7, 1), date(2019, 12, 1)),
            web_gui=True)
# 策略初始化
symbol = "CFFEX.IF1912"
klines = api.get_kline_serial(symbol, 60 * 15)  # 订阅15分钟K线序列
target_pos = TargetPosTask(api, symbol)
try:
    while True:
        api.wait_update()
        if api.is_changing(klines):
            # MA120的最新值
            ma120 = ma(klines.close, 120).iloc[-1]
            # MA10上穿MA20的bool序列的最新值
            up_cross = crossup(ma(klines.close, 10), ma(klines.close,
                                                        20)).iloc[-1]
            # MA10下穿MA20的bool序列的最新值
            down_cross = crossdown(ma(klines.close, 10), ma(klines.close,
                                                            20)).iloc[-1]
            # 如果最新K线收盘价在MA120上方
            if klines.close.iloc[-1] > ma120:
                # 如果MA10上穿MA20,开一手
Example #10
0
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = 'chengzhi'

from tqsdk.api import TqApi
from tqsdk.lib import TargetPosTask
'''
如果当前价格大于10秒K线的MA15则开多仓
如果小于则平仓
'''
api = TqApi("SIM")
# 获得 m1901 10秒K线的引用
klines = api.get_kline_serial("DCE.m1901", 10)
# 创建 m1901 的目标持仓 task,该 task 负责调整 m1901 的仓位到指定的目标仓位
target_pos = TargetPosTask(api, "DCE.m1901")

while True:
    api.wait_update()
    if api.is_changing(klines):
        ma = sum(klines.close[-15:]) / 15
        print("最新价", klines.close[-1], "MA", ma)
        if klines.close[-1] > ma:
            print("最新价大于MA: 目标多头5手")
            # 设置目标持仓为多头5手
            target_pos.set_target_volume(5)
        elif klines.close[-1] < ma:
            print("最新价小于MA: 目标空仓")
            # 设置目标持仓为空仓
            target_pos.set_target_volume(0)
Example #11
0
    HH = max(klines.high[-Nday - 1:-1])  # N日最高价的最高价
    HC = max(klines.close[-Nday - 1:-1])  # N日收盘价的最高价
    LC = min(klines.close[-Nday - 1:-1])  # N日收盘价的最低价
    LL = min(klines.low[-Nday - 1:-1])  # N日最低价的最低价
    range = max(HH - LC, HC - LL)
    buy_line = current_open + range * K1  # 上轨
    sell_line = current_open - range * K2  # 下轨

    print("当前开盘价:", current_open, "\n上轨:", buy_line, "\n下轨:", sell_line)
    return buy_line, sell_line


api = TqApi("SIM")
quote = api.get_quote(symbol)
klines = api.get_kline_serial(symbol, 24 * 60 * 60)  # 86400使用日线
target_pos = TargetPosTask(api, symbol)
buy_line, sell_line = dual_thrust(quote, klines)  # 获取上下轨

while True:
    api.wait_update()
    if api.is_changing(klines[-1], "datetime") or api.is_changing(
            quote, "open"):  # 新产生一根日线或开盘价发生变化: 重新计算上下轨
        buy_line, sell_line = dual_thrust(quote, klines)

    if api.is_changing(quote, "last_price"):
        print("最新价变化", quote["last_price"], end=':')
        if quote["last_price"] > buy_line:  # 高于上轨
            print("高于上轨,目标持仓 多头3手")
            target_pos.set_target_volume(3)  # 交易
        elif quote["last_price"] < sell_line:  # 低于下轨
            print("低于下轨,目标持仓 空头3手")