Exemple #1
0
class Single_bar:
    """
    用来生成单品种的K线
    
    """
    def __init__(self, strategy: StrategyTemplate, vt_symbol: str):
        """"""
        # 和portfolio的接口
        self.portfolio = strategy
        self.vt_symbol = vt_symbol

        # 需要合成的K线周期设置
        self.bar_interval = self.portfolio.bar_interval
        self.bar_frequency = self.portfolio.bar_frequency

        # K线合成工具和储存容器
        self.bg = BarGenerator(self.on_bar, self.bar_interval,
                               self.on_5min_bar, self.bar_frequency)
        self.am = ArrayManager()

        # K线合成计数
        self.bar_count = 0

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.bar_count += 1
        self.am.update_bar(bar)
Exemple #2
0
class MaSignal(CtaSignal):
    """"""
    def __init__(self, fast_window: int, slow_window: int):
        """"""
        super(MaSignal, self).__init__()

        self.fast_window = fast_window
        self.slow_window = slow_window

        self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)
        if not self.am.inited:
            self.set_signal_pos(0)

        fast_ma = self.am.sma("c", self.fast_window)
        slow_ma = self.am.sma("c", self.slow_window)

        if fast_ma > slow_ma:
            self.set_signal_pos(1)
        elif fast_ma < slow_ma:
            self.set_signal_pos(-1)
        else:
            self.set_signal_pos(0)
