예제 #1
0
 def __init__(self, name, settings={}):
     self.events_pool = EventsPool()
     # @TODO merge blotter and exchange
     self.blotter = SimpleBlotter(name, self.events_pool, settings)
     self.exchange = Exchange(name, self.events_pool, strict=True)
     self._orders = []
     self._datetime = None
     self._cancel_now = False  # 是当根bar还是下一根bar撤单成功。
예제 #2
0
 def __init__(self, name, settings={}):
     self.events_pool = EventsPool()
     # @TODO merge blotter and exchange
     self.blotter = SimpleBlotter(name, self.events_pool, settings)
     self.exchange = Exchange(name, self.events_pool, strict=True)
     self.name = name
     # 0: line_marks, 1: text_marks
     self.marks = [{}, {}]
     self._entry_orders = []
     self._exit_orders = []
     self._datetime = None
     self._cancel_now = False  # 是当根bar还是下一根bar撤单成功。
예제 #3
0
 def __init__(self, name, settings={}):
     self.events_pool = EventsPool()
     # @TODO merge blotter and exchange
     self.blotter = SimpleBlotter(name, self.events_pool, settings)
     self.exchange = Exchange(name, self.events_pool, strict=True)
     self.name = name
     # 0: line_marks, 1: text_marks
     self.marks = [{}, {}]
     self._orders = []
     self._datetime = None
     self._cancel_now = False  # 是当根bar还是下一根bar撤单成功。
