Пример #1
0
    def order_status_change(self, order: Order, account: AbstractAccount):
        if order.status != OrderStatus.FILLED:
            return
        current_time = order.filled_end_time
        if current_time >= (
                self.scope.trading_calendar.next_close(current_time) -
                Timedelta(minutes=1)):
            # 收盘前一分钟不下单
            return
        # 取消当前所有的订单
        account.cancel_all_open_orders()

        # 挂上下两个网格的交易订单
        k = round((order.filled_avg_price - self.base_price) /
                  self.base_price / self.p)
        hold_quantity = 0 if self.code not in account.positions else account.positions[
            self.code]
        # 上一个格子的卖单
        if (k + 1) <= self.n:
            up_percentage = 0.5 - (k + 1) * (0.5 / self.n)
            up_price = self.base_price + self.base_price * self.p * (k + 1)
            up_net_val = hold_quantity * up_price + account.cash
            dest_quantity = int(up_net_val * up_percentage / up_price)
            sell_order = LimitOrder(self.code, OrderDirection.SELL,
                                    hold_quantity - dest_quantity,
                                    current_time, up_price)
            account.place_order(sell_order)
        # 下一个格子的买单
        if (k - 1) >= -self.n:
            down_percentage = 0.5 - (k - 1) * (0.5 / self.n)
            down_price = self.base_price + self.base_price * self.p * (k - 1)
            down_net_val = hold_quantity * down_price + account.cash
            dest_quantity = int(down_net_val * down_percentage / down_price)
            buy_order = LimitOrder(self.code, OrderDirection.BUY,
                                   dest_quantity - hold_quantity, current_time,
                                   down_price)
            account.place_order(buy_order)
Пример #2
0
    def market_open(self, event: Event, account: AbstractAccount, data_portal: DataPortal):
        dest_position = 0
        current_position = 0
        net_value = None

        # 等待直到获取到最新的股票价格
        current_price = None
        try:
            current_price = data_portal.current_price([self.code], event.visible_time)[self.code].price
        except:
            logging.error("没有获取到当天的开盘价,code:{}".format(self.code))
        if current_price:
            net_value = account.net_value({self.code: current_price})

        current_bid_ask = None
        try:
            current_bid_ask = data_portal.current_bid_ask([self.code])[self.code]
        except:
            logging.error("没有获取到最新的买卖价, code:{}".format(self.code))

        if self.last_close_price and current_price:
            if np.log(current_price / self.last_close_price) < 0.025:
                dest_position = int(net_value / current_price)

        if len(account.positions) > 0:
            current_position = account.positions[self.code]

        change = dest_position - current_position

        if change != 0:
            direction = OrderDirection.BUY if change > 0 else OrderDirection.SELL
            reason = "时间:{}, 当前持仓:{}, 总市值:{}, 目标持仓:{}, 昨日收盘价:{}, 今日开盘价:{}, 最新买卖价:{}, strategy:{}" \
                .format(event.visible_time, current_position, net_value, dest_position, self.last_close_price,
                        current_price, current_bid_ask.__dict__ if current_bid_ask else None, TestStrategy3.__doc__)
            if current_bid_ask:
                delta = 0.01
                limit_price = (current_bid_ask.bid_price + delta) if direction == OrderDirection.BUY else (
                        current_bid_ask.ask_price - delta)
                order = LimitOrder(self.code, direction, abs(change), event.visible_time, limit_price)
                order.with_reason(reason)
                account.place_order(order)
                # self.ensure_order_filled(account, data_portal, order, period=30, retry_count=3)
                self.ensure_order_filled_v2(account, data_portal, order, duration=60, delta=delta)
            else:
                order = MKTOrder(self.code, direction, abs(change), event.visible_time)
                order.with_reason(reason)
                account.place_order(order)
        else:
            msg = "不需要下单, 时间:{}, 当前持仓:{}, 总市值:{}, 目标持仓:{}, 昨日收盘价:{}, 今日开盘价:{}". \
                format(event.visible_time, current_position, net_value, dest_position, self.last_close_price,
                       current_price)
            logging.info(msg)