Exemple #3
0
class CorrelationMonitor(QWidget):
    signal_new_corr = QtCore.pyqtSignal((dt.datetime, float, float))
    signal_process = QtCore.pyqtSignal(int)

    class DataFetcher(QThread):
        def __init__(self, parent=None):
            super().__init__(parent)
            from KRData.HKData import HKFuture
            self.hf = HKFuture()
            self.finished.connect(self.parent().show_data_fetch_finished)

        def run(self) -> None:
            parent = self.parent()
            if parent:
                parent.raw_data['HSI'] = self.hf.get_main_contract_bars('HSI', start='20190101')

    def __init__(self):
        super().__init__()
        self.interval = 1
        self.raw_data = {}
        self.period = 0
        self._selected_row = 0
        self.data_fetcher = self.DataFetcher(self)
        self.hkm = HKMarket()
        self.data_fetcher.start()

        self.init_ui()

    def init_ui(self):
        self.setWindowTitle('相关性对比')
        self.setAcceptDrops(True)
        self.target_chart_widget = KLineWidget()
        # self.target_chart_widget.interval_combo.setEnabled(False)
        self.source_chart_widget = MarketDataChartWidget()
        self.compare_btn = QPushButton('历史数据对照')
        self.interval_combo = QComboBox()
        for i in [1, 5, 10, 15, 30, 60]:
            self.interval_combo.addItem(f'{i} min', i)

        self.save_btn = QPushButton('保存数据')

        # self.compare_btn.clicked.connect(self.calc_corr)
        # self.forward_num = QtWidgets.QLineEdit('30')
        # self.target_chart_widget.indicator_combo.currentTextChanged.connect(self.source_chart_widget.change_indicator)

        self.corr_table = QTableWidget()
        self.corr_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.corr_table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.corr_table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.corr_table.verticalHeader().setVisible(False)
        self.corr_table.setSortingEnabled(True)
        # self.corr_table.cellDoubleClicked.connect(self.show_corr_chart)

        self.process_bar = QtWidgets.QProgressBar()

        self.vb = QHBoxLayout()
        inner_vb = QVBoxLayout()

        inner_vb.addWidget(self.target_chart_widget)
        btn_hbox = QHBoxLayout()
        btn_hbox.addWidget(self.compare_btn, 3)
        btn_hbox.addWidget(self.interval_combo, 1)
        # btn_hbox.addWidget(self.forward_num, 2)
        btn_hbox.addWidget(self.process_bar, 5)
        btn_hbox.addWidget(self.save_btn, 1)
        inner_vb.addLayout(btn_hbox)
        inner_vb.addWidget(self.source_chart_widget)

        self.vb.addLayout(inner_vb, 8)
        self.vb.addWidget(self.corr_table, 2)

        self.setLayout(self.vb)
        self.resize(1500, 1000)

        self.init_signal()

    def init_signal(self):
        def change_interval(index):
            val = self.interval_combo.itemData(index)
            self.interval = val
            self.show_corr_chart(self._selected_row, 0)

        self.interval_combo.currentIndexChanged.connect(change_interval)
        self.compare_btn.clicked.connect(self.calc_corr)
        self.target_chart_widget.indicator_combo.currentTextChanged.connect(self.source_chart_widget.change_indicator)
        self.corr_table.cellDoubleClicked.connect(self.show_corr_chart)
        self.source_chart_widget.signal_new_bar_request.connect(self.update_bars_backward)
        self.signal_process.connect(self.process_bar.setValue)
        self.signal_new_corr.connect(self.insert_corr)
        self.save_btn.clicked.connect(self.save_corr_data)

    def update_bars_backward(self, n):
        source_data = self.raw_data['HSI']
        last_bar = self.bar_generator.last_bar
        if last_bar is None:
            return
        start = last_bar.datetime
        end = source_data.datetime.shift(-n)[start]
        data = source_data[start:end]

        for _, d in data.iterrows():
            b = BarData('KRData', d.code, Exchange.HKFE, d.datetime, None,
                        d.volume, 0, d.open, d.high, d.low, d.close)
            self.bar_generator.update_bar(b)


    def calc_corr(self):
        if not self.data_fetcher.isFinished():
            QMessageBox.critical(self, 'DataFetcher', '数据未加载完毕!', QMessageBox.Ok)
            return
        import scipy.stats as st
        target_data = self.target_chart_widget.datas
        source_data = self.raw_data['HSI']

        apply_func_dict = {'datetime': 'last',
                           'code': 'first',
                           'open': 'first',
                           'high': 'max',
                           'low': 'min',
                           'close': 'last',
                           'volume': 'sum',
                           'trade_date': 'first'
                           }

        ktype = {'1min': '1T', '5min': '5T', '15min': '15T',
                 '30min': '30T', '60min': '60T', '1day': '1D'}.get(self.target_chart_widget.period)
        if ktype:
            self.data = source_data.resample(ktype).apply(apply_func_dict)
            self.data.dropna(thresh=2, inplace=True)
            self.data.datetime = self.data.index
        else:
            self.data = source_data

        target_values = target_data.close.values
        self.process_bar.setValue(0)
        @numba.jit
        def corr(nd):
            return st.pearsonr(nd, target_values)

        self.period = len(target_data)
        # ret = source_data.close.rolling(self.period).apply(corr)

        table = self.corr_table
        table.clearContents()
        table.setColumnCount(3)
        # table.setRowCount(len(ret))
        table.setHorizontalHeaderLabels(['datetime', 'corr', 'p'])
        count = len(self.data)

        corr_data = []
        for i in range(self.period, count, 10):
            data = (self.data.datetime[i], *corr(self.data.close.values[i - self.period:i]))
            process_value = (i + 10) * 100 // count
            self.signal_process.emit(process_value)
            self.signal_new_corr.emit(*data)
            corr_data.append(data)
        else:
            self.corr_data = pd.DataFrame(corr_data, columns=['datetime', 'corr', 'p'])

    def insert_corr(self, d, corr, p):
        table = self.corr_table
        r = table.rowCount()
        table.insertRow(r)
        dt_cell = QTableWidgetItem()
        dt_cell.setFlags(QtCore.Qt.ItemIsEnabled)
        dt_cell.setData(Qt.DisplayRole, str(d))
        dt_cell.setTextAlignment(QtCore.Qt.AlignCenter)

        corr_cell = QTableWidgetItem()
        corr_cell.setFlags(QtCore.Qt.ItemIsEnabled)
        corr_cell.setData(Qt.DisplayRole, 0 if np.isnan(corr) else corr)
        corr_cell.setTextAlignment(QtCore.Qt.AlignCenter)

        p_cell = QTableWidgetItem()
        p_cell.setFlags(QtCore.Qt.ItemIsEnabled)
        p_cell.setData(Qt.DisplayRole, p)
        p_cell.setTextAlignment(QtCore.Qt.AlignCenter)


        table.setItem(r, 0, dt_cell)
        table.setItem(r, 1, corr_cell)
        table.setItem(r, 2, p_cell)

    def show_corr_chart(self, r, c):
        self._selected_row = r
        _end = self.corr_table.item(r, 0).text()

        source_data = self.raw_data['HSI']
        forward = 1
        start = self.data.shift(self.period).asof(_end).datetime
        end = self.data.shift(-forward).asof(_end).datetime
        data = source_data.loc[start:end]
        self.source_chart_widget.clear_all()
        # barList = []
        if self.interval >= 60:
            self.bar_generator = BarGenerator(None, 1, self.source_chart_widget.update_bar, Interval.HOUR)
        else:
            self.bar_generator = BarGenerator(None, self.interval, self.source_chart_widget.update_bar, Interval.MINUTE)

        for _, d in data.iterrows():
            b = BarData('KRData', d.code, Exchange.HKFE, d.datetime, None,
                        d.volume, 0, d.open, d.high, d.low, d.close)
            self.bar_generator.update_bar(b)
            if d.datetime == parser.parse(_end):
                last_bar = self.source_chart_widget._manager.get_bar(self.source_chart_widget.last_ix)
                self.source_chart_widget.add_splitLine(last_bar.datetime)
            # barList.append(b)
        # self.source_chart_widget.update_all(barList, [], [])
        # self.source_chart_widget.add_splitLine(barList[-forward].datetime, offset=0.5)

    def save_corr_data(self):
        if not hasattr(self, 'self.corr_data'):
            return

        target_data = self.target_chart_widget.datas
        target_start = target_data.iloc[0].datetime
        target_end = target_data.iloc[-1].datetime

        s = {}
        s['start'] = target_start
        s['end'] = target_end
        s['symbol'] = self.target_chart_widget.symbol_line.text()
        s['period'] = self.target_chart_widget.period
        s['source'] = self.target_chart_widget.data_source
        s['data'] = self.corr_data

        # data.to_excel(f'{target_start}-{target_end}.xls', sheet_name=self.target_chart_widget.period)
        import pickle
        with open(f'{target_start.strftime("%Y%m%dT%H%M%S")}_{target_end.strftime("%Y%m%dT%H%M%S")}.pkl', 'wb') as f:
            pickle.dump(s, f)

    def load_corr_data(self, file_name):
        if not self.data_fetcher.isFinished():
            QMessageBox.critical(self, 'DataFetcher', '数据未加载完毕!', QMessageBox.Ok)
            return

        import pickle
        with open(file_name, 'rb') as f:
            s = pickle.load(f)

        self.target_chart_widget.symbol_line.setText(s['symbol'])
        self.target_chart_widget.datetime_from.setDateTime(s['start'])
        self.target_chart_widget.datetime_to.setDateTime(s['end'])
        self.target_chart_widget.interval_combo.setCurrentText(s['period'])
        if s['source'] == 'HK':
            self.target_chart_widget.source_HK_btn.setChecked(True)
        elif s['source'] == 'IB':
            self.target_chart_widget.source_IB_btn.setChecked(True)

        self.corr_table.clearContents()
        self.corr_table.setColumnCount(3)
        # table.setRowCount(len(ret))
        self.corr_table.setHorizontalHeaderLabels(['datetime', 'corr', 'p'])

        for _, d in s['data'].iterrows():
            self.insert_corr(d['datetime'], d['corr'], d['p'])

        source_data = self.raw_data['HSI']

        apply_func_dict = {'datetime': 'last',
                           'code': 'first',
                           'open': 'first',
                           'high': 'max',
                           'low': 'min',
                           'close': 'last',
                           'volume': 'sum',
                           'trade_date': 'first'
                           }

        ktype = {'1min': '1T', '5min': '5T', '15min': '15T',
                 '30min': '30T', '60min': '60T', '1day': '1D'}.get(self.target_chart_widget.period)
        if ktype:
            self.data = source_data.resample(ktype).apply(apply_func_dict)
            self.data.dropna(thresh=2, inplace=True)
            self.data.datetime = self.data.index
        else:
            self.data = source_data

        self.target_chart_widget.query_btn.click()
        self.period = len(self.target_chart_widget.datas)

    def show_data_fetch_finished(self):
        QMessageBox.information(self, 'DataFetcher', '数据加载完毕!', QMessageBox.Ok)

    def closeEvent(self, a0: QCloseEvent) -> None:
        self.target_chart_widget.closeEvent(a0)
        self.source_chart_widget.closeEvent(a0)
        super().closeEvent(a0)

    def dragEnterEvent(self, a0: QDragEnterEvent) -> None:
        super().dragEnterEvent(a0)
        if a0.mimeData().hasFormat('text/plain'):
            a0.accept()
        else:
            a0.ignore()

    def dropEvent(self, a0: QDropEvent) -> None:
        super().dropEvent(a0)

        file_name = a0.mimeData().text().lstrip('file:/')
        self.load_corr_data(file_name)