예제 #4
0
class StrategyContext(object):
    """ 策略组合

    :ivar name: 策略名
    :ivar blotter: 订单管理
    :ivar exchange: 价格撮合器
    :ivar marks: 绘图标志集合
    """

    def __init__(self, name, settings={}):
        self.events_pool = EventsPool()
        # @TODO merge blotter and exchange
        self.blotter = SimpleBlotter(name, self.events_pool, settings)
        self.exchange = Exchange(name, self.events_pool, strict=True)
        self.name = name
        # 0: line_marks, 1: text_marks
        self.marks = [{}, {}]
        self._orders = []
        self._datetime = None
        self._cancel_now = False  # 是当根bar还是下一根bar撤单成功。

    def update_environment(self, dt, ticks, bars):
        """ 更新模拟交易所和订单管理器的数据,时间,持仓 """
        self.blotter.update_datetime(dt)
        self.exchange.update_datetime(dt)
        self.blotter.update_data(ticks, bars)
        self._datetime = dt
        return

    def process_trading_events(self, at_baropen):
        """ 提交订单,撮合,更新持仓 """
        if self._orders:
            self.events_pool.put(SignalEvent(self._orders))
        if not self._orders:
            # 没有交易信号,确保至少运行一次
            self.events_pool.put(OnceEvent())
        self._process_trading_events(at_baropen)
        self._orders = []

    def _process_trading_events(self, at_baropen):
        """"""
        while True:
            # 事件处理。
            try:
                event = self.events_pool.get()
            except Queue.Empty:
                assert False
            except IndexError:
                break
            else:
                # if event.type == 'MARKET':
                # strategy.calculate_signals(event)
                # port.update_timeindex(event)
                if event.route == Event.SIGNAL:
                    assert not at_baropen
                    self.blotter.update_signal(event)
                elif event.route == Event.ORDER:
                    assert not at_baropen
                    self.exchange.insert_order(event)
                elif event.route == Event.FILL:
                    # 模拟交易接口收到报单成交
                    self.blotter.api.on_transaction(event)
            # 价格撮合。note: bar价格撮合要求撮合置于运算后面。
            # @TODO tick 回测不一样
            if event.route == Event.ONCE or event.route == Event.ORDER:
                self.exchange.make_market(self.blotter._bars, at_baropen)
        self.blotter.update_status(self._datetime, at_baropen)

    def plot_line(self, name, ith_window, x, y, styles, lw=1, ms=10, twinx=False):
        """ 绘制曲线

        Args:
            name (str): 标志名称
            ith_window (int): 在第几个窗口显示,从1开始。
            x (datetime): 时间坐标
            y (float): y坐标
            styles (str): 控制颜色,线的风格,点的风格
            lw (int): 线宽
            ms (int): 点的大小
        """
        mark = self.marks[0].setdefault(name, [])
        mark.append((ith_window, twinx, x, y, styles, lw, ms))

    def plot_text(self, name, ith_window, x, y, text, color="black", size=15, rotation=0):
        """ 绘制文本

        Args:
            name (str): 标志名称
            ith_window (int): 在第几个窗口显示,从1开始。
            x (float): x坐标
            y (float): y坐标
            text (str): 文本内容
            color (str): 颜色
            size (int): 字体大小
            rotation (float): 旋转角度
        """
        mark = self.marks[1].setdefault(name, [])
        mark.append((ith_window, x, y, text, color, size, rotation))

    def buy(self, price, quantity, price_type, contract):
        self._orders.append(Order(None, contract, price_type, TradeSide.KAI, Direction.LONG, float(price), quantity))

    def sell(self, price, quantity, price_type, contract):
        self._orders.append(Order(None, contract, price_type, TradeSide.PING, Direction.LONG, float(price), quantity))

    def short(self, price, quantity, price_type, contract):
        self._orders.append(Order(None, contract, price_type, TradeSide.KAI, Direction.SHORT, float(price), quantity))

    def cover(self, price, quantity, price_type, contract):
        self._orders.append(Order(None, contract, price_type, TradeSide.PING, Direction.SHORT, float(price), quantity))

    def cancel(self, orders):
        """ 撤单

        Args:
            orders (list/Order): 撤单,参数为list表示撤多个单。
        """
        orders = orders if isinstance(orders, list) else [orders]
        if not self._cancel_now:
            # 当前bar收盘处处理撤单
            for order in orders:
                norder = copy.deepcopy(order)
                norder.side = TradeSide.CANCEL
                # @TODO or self._orders ?
                # 结合实盘考虑, 实盘可能自动撤单。
                self._orders.append(norder)
            return
        ## 立即处理撤单
        # temp = copy.deepcopy(self._orders)
        # self._orders = []
        # for order in orders:
        # order.side = TradeSide.CANCEL
        # self._orders.append(order)
        # self.process_trading_events(False)
        # self._orders = temp

    @property
    def open_orders(self):
        """ 未成交的订单 """
        return self.blotter.open_orders

    def all_positions(self):
        return self.blotter.positions.values()

    def position(self, contract, direction):
        try:
            poskey = PositionKey(contract, direction)
            return self.blotter.positions[poskey]
        except KeyError:
            return None

    def pos(self, contract, direction):
        try:
            poskey = PositionKey(contract, direction)
            return self.blotter.positions[poskey].closable
        except KeyError:
            return 0

    def cash(self):
        return self.blotter.holding["cash"]

    def equity(self):
        return self.blotter.holding["equity"]

    def profit(self, contract):
        pass

    def day_profit(self, contract):
        """ 当前持仓的浮动盈亏 """
        pass