Пример #3
0
    def _to_order(self, od_model: UserOrderModel) -> Order:
        if od_model.type == "MKTOrder":
            o = MKTOrder(od_model.code, OrderDirection(od_model.direction),
                         od_model.quantity,
                         self._to_timestamp(od_model.place_time))
        elif od_model.type == "LimitOrder":
            o = LimitOrder(od_model.code, OrderDirection(od_model.direction),
                           od_model.quantity,
                           self._to_timestamp(od_model.place_time),
                           od_model.limit_price)
        elif od_model.type == "DelayMKTOrder":
            o = DelayMKTOrder(od_model.code,
                              OrderDirection(od_model.direction),
                              od_model.quantity,
                              self._to_timestamp(od_model.place_time),
                              Timedelta(od_model.delay_time))
        elif od_model.type == 'CrossMKTOrder':
            o = CrossMKTOrder(od_model.code,
                              OrderDirection(od_model.direction),
                              od_model.quantity,
                              self._to_timestamp(od_model.place_time),
                              CrossDirection(od_model.cross_direction),
                              od_model.cross_price)
        else:
            raise RuntimeError("wrong order type")
        new_execution_map = {}
        for exec_id in od_model.execution_map.keys():
            oe_model: UserOrderExecutionModel = od_model.execution_map[exec_id]
            oe = OrderExecution(exec_id, oe_model.version, oe_model.commission,
                                oe_model.filled_quantity,
                                oe_model.filled_avg_price,
                                self._to_timestamp(oe_model.filled_start_time),
                                self._to_timestamp(oe_model.filled_end_time),
                                OrderDirection(oe_model.direction),
                                oe_model.attributes)
            new_execution_map[exec_id] = oe
        o.execution_map = new_execution_map

        o.filled_start_time = self._to_timestamp(od_model.filled_start_time)
        o.filled_end_time = self._to_timestamp(od_model.filled_end_time)
        o.filled_avg_price = od_model.filled_avg_price
        o.filled_quantity = od_model.filled_quantity
        o.status = OrderStatus(od_model.status)
        return o
Пример #4
0
    def market_close(self, event: Event, account: AbstractAccount, data_portal: DataPortal):
        dest_position = 0
        current_position = 0
        net_value = None

        # 等待直到获取到最新的股票价格
        current_price = None
        try:
            current_price = data_portal.current_price([self.code], event.visible_time)[self.code].price
        except:
            logging.error("没有获取到当天的开盘价,code:{}".format(self.code))
        if current_price:
            net_value = account.net_value({self.code: current_price})

        if current_price and self.last_close and current_price > self.last_close:
            dest_position = int(net_value / current_price)

        if len(account.positions) > 0:
            current_position = account.positions[self.code]

        change = dest_position - current_position
        if change != 0:
            direction = OrderDirection.BUY if change > 0 else OrderDirection.SELL
            reason = "时间:{}, 当前持仓:{}, 总市值:{}, 目标持仓:{}, 昨日收盘价:{}, 今日收盘价:{}, strategy:{}".format(event.visible_time,
                                                                                  current_position,
                                                                                  net_value, dest_position,
                                                                                  self.last_close,
                                                                                  current_price, TestStrategy2.__doc__)
            if current_price:
                order = LimitOrder(self.code, direction, abs(change), event.visible_time, current_price)
                order.with_reason(reason)
                account.place_order(order)
                self.ensure_order_filled(account, data_portal, order, 40, 1)
            else:
                order = MKTOrder(self.code, direction, abs(change), event.visible_time)
                order.with_reason(reason)
                account.place_order(order)
        else:
            logging.info("不需要下单, 时间:{}, 当前持仓:{}, 总市值:{}, 目标持仓:{}, 今日开盘价:{}, 今日收盘价:{}".
                         format(event.visible_time,
                                current_position,
                                net_value, dest_position,
                                self.last_open,
                                current_price))

        self.last_close = current_price