class MACDSignal:
    """"""
    def __init__(self, strategy: StrategyTemplate, vt_symbol: str):
        """"""

        self.portfolio = strategy
        self.vt_symbol = vt_symbol

        self.fast_period = self.portfolio.fast_period
        self.slow_period = self.portfolio.slow_period
        self.signal_period = self.portfolio.signal_period
        self.trailing_percent = self.portfolio.trailing_percent
        self.fixed_size = self.portfolio.fixed_size
        self.bar_interval = self.portfolio.bar_interval
        self.bar_frequency = self.portfolio.bar_frequency

        self.macd_value = 0
        self.intra_trade_high = 0
        self.intra_trade_low = 0

        self.bg = BarGenerator(self.on_bar, self.bar_interval,
                               self.on_5min_bar, self.bar_frequency)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)

        if not self.am.inited:
            return

        self.portfolio.cancel_all()
        am = self.am
        macd, macd_signal, _ = am.macd(self.fast_period,
                                       self.slow_period,
                                       self.signal_period,
                                       array=True)

        long_trend = (macd[-2] < macd_signal[-2]) and (macd[-1] >
                                                       macd_signal[-1])
        short_trend = (macd[-2] > macd_signal[-2]) and (macd[-1] <
                                                        macd_signal[-1])

        symbol_pos = self.portfolio.get_pos(self.vt_symbol)
        if symbol_pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            if long_trend:

                open_order = self.portfolio.buy(self.vt_symbol,
                                                bar.close_price + 5,
                                                self.fixed_size)

            elif short_trend:

                open_order = self.portfolio.short(self.vt_symbol,
                                                  bar.close_price - 5,
                                                  self.fixed_size)

        elif symbol_pos > 0:

            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            long_stop = self.intra_trade_high * (1 -
                                                 self.trailing_percent / 100)
            # if bar.close_price <= long_stop:
            #     close_order = self.portfolio.sell(self.vt_symbol, bar.close_price - 5, abs(symbol_pos))
            #     self.limit_orders.append(close_order)
            if short_trend:

                close_order = self.portfolio.sell(self.vt_symbol,
                                                  bar.close_price - 5,
                                                  abs(symbol_pos))

        elif symbol_pos < 0:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.intra_trade_high = bar.high_price

            short_stop = self.intra_trade_low * (1 +
                                                 self.trailing_percent / 100)
            # if bar.close_price >= short_stop:
            #     close_order = self.portfolio.cover(self.vt_symbol, bar.high_price + 5, abs(symbol_pos))
            #     self.limit_orders.append(close_order)
            if long_trend:
                close_order = self.portfolio.cover(self.vt_symbol,
                                                   bar.high_price + 5,
                                                   abs(symbol_pos))