예제 #5
0
class StrategyContext(object):
    """ 策略组合

    :ivar name: 策略名
    :ivar blotter: 订单管理
    :ivar exchange: 价格撮合器
    :ivar marks: 绘图标志集合
    """
    def __init__(self, name, settings={}):
        self.events_pool = EventsPool()
        # @TODO merge blotter and exchange
        self.blotter = SimpleBlotter(name, self.events_pool, settings)
        self.exchange = Exchange(name, self.events_pool, strict=True)
        self.name = name
        # 0: line_marks, 1: text_marks
        self.marks = [{}, {}]
        self._orders = []
        self._datetime = None
        self._cancel_now = False  # 是当根bar还是下一根bar撤单成功。

    def update_environment(self, dt, ticks, bars):
        """ 更新模拟交易所和订单管理器的数据,时间,持仓 """
        self.blotter.update_datetime(dt)
        self.exchange.update_datetime(dt)
        self.blotter.update_data(ticks, bars)
        self._datetime = dt
        return

    def process_trading_events(self, at_baropen):
        """ 提交订单,撮合,更新持仓 """
        if self._orders:
            self.events_pool.put(SignalEvent(self._orders))
        if not self._orders:
            # 没有交易信号,确保至少运行一次
            self.events_pool.put(OnceEvent())
        self._process_trading_events(at_baropen)
        self._orders = []

    def _process_trading_events(self, at_baropen):
        """"""
        while True:
            # 事件处理。
            try:
                event = self.events_pool.get()
            except Queue.Empty:
                assert (False)
            except IndexError:
                break
            else:
                # if event.type == 'MARKET':
                # strategy.calculate_signals(event)
                # port.update_timeindex(event)
                if event.route == Event.SIGNAL:
                    assert (not at_baropen)
                    self.blotter.update_signal(event)
                elif event.route == Event.ORDER:
                    assert (not at_baropen)
                    self.exchange.insert_order(event)
                elif event.route == Event.FILL:
                    # 模拟交易接口收到报单成交
                    self.blotter.api.on_transaction(event)
            # 价格撮合。note: bar价格撮合要求撮合置于运算后面。
            # @TODO tick 回测不一样
            if event.route == Event.ONCE or event.route == Event.ORDER:
                self.exchange.make_market(self.blotter._bars, at_baropen)
        self.blotter.update_status(self._datetime, at_baropen)

    def plot_line(self,
                  name,
                  ith_window,
                  x,
                  y,
                  styles,
                  lw=1,
                  ms=10,
                  twinx=False):
        """ 绘制曲线

        Args:
            name (str): 标志名称
            ith_window (int): 在第几个窗口显示,从1开始。
            x (datetime): 时间坐标
            y (float): y坐标
            styles (str): 控制颜色,线的风格,点的风格
            lw (int): 线宽
            ms (int): 点的大小
        """
        mark = self.marks[0].setdefault(name, [])
        mark.append((ith_window, twinx, x, y, styles, lw, ms))

    def plot_text(self,
                  name,
                  ith_window,
                  x,
                  y,
                  text,
                  color='black',
                  size=15,
                  rotation=0):
        """ 绘制文本

        Args:
            name (str): 标志名称
            ith_window (int): 在第几个窗口显示,从1开始。
            x (float): x坐标
            y (float): y坐标
            text (str): 文本内容
            color (str): 颜色
            size (int): 字体大小
            rotation (float): 旋转角度
        """
        mark = self.marks[1].setdefault(name, [])
        mark.append((ith_window, x, y, text, color, size, rotation))

    def buy(self, price, quantity, price_type, contract):
        self._orders.append(
            Order(None, contract, price_type, TradeSide.KAI, Direction.LONG,
                  float(price), quantity))

    def sell(self, price, quantity, price_type, contract):
        self._orders.append(
            Order(None, contract, price_type, TradeSide.PING, Direction.LONG,
                  float(price), quantity))

    def short(self, price, quantity, price_type, contract):
        self._orders.append(
            Order(None, contract, price_type, TradeSide.KAI, Direction.SHORT,
                  float(price), quantity))

    def cover(self, price, quantity, price_type, contract):
        self._orders.append(
            Order(None, contract, price_type, TradeSide.PING, Direction.SHORT,
                  float(price), quantity))

    def cancel(self, orders):
        """ 撤单

        Args:
            orders (list/Order): 撤单,参数为list表示撤多个单。
        """
        orders = orders if isinstance(orders, list) else [orders]
        if not self._cancel_now:
            # 当前bar收盘处处理撤单
            for order in orders:
                norder = copy.deepcopy(order)
                norder.side = TradeSide.CANCEL
                # @TODO or self._orders ?
                # 结合实盘考虑, 实盘可能自动撤单。
                self._orders.append(norder)
            return
        ## 立即处理撤单
        #temp = copy.deepcopy(self._orders)
        #self._orders = []
        #for order in orders:
        #order.side = TradeSide.CANCEL
        #self._orders.append(order)
        #self.process_trading_events(False)
        #self._orders = temp

    @property
    def open_orders(self):
        """ 未成交的订单 """
        return self.blotter.open_orders

    def all_positions(self):
        return self.blotter.positions.values()

    def position(self, contract, direction):
        try:
            poskey = PositionKey(contract, direction)
            return self.blotter.positions[poskey]
        except KeyError:
            return None

    def pos(self, contract, direction):
        try:
            poskey = PositionKey(contract, direction)
            return self.blotter.positions[poskey].closable
        except KeyError:
            return 0

    def cash(self):
        return self.blotter.holding['cash']

    def equity(self):
        return self.blotter.holding['equity']

    def profit(self, contract):
        pass

    def day_profit(self, contract):
        """ 当前持仓的浮动盈亏 """
        pass
