def market_close(self, event: Event, account: AbstractAccount, data_portal: DataPortal): account.cancel_all_open_orders() for code in account.positions.keys(): sell_order = MKTOrder(code, OrderDirection.SELL, account.positions[code], event.visible_time) account.place_order(sell_order)
def calc_net_value(event: Event, account: AbstractAccount, data_portal: DataPortal): if len(account.positions) > 0: current_price: Mapping[str, Price] = data_portal.current_price( list(account.positions.keys()), event.visible_time, delay_allowed=Timedelta(seconds=20)) cp = {code: current_price[code].price for code in current_price.keys()} else: cp = {} account.calc_net_value(cp, event.visible_time)
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)
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
def market_open(self, event: Event, account: AbstractAccount, data_portal: DataPortal): if len(account.positions) > 0: raise RuntimeError("错误的账户状态") # 检查最新价格的时间是否是开盘之后的价格 open_time = event.visible_time code = self.scope.codes[0] while True: cp = data_portal.current_price([code], event.visible_time)[code] if cp.time >= open_time: break logging.info("没有获取到最新的价格,将会重试, 获取到的价格是:{}, 事件时间是:{}".format( cp, event.visible_time)) time.sleep(1) quantity = int(account.cash * 0.5 / cp.price) buy_order = MKTOrder(code, OrderDirection.BUY, quantity, event.visible_time) account.place_order(buy_order) self.base_price = cp.price
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))
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)
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
def match(self, event: Event, account: AbstractAccount, data_portal: DataPortal): if not (isinstance(event.data, Bar) or isinstance(event.data, Tick)): raise RuntimeError("wrong event data") account.match(event.data)