class KingKeltnerStrategy(CtaTemplate):
    """"""

    author = '中科云集'

    kk_length = 11
    kk_dev = 1.6
    trailing_percent = 0.8
    fixed_size = 1

    kk_up = 0
    kk_down = 0
    intra_trade_high = 0
    intra_trade_low = 0

    long_vt_orderids = []
    short_vt_orderids = []
    vt_orderids = []

    parameters = ['kk_length', 'kk_dev', 'fixed_size']
    variables = ['kk_up', 'kk_down']

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(KingKeltnerStrategy, self).__init__(
            cta_engine, strategy_name, vt_symbol, setting
        )

        self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        for orderid in self.vt_orderids:
            self.cancel_order(orderid)
        self.vt_orderids.clear()

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        self.kk_up, self.kk_down = am.keltner(self.kk_length, self.kk_dev)

        if self.pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price
            self.send_oco_order(self.kk_up, self.kk_down, self.fixed_size)

        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            vt_orderids = self.sell(self.intra_trade_high * (1 - self.trailing_percent / 100),
                                    abs(self.pos), True)
            self.vt_orderids.extend(vt_orderids)

        elif self.pos < 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)

            vt_orderids = self.cover(self.intra_trade_low * (1 + self.trailing_percent / 100),
                                     abs(self.pos), True)
            self.vt_orderids.extend(vt_orderids)

        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if self.pos != 0:
            if self.pos > 0:
                for short_orderid in self.short_vt_orderids:
                    self.cancel_order(short_orderid)

            elif self.pos < 0:
                for buy_orderid in self.long_vt_orderids:
                    self.cancel_order(buy_orderid)

            for orderid in (self.long_vt_orderids + self.short_vt_orderids):
                if orderid in self.vt_orderids:
                    self.vt_orderids.remove(orderid)

        self.put_event()

    def send_oco_order(self, buy_price, short_price, volume):
        """"""
        self.long_vt_orderids = self.buy(buy_price, volume, True)
        self.short_vt_orderids = self.short(short_price, volume, True)

        self.vt_orderids.extend(self.long_vt_orderids)
        self.vt_orderids.extend(self.short_vt_orderids)

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Exemple #6
0
class DemoStrategy(CtaTemplate):
    """
    策略学习
    """
    author = "蒋越希"

    # 定义界面可以配置的参数
    fast_window = 10
    slow_window = 20
    parameters = [
        # 快速窗口
        "fast_window",
        # 慢速窗口
        "slow_window"
    ]

    # 定义变量
    fast_ma0 = 0.0
    fast_ma1 = 0.0
    slow_ma0 = 0.0
    slow_ma1 = 0.0
    variables = [
        "fast_ma0",
        "fast_ma1",
        "slow_ma0",
        "slow_ma1",
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        super(DemoStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting)
        # 在on_window_bar参数里合成K线
        self.bg = BarGenerator(self.on_bar, window=5, on_window_bar=self.on_5min_bar, interval=Interval.MINUTE)
        self.am = ArrayManager()

    def on_init(self):
        """
        策略初始化
        :return: 
        """
        self.write_log("策略初始化")
        # 10 天
        self.load_bar(10)

    def on_start(self):
        """
        启动
        :return: 
        """
        self.write_log("启动")

    def on_stop(self):
        """
        策略停止
        :return: 
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """TICK"""
        self.bg.update_tick(tick)

    def on_5min_bar(self, bar: BarData):
        """
        5分钟K线
        :param bar: 
        :return: 
        """
        am = self.am

        am.update_bar(bar)
        if not am.inited:
            return
        # 快移动均线
        fast_ma = am.sma(self.fast_window, array=True)
        self.fast_ma0 = fast_ma[-1]
        self.fast_ma1 = fast_ma[-2]
        # 慢速移动均线
        slow_ma = am.sma(self.slow_window, array=True)
        self.slow_ma0 = slow_ma[-1]
        self.slow_ma1 = slow_ma[-2]

        # 判断均线交叉
        # 金叉
        cross_over = (self.fast_ma0 >= self.slow_ma0) and (self.fast_ma1 < self.slow_ma1)
        # 死叉
        cross_below = (self.fast_ma0 <= self.slow_ma0) and (self.fast_ma1 > self.slow_ma1)

        if cross_over:
            price = bar.close_price + 5
            if not self.pos:
                # 如果没有仓位

                # 买入开仓(看涨)
                self.buy(price, 1)
            elif self.pos < 0:
                # 买入平仓
                self.cover(price, 1)
                self.buy(price, 1)
            elif self.pos > 0:
                # 如果是 多, 不操作
                pass
        elif cross_below:
            price = bar.close_price - 5
            if not self.pos:
                # 做空 卖出开仓(看跌)
                self.short(price, 1)
            elif self.pos > 0:
                self.sell(price, 1)
                self.short(price, 1)

        self.put_event()

    def on_bar(self, bar: BarData):
        """
        K 线更新
        :param bar: 
        :return: 
        """
        self.bg.update_bar(bar)
Exemple #7
0
class StatisticalArbitrageStrategy(SpreadStrategyTemplate):
    """"""

    author = "用Python的交易员"

    open_window = 1
    boll_window = 40
    boll_dev = 4.9
    fixed_pos = 10
    payup = 10.0
    increase_price = 0.0  # 超价
    interval = 5

    spread_pos = 0.0
    boll_up = 0.0
    boll_down = 0.0
    boll_mid = 0.0

    parameters = [
        "boll_window", "boll_dev", "fixed_pos", "payup", "interval",
        "increase_price"
    ]
    variables = ["spread_pos", "boll_up", "boll_down", "boll_mid"]

    def __init__(self, strategy_engine, strategy_name: str, spread: SpreadData,
                 setting: dict):
        """"""
        super().__init__(strategy_engine, strategy_name, spread, setting)

        self.bg = BarGenerator(self.on_open_spread_bar, self.open_window,
                               self.on_open_spread_bar)
        self.am = ArrayManager()

        self.spread_pos = 0.0
        self.boll_up = 0.0
        self.boll_down = 0.0
        self.boll_mid = 0.0

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

        self.put_event()

    def on_spread_data(self):
        """
        Callback when spread price is updated.
        收到差价推送后,合成价差TICK数据
        """
        #这里的价差tick
        tick = self.get_spread_tick()
        self.on_spread_tick(tick)

    def on_spread_tick(self, tick: TickData):
        """
        Callback when new spread tick data is generated.
        """
        self.bg.update_tick(tick)

    def on_spread_bar(self, bar: BarData):
        """
        Callback when new spread bar data is generated.
        """
        self.bg.update_bar(bar)

    def on_open_spread_bar(self, bar: BarData):
        """
        Callback when spread bar data is generated.

        目前的策略逻辑:
        1、当价差价格大于布林上轨,以当前收盘加低10的价格下单(以市价下单保证成交),当价格跌破中轨时平仓 (做空)
        2、当价差价格小于布林下轨,以当前收盘价加10的价格下单,当价格高于中轨时平仓 (做多)

        策略优化方向:
        1、把目前在分钟价差K线逻辑移到 tick逻辑中实盘,增加细腻度
        2、仓位分为四次加减仓,第一次上穿时,开一份,第二次上穿的价格要高于第一次一定比较时,开第二份,一直到满四份。
        (这两个参数,一个是份数,一个是跨度(格距)),目的解决如果出现单边短时趋势抗单时爆仓(最后都会回归中轨)
        3、回到中轨全部平仓位

        """
        # 把老算法先停止,
        self.stop_all_algos()

        self.am.update_bar(bar)

        if not self.am.inited:
            return

        self.boll_mid = self.am.sma(self.boll_window)
        self.boll_up, self.boll_down = self.am.boll(self.boll_window,
                                                    self.boll_dev)

        if not self.spread_pos:
            if bar.close_price >= self.boll_up:
                self.start_short_algo(bar.close_price - self.increase_price,
                                      self.fixed_pos,
                                      payup=self.payup,
                                      interval=self.interval)
            elif bar.close_price <= self.boll_down:
                self.start_long_algo(bar.close_price + self.increase_price,
                                     self.fixed_pos,
                                     payup=self.payup,
                                     interval=self.interval)
        elif self.spread_pos < 0:
            if bar.close_price <= self.boll_mid:
                self.start_long_algo(bar.close_price + self.increase_price,
                                     abs(self.spread_pos),
                                     payup=self.payup,
                                     interval=self.interval)
        else:
            if bar.close_price >= self.boll_mid:
                self.start_short_algo(bar.close_price - self.increase_price,
                                      abs(self.spread_pos),
                                      payup=self.payup,
                                      interval=self.interval)
        self.put_event()

    def on_spread_pos(self):
        """
        Callback when spread position is updated.
        """
        self.spread_pos = self.get_spread_pos()
        self.put_event()

    def on_spread_algo(self, algo: SpreadAlgoTemplate):
        """
        Callback when algo status is updated.
        """
        pass

    def on_order(self, order: OrderData):
        """
        Callback when order status is updated.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback when new trade data is received.
        """
        pass
class BollChannelStrategy(CtaTemplate):
    """"""

    author = "中科云集"

    boll_window = 18
    boll_dev = 3.4
    cci_window = 10
    atr_window = 30
    sl_multiplier = 5.2
    fixed_size = 1

    boll_up = 0
    boll_down = 0
    cci_value = 0
    atr_value = 0

    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0

    parameters = [
        "boll_window", "boll_dev", "cci_window", "atr_window", "sl_multiplier",
        "fixed_size"
    ]
    variables = [
        "boll_up", "boll_down", "cci_value", "atr_value", "intra_trade_high",
        "intra_trade_low", "long_stop", "short_stop"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(BollChannelStrategy, self).__init__(cta_engine, strategy_name,
                                                  vt_symbol, setting)

        self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        self.am = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_15min_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev)
        self.cci_value = am.cci(self.cci_window)
        self.atr_value = am.atr(self.atr_window)

        if self.pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            if self.cci_value > 0:
                self.buy(self.boll_up, self.fixed_size, True)
            elif self.cci_value < 0:
                self.short(self.boll_down, self.fixed_size, True)

        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier
            self.sell(self.long_stop, abs(self.pos), True)

        elif self.pos < 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)

            self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier
            self.cover(self.short_stop, abs(self.pos), True)

        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Exemple #9
0
class MultiTimeframeStrategy(CtaTemplate):
    """"""
    author = "中科云集"

    rsi_signal = 20
    rsi_window = 14
    fast_window = 5
    slow_window = 20
    fixed_size = 1

    rsi_value = 0
    rsi_long = 0
    rsi_short = 0
    fast_ma = 0
    slow_ma = 0
    ma_trend = 0

    parameters = [
        "rsi_signal", "rsi_window", "fast_window", "slow_window", "fixed_size"
    ]

    variables = [
        "rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(MultiTimeframeStrategy, self).__init__(cta_engine, strategy_name,
                                                     vt_symbol, setting)

        self.rsi_long = 50 + self.rsi_signal
        self.rsi_short = 50 - self.rsi_signal

        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am5 = ArrayManager()

        self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        self.am15 = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg5.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg5.update_bar(bar)
        self.bg15.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        self.am5.update_bar(bar)
        if not self.am5.inited:
            return

        if not self.ma_trend:
            return

        self.rsi_value = self.am5.rsi(self.rsi_window)

        if self.pos == 0:
            if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                self.buy(bar.close_price + 5, self.fixed_size)
            elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                self.short(bar.close_price - 5, self.fixed_size)

        elif self.pos > 0:
            if self.ma_trend < 0 or self.rsi_value < 50:
                self.sell(bar.close_price - 5, abs(self.pos))

        elif self.pos < 0:
            if self.ma_trend > 0 or self.rsi_value > 50:
                self.cover(bar.close_price + 5, abs(self.pos))

        self.put_event()

    def on_15min_bar(self, bar: BarData):
        """"""
        self.am15.update_bar(bar)
        if not self.am15.inited:
            return

        self.fast_ma = self.am15.sma("c", self.fast_window)
        self.slow_ma = self.am15.sma("c", self.slow_window)

        if self.fast_ma > self.slow_ma:
            self.ma_trend = 1
        else:
            self.ma_trend = -1

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
class TredningFollowingSignal:
    """"""
    def __init__(self, strategy: StrategyTemplate, vt_symbol: str):
        """"""

        self.portfolio = strategy
        self.vt_symbol = vt_symbol

        self.atr_window = self.portfolio.atr_window
        self.atr_ma_window = self.portfolio.atr_ma_window
        self.rsi_window = self.portfolio.rsi_window
        self.rsi_entry = self.portfolio.rsi_entry
        self.trailing_percent = self.portfolio.trailing_percent
        self.fixed_size = self.portfolio.fixed_size

        self.atr_value = 0
        self.atr_ma = 0
        self.rsi_value = 0
        self.rsi_buy = 50 + self.rsi_entry
        self.rsi_sell = 50 - self.rsi_entry
        self.intra_trade_high = 0
        self.intra_trade_low = 0

        self.limit_orders = []
        self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)

        if not self.am.inited:
            return

        self.portfolio.cancel_all()
        am = self.am
        atr_array = am.atr(self.atr_window, array=True)
        self.atr_value = atr_array[-1]
        self.atr_ma = atr_array[-self.atr_ma_window:].mean()
        self.rsi_value = am.rsi(self.rsi_window)

        symbol_pos = self.portfolio.get_pos(self.vt_symbol)
        if symbol_pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            if self.atr_value > self.atr_ma:
                if self.rsi_value > self.rsi_buy:
                    open_order = self.portfolio.buy(self.vt_symbol,
                                                    bar.close_price + 5,
                                                    self.fixed_size)
                    self.limit_orders.append(open_order)
                elif self.rsi_value < self.rsi_sell:
                    open_order = self.portfolio.short(self.vt_symbol,
                                                      bar.close_price - 5,
                                                      self.fixed_size)
        elif symbol_pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            long_stop = self.intra_trade_high * (1 -
                                                 self.trailing_percent / 100)
            if bar.close_price <= long_stop:
                close_order = self.portfolio.sell(self.vt_symbol,
                                                  bar.close_price - 5,
                                                  abs(symbol_pos))
                self.limit_orders.append(close_order)
        elif symbol_pos < 0:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.intra_trade_high = bar.high_price

            short_stop = self.intra_trade_low * (1 +
                                                 self.trailing_percent / 100)
            if bar.close_price >= short_stop:
                close_order = self.portfolio.cover(self.vt_symbol,
                                                   bar.high_price + 5,
                                                   abs(symbol_pos))
                self.limit_orders.append(close_order)