Пример #5
0
 def on_tick(self, event: Event, account: AbstractAccount, data_portal: DataPortal):
     if not self.market_is_open:
         return
     if not isinstance(event.data, Tick):
         raise RuntimeError("wrong data")
     data = DataFrame([{'visible_time': event.data.visible_time, 'price': event.data.price}]).set_index('visible_time')
     self.daily_ticks.append(data)
     now = Timestamp.now(tz='Asia/Shanghai')
     start = now - self.time_span
     check_df = self.daily_ticks[start: now]
     this_price = event.data.price
     if len(account.get_open_orders()) <= 0:
         if len(account.positions) > 0:
             max_price = check_df['price'].max()
             change = abs((this_price - max_price) / max_price)
             if change > self.threshold:
                 reason = '当前价格:{}, 时间范围:{}的最高价为:{}, 当前持仓:{}'.\
                     format(this_price, self.time_span, max_price, account.positions)
                 order = LimitOrder(self.code, OrderDirection.SELL, quantity=abs(account.positions[self.code]),
                                    place_time=event.visible_time, limit_price=this_price)
                 order.with_reason(reason)
                 account.place_order(order)
                 self.ensure_order_filled(account, data_portal, order, period=10, retry_count=2)
             else:
                 logging.info("当前价格:{}, 时间范围:{}的最高价为:{}, 变动为:{}".
                              format(this_price, self.time_span, max_price, change))
         else:
             lowest_price = check_df['price'].min()
             change = abs((this_price - lowest_price) / lowest_price)
             if change > self.threshold:
                 reason = '当前价格:{}, 时间范围:{}的最低价为:{}, 当前持仓:{}'.\
                     format(this_price, self.time_span, lowest_price, account.positions)
                 quantity = int(account.cash / this_price)
                 order = LimitOrder(self.code, OrderDirection.BUY, quantity=quantity,
                                    place_time=event.visible_time, limit_price=this_price)
                 order.with_reason(reason)
                 account.place_order(order)
                 self.ensure_order_filled(account, data_portal, order, period=10, retry_count=2)
             else:
                 logging.info("当前价格:{}, 时间范围:{}的最低价为:{}, 变动为:{}".
                              format(this_price, self.time_span, lowest_price, change))
Пример #6
0
 def ensure():
     try:
         time.sleep(period)
         logging.info("ensure order filled thread start")
         if order.status == OrderStatus.CREATED or order.status == OrderStatus.PARTIAL_FILLED \
                 or order.status == OrderStatus.SUBMITTED:
             account.cancel_open_order(order)
             # 保证下单的总价值是相同的
             remain_quantity = order.quantity - order.filled_quantity
             cp = data_portal.current_price(
                 [order.code],
                 Timestamp.now(tz='Asia/Shanghai'))[order.code]
             new_quantity = int(remain_quantity * order.limit_price /
                                cp.price)
             now = Timestamp.now(tz='Asia/Shanghai')
             if retry_count > 1:
                 new_order = LimitOrder(order.code, order.direction,
                                        new_quantity, now, cp.price)
             else:
                 new_order = MKTOrder(order.code, order.direction,
                                      new_quantity, now)
             account.place_order(new_order)
             if retry_count > 1:
                 self.ensure_order_filled(account, data_portal,
                                          new_order, period,
                                          retry_count - 1)
         else:
             logging.info("没有还未成交的订单, 不需要ensure")
     except:
         import traceback
         err_msg = "ensure order filled失败:{}".format(
             traceback.format_exc())
         logging.error(err_msg)
         # 显示告警,因为在线程的Runable方法中,不能再抛出异常。
         do_alarm('ensure order filled', AlarmLevel.ERROR, None, None,
                  '{}'.format(traceback.format_exc()))
