def get_stop_price_trigger(action, stopPrice, useAdjustedValues, bar): ret = None open_ = bar.getOpen(useAdjustedValues) high = bar.getHigh(useAdjustedValues) low = bar.getLow(useAdjustedValues) # If the bar is above the stop price, use the open price. # If the bar includes the stop price, use the open price or the stop price. Whichever is better. if action in [broker.Order.Action.BUY, broker.Order.Action.BUY_TO_COVER]: if low > stopPrice: ret = open_ elif stopPrice <= high: if open_ > stopPrice: # The stop price was penetrated on open. ret = open_ else: ret = stopPrice # If the bar is below the stop price, use the open price. # If the bar includes the stop price, use the open price or the stop price. Whichever is better. elif action in [broker.Order.Action.SELL, broker.Order.Action.SELL_SHORT]: if high < stopPrice: ret = open_ elif stopPrice >= low: if open_ < stopPrice: # The stop price was penetrated on open. ret = open_ else: ret = stopPrice else: # Unknown action assert (False) return ret
def fillMarketOrder(self, broker_, order, bar): # Calculate the fill size for the order. # 计算订单的建仓大小。 fillSize = self.__calculateFillSize(broker_, order, bar) if fillSize == 0: broker_.getLogger().debug( "Not enough volume to fill %s market order [%s] for %s share/s" % (order.getInstrument(), order.getId(), order.getRemaining())) return None # Unless its a fill-on-close order, use the open price. if order.getFillOnClose(): price = bar.getClose(broker_.getUseAdjustedValues()) else: price = bar.getOpen(broker_.getUseAdjustedValues()) assert price is not None # Don't slip prices when the bar represents the trading activity of a single trade. if bar.getFrequency() != mooquant.bar.Frequency.TRADE: price = self.__slippageModel.calculatePrice( order, price, fillSize, bar, self.__volumeUsed[order.getInstrument()]) return FillInfo(price, fillSize)
def addBar(self, instrument, bar, frequency): instrument = normalize_instrument(instrument) instrumentId = self.__getOrCreateInstrument(instrument) timeStamp = dt.datetime_to_timestamp(bar.getDateTime()) try: sql = "INSERT INTO bar (instrument_id, frequency, timestamp, open, high, low, close, volume, adj_close) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" params = [instrumentId, frequency, timeStamp, bar.getOpen(), bar.getHigh(), bar.getLow(), bar.getClose(), bar.getVolume(), bar.getAdjClose()] self.__connection.execute(sql, params) except sqlite3.IntegrityError: sql = "UPDATE bar SET open = ?, high = ?, low = ?, close = ?, volume = ?, adj_close = ?" \ " WHERE instrument_id = ? AND frequency = ? AND timestamp = ?" params = [bar.getOpen(), bar.getHigh(), bar.getLow(), bar.getClose(), bar.getVolume(), bar.getAdjClose(), instrumentId, frequency, timeStamp] self.__connection.execute(sql, params)
def fillStopOrder(self, broker_, order, bar): ret = None # First check if the stop price was hit so the market order becomes active. stopPriceTrigger = None if not order.getStopHit(): stopPriceTrigger = get_stop_price_trigger( order.getAction(), order.getStopPrice(), broker_.getUseAdjustedValues(), bar) order.setStopHit(stopPriceTrigger is not None) # If the stop price was hit, check if we can fill the market order. if order.getStopHit(): # Calculate the fill size for the order. fillSize = self.__calculateFillSize(broker_, order, bar) if fillSize == 0: broker_.getLogger().debug( "Not enough volume to fill %s stop order [%s] for %s share/s" % (order.getInstrument(), order.getId(), order.getRemaining())) return None # If we just hit the stop price we'll use it as the fill price. # For the remaining bars we'll use the open price. if stopPriceTrigger is not None: price = stopPriceTrigger else: price = bar.getOpen(broker_.getUseAdjustedValues()) assert price is not None # Don't slip prices when the bar represents the trading activity of a single trade. if bar.getFrequency() != mooquant.bar.Frequency.TRADE: price = self.__slippageModel.calculatePrice( order, price, fillSize, bar, self.__volumeUsed[order.getInstrument()]) ret = FillInfo(price, fillSize) return ret