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 adjustBars(instrument, bars, startdate, enddate): bars = [] bars_in_dtrange = [bar for bar in bars if startdate.replace(tzinfo=None) <= bar.getDateTime() <= enddate.replace(tzinfo=None)] bars_in_dtrange.sort(key=lambda bar: bar.getDateTime(), reverse=True) k = 0 splitdataList = [] dividendList = [] for bar in bars_in_dtrange: splitdata = bar.getSplit() dividend = bar.getDividend() if splitdata != 1.0: splitdataList.append(bar.getSplit()) if dividend != 0.0: adjFactor = (bar.getClose() + bar.getDividend()) / bar.getClose() dividendList.append(adjFactor) #### Special case.... end date / analysis date nothing to do.. if (k==0): bar = BasicBar(bar.getDateTime(), bar.getOpen() , bar.getHigh(), bar.getLow(), bar.getClose(), bar.getVolume(), bar.getClose(), Frequency.DAY) bars.append(bar) else: #### Adjust OHLC & Volume data for split adjustments and dividend adjustments Open = bar.getOpen() High = bar.getHigh() Low = bar.getLow() Close = bar.getClose() Volume = bar.getVolume() ### adjust data for splits for split in splitdataList: Open = Open / split High = High / split Low = Low / split Close = Close /split Volume = Volume * split ### adjust data for dividends for adjFactor in dividendList: Open = Open / adjFactor High = High / adjFactor Low = Low / adjFactor Close = Close / adjFactor Volume = Volume * adjFactor bar = BasicBar(bar.getDateTime(), Open , High, Low, Close, Volume, Close, Frequency.DAY) bars.append(bar) k +=1 feed = Feed(Frequency.DAY, 1024) return feed.loadBars(instrument+"_adjusted", bars)
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 get_range_price_trigger(action, lowPrice, upPrice, useAdjustedValues, bar): ret = None open_ = bar.getOpen(useAdjustedValues) high = bar.getHigh(useAdjustedValues) low = bar.getLow(useAdjustedValues) # If the bar is below the limit price, use the open price. # If the bar includes the limit price, use the open price or the limit price. # if action in [broker.Order.Action.BUY, broker.Order.Action.BUY_TO_COVER]: # if high < limitPrice: # ret = open_ # elif limitPrice >= low: # if open_ < limitPrice: # The limit price was penetrated on open. # ret = open_ # else: # ret = limitPrice # If low of the bar is below lowPrice, use the open price when open is below lowPrice else use lowPrice. # If high of the bar is above upPrice, use the open price when open is above upPrice else use upPrice. if action in [broker.Order.Action.SELL, broker.Order.Action.SELL_SHORT]: if low < lowPrice: if open_ < lowPrice: ret = open_ else: ret = lowPrice elif upPrice <= high: if open_ > upPrice: # The limit price was penetrated on open. ret = open_ else: ret = upPrice else: # Unknown action assert(False) return ret
def compute_BBands(instrument, startdate, enddate ): from pyalgotrade.talibext import indicator bBandsPeriod = 20 #### No of periods..... feed = redis_build_feed_EOD_RAW(instrument, startdate, enddate) barsDictForCurrAdj = {} barsDictForCurrAdj[instrument] = feed.getBarSeries(instrument) feedLookbackEndAdj = xiquantPlatform.xiQuantAdjustBars(barsDictForCurrAdj, startdate, enddate) feedLookbackEndAdj.adjustBars() closeDS = feedLookbackEndAdj.getCloseDataSeries(instrument + "_adjusted") upper, middle, lower = indicator.BBANDS(closeDS, len(closeDS), bBandsPeriod, 2.0, 2.0) dateTimes = feedLookbackEndAdj.getDateTimes(instrument + "_adjusted") upperDS = numpy_to_highchartds(dateTimes, upper, startdate, enddate) middleDS = numpy_to_highchartds(dateTimes, middle, startdate, enddate) lowerDS = numpy_to_highchartds(dateTimes, lower, startdate, enddate) ##########Display price seriesin the center of Bolinger bands......################## barDS = feedLookbackEndAdj.getBarSeries(instrument + "_adjusted") adj_Close_Series = [] for bar in barDS: dt = bar.getDateTime() sec = calendar.timegm(dt.timetuple()) dtInMilliSeconds = int(sec * 1000) adjPrice_val = [dtInMilliSeconds, bar.getOpen(), bar.getHigh(), \ bar.getLow(), bar.getClose()] adj_Close_Series.append(adjPrice_val) return upperDS, middleDS, lowerDS, adj_Close_Series
def fillStopOrder(self, order, broker_, 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(): fillSize = self.__calculateFillSize(order, broker_, bar) if fillSize == 0: broker_.getLogger().debug("Not enough volume to fill %s stop order [%s] for %d 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()) ret = FillInfo(price, fillSize) return ret
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): broker_.getLogger().debug('fillMarketOrder') # 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(): broker_.getLogger().debug('fillMarketOrder -> getFillOnClose()') price = bar.getClose(broker_.getUseAdjustedValues()) else: broker_.getLogger().debug('fillMarketOrder -> getFillOnOpen()') 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() != pyalgotrade.bar.Frequency.TRADE: price = self.__slippageModel.calculatePrice( order, price, fillSize, bar, self.__volumeUsed[order.getInstrument()]) broker_.getLogger().debug('fillMarketOrder, return FillInfo') return FillInfo(price, fillSize)
def get_limit_price_trigger(action, limitPrice, useAdjustedValues, bar): ret = None open_ = bar.getOpen(useAdjustedValues) high = bar.getHigh(useAdjustedValues) low = bar.getLow(useAdjustedValues) # If the bar is below the limit price, use the open price. # If the bar includes the limit price, use the open price or the limit price. if action in [broker.Order.Action.BUY, broker.Order.Action.BUY_TO_COVER]: if high < limitPrice: ret = open_ elif limitPrice >= low: if open_ < limitPrice: # The limit price was penetrated on open. ret = open_ else: ret = limitPrice # If the bar is above the limit price, use the open price. # If the bar includes the limit price, use the open price or the limit price. elif action in [broker.Order.Action.SELL, broker.Order.Action.SELL_SHORT]: if low > limitPrice: ret = open_ elif limitPrice <= high: if open_ > limitPrice: # The limit price was penetrated on open. ret = open_ else: ret = limitPrice 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() != pyalgotrade.bar.Frequency.TRADE: price = self.__slippageModel.calculatePrice( order, price, fillSize, bar, self.__volumeUsed[order.getInstrument()] ) return FillInfo(price, fillSize)
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 fillStopOrder(self, order, broker_, 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(): fillSize = self.__calculateFillSize(order, broker_, bar) if fillSize == 0: broker_.getLogger().debug("Not enough volume to fill %s stop order [%s] for %d 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()) ret = FillInfo(price, fillSize) return ret
def onBars(self, bars): for instrument in bars.getInstruments(): bar = bars[instrument] self.info("%s: %s %s %s %s %s %s" % ( instrument, bar.getOpen(), bar.getHigh(), bar.getLow(), bar.getClose(), bar.getAdjClose(), bar.getVolume(), ))
def fillMarketOrder(self, order, broker_, bar): fillSize = self.__calculateFillSize(order, broker_, bar) if fillSize == 0: return None ret = None if order.getFillOnClose(): price = bar.getClose(broker_.getUseAdjustedValues()) else: price = bar.getOpen(broker_.getUseAdjustedValues()) if price is not None: ret = FillInfo(price, fillSize) return ret
def dayInfo(self, bar): try: self.__openD[-1] except AttributeError: self.__openD = [] self.__highD = [] self.__lowD = [] self.__closeD = [] self.__upper_limit = [] self.__lower_limit = [] if len(self.__datetime) < 2: self.__openD.append(bar.getOpen()) self.__highD.append(self.__high[-1]) self.__lowD.append(self.__low[-1]) self.__closeD.append(self.__close[-1]) return # if another day if self.__datetime[-1].date() != self.__datetime[-2].date(): self.__openD.append(bar.getOpen()) self.__highD.append(self.__high[-1]) self.__lowD.append(self.__low[-1]) self.__closeD.append(self.__close[-1]) self.__upper_limit.append( round(round(self.__closeD[-2] * 1.1 * 1000) / 10) / 100) self.__lower_limit.append( round(round(self.__closeD[-2] * 0.9 * 1000) / 10) / 100) print self.__datetime[-1].date(), self.__datetime[-2].date( ), self.__openD[-1] elif self.__datetime[-1].date() == self.__datetime[-2].date(): if self.__high[-1] > self.__highD[-1]: self.__highD[-1] = self.__high[-1] if self.__low[-1] < self.__lowD[-1]: self.__lowD[-1] = self.__low[-1] self.__closeD[-1] = self.__close[-1]
def fillMarketOrder(self, order, broker_, bar): fillSize = self.__calculateFillSize(order, broker_, bar) if fillSize == 0: broker_.getLogger().debug("Not enough volume to fill %s market order [%s] for %d share/s" % (order.getInstrument(), order.getId(), order.getRemaining())) return None ret = None if order.getFillOnClose(): price = bar.getClose(broker_.getUseAdjustedValues()) else: price = bar.getOpen(broker_.getUseAdjustedValues()) if price is not None: ret = FillInfo(price, fillSize) return ret
def dayInfo(self, bar): try: self.__openD[-1] except AttributeError: self.__openD = [] self.__highD = [] self.__lowD = [] self.__closeD = [] self.__upper_limit = [] self.__lower_limit = [] if len(self.__datetime) < 2: self.__openD.append(bar.getOpen()) self.__highD.append(self.__high[-1]) self.__lowD.append(self.__low[-1]) self.__closeD.append(self.__close[-1]) return # if another day if self.__datetime[-1].date() != self.__datetime[-2].date(): self.__openD.append(bar.getOpen()) self.__highD.append(self.__high[-1]) self.__lowD.append(self.__low[-1]) self.__closeD.append(self.__close[-1]) self.__upper_limit.append(round(round(self.__closeD[-2] * 1.1 * 1000) / 10) / 100) self.__lower_limit.append(round(round(self.__closeD[-2] * 0.9 * 1000) / 10) / 100) print self.__datetime[-1].date(), self.__datetime[-2].date(), self.__openD[-1] elif self.__datetime[-1].date() == self.__datetime[-2].date(): if self.__high[-1] > self.__highD[-1]: self.__highD[-1] = self.__high[-1] if self.__low[-1] < self.__lowD[-1]: self.__lowD[-1] = self.__low[-1] self.__closeD[-1] = self.__close[-1]
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() != pyalgotrade.bar.Frequency.TRADE: price = self.__slippageModel.calculatePrice( order, price, fillSize, bar, self.__volumeUsed[order.getInstrument()] ) ret = FillInfo(price, fillSize) return ret
def adjustBars(self): for key, value in self.__barsDict.iteritems(): basicbars = [] bars = value bars_in_dtrange = [bar for bar in bars if self.__startdate.replace(tzinfo=None) <= bar.getDateTime() <= self.__enddate.replace(tzinfo=None)] bars_in_dtrange.sort(key=lambda bar: bar.getDateTime(), reverse=True) k = 0 splitdataList = [] dividendList = [] for bar in bars_in_dtrange: splitdata = float(bar.getSplit()) dividend = float(bar.getDividend()) if splitdata != 1.0: splitdataList.append(bar.getSplit()) if dividend != 0.0: adjFactor = (bar.getClose() + bar.getDividend()) / bar.getClose() dividendList.append(adjFactor) #### Special case.... end date / analysis date nothing to do.. if (k==0): bar = BasicBar(bar.getDateTime(), bar.getOpen() , bar.getHigh(), bar.getLow(), bar.getClose(), bar.getVolume(), bar.getClose(), Frequency.DAY) basicbars.append(bar) else: #### Adjust OHLC & Volume data for split adjustments and dividend adjustments Open = bar.getOpen() High = bar.getHigh() Low = bar.getLow() Close = bar.getClose() Volume = bar.getVolume() ### adjust data for splits for split in splitdataList: Open = Open / split High = High / split Low = Low / split Close = Close /split Volume = Volume * split ### adjust data for dividends for adjFactor in dividendList: Open = Open / adjFactor High = High / adjFactor Low = Low / adjFactor Close = Close / adjFactor Volume = Volume * adjFactor bar = BasicBar(bar.getDateTime(), Open , High, Low, Close, Volume, Close, Frequency.DAY) basicbars.append(bar) k +=1 DateTimes = [] OpenSeries = SequenceDataSeries(4000) HighSeries = SequenceDataSeries(4000) LowSeries = SequenceDataSeries(4000) CloseSeries = SequenceDataSeries(4000) VolumeSeries = SequenceDataSeries(4000) TypicalSeries = SequenceDataSeries(4000) barSeries = BarDataSeries(4000) basicbars.sort(key=lambda bar: bar.getDateTime(), reverse=False) for bar in basicbars: DateTimes.append(bar.getDateTime()) OpenSeries.appendWithDateTime(bar.getDateTime(), bar.getOpen()) HighSeries.appendWithDateTime(bar.getDateTime(), bar.getHigh()) LowSeries.appendWithDateTime(bar.getDateTime(), bar.getLow()) CloseSeries.appendWithDateTime(bar.getDateTime(), bar.getClose()) VolumeSeries.appendWithDateTime(bar.getDateTime(), bar.getVolume()) TypicalSeries.appendWithDateTime(bar.getDateTime(), (bar.getClose()+bar.getHigh()+bar.getLow())/3.0) barSeries.appendWithDateTime(bar.getDateTime(), bar) self.__DateTimes[key+"_adjusted"] = DateTimes self.__OpenDataSeries[key+"_adjusted"] = OpenSeries self.__HighDataSeries[key+"_adjusted"] = HighSeries self.__LowDataSeries[key+"_adjusted"] = LowSeries self.__CloseDataSeries[key+"_adjusted"] = CloseSeries self.__VolumeDataSeries[key+"_adjusted"] = VolumeSeries self.__TypicalDataSeries[key+"_adjusted"] = TypicalSeries self.__barSeries[key+"_adjusted"] = barSeries
def resampledOnBar(self, bars): bar = bars[self.__instrument] # pyalgotrade.bar.BasicBar object # print("Date: {} Close: {} PriceHigh: {}" .format(bar.getDateTime(), round(bar.getClose(),2), round(bar.getHigh(),2) )) shares = int(self.getBroker().getCash() * 0.5 / bar.getHigh()) # 80% of cash stock # print("this is current total cash {}" .format(round(self.getBroker().getCash(),2))) # print("shares is {}" .format(shares)) print("Date: {} Open: {} Close: {} PriceLow: {} PriceHigh: {} ".format(bar.getDateTime(), round(bar.getOpen(), 2), round(bar.getClose(), 2),round(bar.getLow()), round(bar.getHigh()))) if self.__position is None: self.__position = self.enterLong(self.__instrument, shares, False, True) # this to enter market order # pyalgotrade.strategy.position.LongPosition object print("enter long for {} shares at {} price".format(shares, bar.getPrice())) print("remaining cash is " + str(self.getBroker().getCash())) print("position is " + str(self.__position.getShares())) elif not self.__position.exitActive(): # Returns True if the exit order is active # if not exit orders being active self.__position.exitMarket(True) # this just submits the market order and self.__position becomes none print("exit for {} shares at {} price".format(self.__position.getShares(), bar.getPrice())) print("remaining cash is " + str(self.getBroker().getCash())) print("position is " + str(self.__position.getShares()))