예제 #6
0
class TradingDelegator(object):
    """"""
    def __init__(self, name, settings={}):
        self.events_pool = EventsPool()
        # @TODO merge blotter and exchange
        self.blotter = SimpleBlotter(name, self.events_pool, settings)
        self.exchange = Exchange(name, self.events_pool, strict=True)
        self._orders = []
        self._datetime = None
        self._cancel_now = False  # 是当根bar还是下一根bar撤单成功。

    def update_environment(self, dt, ticks, bars):
        """ 更新模拟交易所和订单管理器的数据,时间,持仓 """
        self.blotter.update_datetime(dt)
        self.exchange.update_datetime(dt)
        self.blotter.update_data(ticks, bars)
        self._datetime = dt

    def process_trading_events(self, at_baropen):
        """ 提交订单,撮合,更新持仓 """
        if self._orders:
            self.events_pool.put(SignalEvent(self._orders))
        if not self._orders:
            # 没有交易信号,确保至少运行一次
            self.events_pool.put(OnceEvent())
        self._process_trading_events(at_baropen)
        self._orders = []

    def _process_trading_events(self, at_baropen):
        """"""
        while True:
            # 事件处理。
            try:
                event = self.events_pool.get()
            except queue.Empty:
                assert (False)
            except IndexError:
                break
            else:
                # if event.type == 'MARKET':
                # strategy.calculate_signals(event)
                # port.update_timeindex(event)
                if event.route == Event.SIGNAL:
                    assert (not at_baropen)
                    self.blotter.update_signal(event)
                elif event.route == Event.ORDER:
                    assert (not at_baropen)
                    self.exchange.insert_order(event)
                elif event.route == Event.FILL:
                    # 模拟交易接口收到报单成交
                    self.blotter.api.on_transaction(event)
            # 价格撮合。note: bar价格撮合要求撮合置于运算后面。
            # @TODO tick 回测不一样
            if event.route == Event.ONCE or event.route == Event.ORDER:
                self.exchange.make_market(self.blotter._bars, at_baropen)
        self.blotter.update_status(self._datetime, at_baropen)

    def buy(self, price, quantity, symbol=None):
        """ 开多仓

        Args:
            price (float): 价格, 0表市价。
            quantity (int): 数量。
            symbol (str): 合约
        """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能下单!')
        if symbol:
            contract = Contract(symbol) if isinstance(symbol, str) else symbol
        else:
            contract = self.contract
        price_type = PriceType.MKT if price == 0 else PriceType.LMT
        self._orders.append(
            Order(None, contract, price_type, TradeSide.OPEN, Direction.LONG,
                  float(price), quantity))

    def sell(self, price, quantity, symbol=None):
        """ 平多仓。

        Args:
           price (float): 价格, 0表市价。
           quantity (int): 数量。
           symbol (str): 合约
        """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能下单!')
        if symbol:
            contract = Contract(symbol) if isinstance(symbol, str) else symbol
        else:
            contract = self.contract
        price_type = PriceType.MKT if price == 0 else PriceType.LMT
        self._orders.append(
            Order(None, contract, price_type, TradeSide.CLOSE, Direction.LONG,
                  float(price), quantity))

    def short(self, price, quantity, symbol=None):
        """ 开空仓

        Args:
            price (float): 价格, 0表市价。
            quantity (int): 数量。
            symbol (str): 合约
        """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能下单!')
        if symbol:
            contract = Contract(symbol) if isinstance(symbol, str) else symbol
        else:
            contract = self.contract
        price_type = PriceType.MKT if price == 0 else PriceType.LMT
        self._orders.append(
            Order(None, contract, price_type, TradeSide.OPEN, Direction.SHORT,
                  float(price), quantity))

    def cover(self, price, quantity, symbol=None):
        """ 平空仓。

        Args:
           price (float): 价格, 0表市价。
           quantity (int): 数量。
           symbol (str): 合约
        """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能下单!')
        if symbol:
            contract = Contract(symbol) if isinstance(symbol, str) else symbol
        else:
            contract = self.contract
        price_type = PriceType.MKT if price == 0 else PriceType.LMT
        self._orders.append(
            Order(None, contract, price_type, TradeSide.CLOSE, Direction.SHORT,
                  float(price), quantity))

    def cancel(self, orders):
        """ 撤单

        Args:
            orders (list/Order): 撤单,参数为list表示撤多个单。
        """
        orders = orders if isinstance(orders, list) else [orders]
        if not self._cancel_now:
            # 当前bar收盘处处理撤单
            for order in orders:
                norder = copy.deepcopy(order)
                norder.side = TradeSide.CANCEL
                # @TODO or self._orders ?
                # 结合实盘考虑, 实盘可能自动撤单。
                self._orders.append(norder)
            return
        ## 立即处理撤单
        #temp = copy.deepcopy(self._orders)
        #self._orders = []
        #for order in orders:
        #order.side = TradeSide.CANCEL
        #self._orders.append(order)
        #self.process_trading_events(False)
        #self._orders = temp

    @property
    def open_orders(self):
        """ 未成交的订单 """
        return list(self.blotter.open_orders)

    def all_positions(self):
        """ 返回所有持仓列表 [Position] """
        return list(six.itervalues(self.blotter.positions))

    def position(self, direction='long', symbol=None):
        """ 合约当前持仓仓位。

        Args:
            direction (str/int): 持仓方向。多头 - 'long' / 1 ;空头 - 'short'  / 2
            , 默认为多头。

            symbol (str): 字符串合约,默认为None表示主合约。

        Returns:
            Position. 该合约的持仓
        """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能查询当前持仓!')
        direction = Direction.arg_to_type(direction)
        contract = Contract(symbol) if symbol else \
            self.contract
        # @TODO assert direction
        try:
            poskey = PositionKey(contract, direction)
            return self.blotter.positions[poskey]
        except KeyError:
            return None

    def pos(self, direction='long', symbol=None):
        """  合约的当前可平仓位。

        Args:
            direction (str/int): 持仓方向。多头 - 'long' / 1 ;空头 - 'short'  / 2
            , 默认为多头。

            symbol (str): 字符串合约,默认为None表示主合约。

        Returns:
            int. 该合约的持仓数目。
        """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能查询当前持仓!')
        direction = Direction.arg_to_type(direction)
        # @TODO symbol xxxxx
        contract = Contract(symbol) if symbol else \
            self.contract
        # @TODO assert direction
        try:
            poskey = PositionKey(contract, direction)
            return self.blotter.positions[poskey].closable
        except KeyError:
            return 0

    def cash(self):
        """ 现金。 """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能查询可用资金!')
        return self.blotter.holding['cash']

    def equity(self):
        """ 当前权益 """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能查询当前权益!')
        return self.blotter.holding['equity']

    def profit(self, contract=None):
        """ 当前持仓的历史盈亏 """
        # if not self.on_bar:
        # log.warn('只有on_bar函数内能查询总盈亏!')
        # return
        pass

    def day_profit(self, contract=None):
        """ 当前持仓的浮动盈亏 """
        #if not self.on_bar:
        #log.warn('只有on_bar函数内能查询浮动盈亏!')
        #return
        pass

    def test_cash(self):
        """  当根bar时间终点撮合后的可用资金,用于测试。 """
        self.process_trading_events(at_baropen=False)
        return self.cash()

    def test_equity(self):
        """  当根bar时间终点撮合后的权益,用于测试。 """
        self.process_trading_events(at_baropen=False)
        return self.equity()