Пример #7
0
    def market_close(self, event: Event, account: AbstractAccount,
                     data_portal: DataPortal):
        dest_position = 0
        current_position = 0
        net_value = None

        # 等待直到获取到最新的股票价格
        current_price = None
        try:
            current_price = data_portal.current_price(
                [self.code], event.visible_time)[self.code].price
        except:
            logging.error("没有获取到当天的开盘价,code:{}".format(self.code))
        if current_price:
            net_value = account.net_value({self.code: current_price})

        current_bid_ask = None
        try:
            current_bid_ask = data_portal.current_bid_ask([self.code
                                                           ])[self.code]
        except:
            logging.error("没有获取到最新的买卖价,code:{}".format(self.code))

        # if current_price and self.last_close and current_price > self.last_close:
        if True:
            dest_position = int(net_value * self.long_leverage / current_price)

        if len(account.positions) > 0:
            current_position = account.positions[self.code]

        change = dest_position - current_position
        if change != 0:
            direction = OrderDirection.BUY if change > 0 else OrderDirection.SELL
            reason = "时间:{}, 当前持仓:{}, 总市值:{}, 目标持仓:{}, 昨日收盘价:{}, 今日收盘价:{}, " \
                     "买卖价:{}, strategy:{}".format(event.visible_time,
                                                  current_position,
                                                  net_value, dest_position,
                                                  self.last_close,
                                                  current_price,
                                                  current_bid_ask.__dict__ if current_bid_ask else None,
                                                  SPCEStrategy.__doc__)
            if current_bid_ask:
                delta = 0.01
                limit_price = (current_bid_ask.bid_price +
                               delta) if direction == OrderDirection.BUY else (
                                   current_bid_ask.ask_price - delta)
                order = LimitOrder(self.code, direction, abs(change),
                                   event.visible_time, limit_price)
                order.with_reason(reason)
                account.place_order(order)
                # self.ensure_order_filled(account, data_portal, order, 40, 1)
                self.ensure_order_filled_v2(account, data_portal, order, 40,
                                            delta)
            else:
                order = MKTOrder(self.code, direction, abs(change),
                                 event.visible_time)
                order.with_reason(reason)
                account.place_order(order)
        else:
            logging.info(
                "不需要下单, 时间:{}, 当前持仓:{}, 总市值:{}, 目标持仓:{}, 今日开盘价:{}, 今日收盘价:{}".
                format(event.visible_time, current_position, net_value,
                       dest_position, self.last_open, current_price))

        self.last_close = current_price
Пример #8
0
acc.with_order_callback(TestStrategy(None))
code = '700_STK_HKD_SEHK'
contract = acc.cli.code_to_contract(code)
ib_order: IBOrder = IBOrder()
ib_order.orderType = "MKT"
ib_order.totalQuantity = 100
# ib_order.lmtPrice = 85
ib_order.action = 'SELL'
# ib_order.outsideRth = True
# ib_order.tif = "GTD"
# ib_order.goodAfterTime = '18:45:00'
# ib_order.goodTillDate = '19:56:00'
# ib_order.orderType = "LIMIT"
# ib_order.lmtPrice = 100
# ib_order.totalQuantity = 100
# ib_order.action = 'BUY'
# ib_order.outsideRth = True
# # 设置自适应算法
# ib_order.algoStrategy = 'Adaptive'
# ib_order.algoParams = [TagValue("adaptivePriority", 'Normal')]

order: Order = LimitOrder(code,
                          OrderDirection.BUY,
                          quantity=1000,
                          place_time=Timestamp.now(),
                          limit_price=644)

# acc.cli.cli.cancelOrder(34)
# acc.cli.placeOrder(acc.cli.next_valid_id(), contract, ib_order)
acc.place_order(order)
print("done")