def test_as_key(): d = {build_instrument("orcl/USD"): 1} assert build_instrument("orcl/USD") in d assert build_instrument("orcl/EUR") not in d assert build_instrument("aig/USD") not in d assert "orcl/USD" in d assert "orcl" not in d assert "aig" not in d
def __getitem__(self, instrument): """ Returns the :class:`pyalgotrade.bar.Bar` for a given instrument. If the instrument is not found an exception is raised. """ instrument = build_instrument(instrument) return self.__barDict[instrument]
def addBarsFromCSV(self, instrument, path, timezone=None, skipMalformedBars=False): """Loads bars for a given instrument from a CSV formatted file. The instrument gets registered in the bar feed. :param instrument: Instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. :param path: The path to the CSV file. :type path: string. :param timezone: The timezone to use to localize bars. Check :mod:`pyalgotrade.marketsession`. :type timezone: A pytz timezone. :param skipMalformedBars: True to skip errors while parsing bars. :type skipMalformedBars: boolean. """ if timezone is None: timezone = self.__timezone instrument = build_instrument(instrument) rowParser = RowParser(instrument, self.getDailyBarTime(), self.getFrequency(), timezone, self.__sanitizeBars) super(Feed, self).addBarsFromCSV(path, rowParser, skipMalformedBars=skipMalformedBars)
def addBarsFromCSV(self, instrument, path, timezone=None): """ Loads bars for a given instrument from a CSV formatted file. The instrument gets registered in the bar feed. :param instrument: Instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. :param path: The path to the CSV file. :type path: string. :param timezone: The timezone to use to localize bars. Check :mod:`pyalgotrade.marketsession`. :type timezone: A pytz timezone. """ if isinstance(timezone, int): raise Exception( "timezone as an int parameter is not supported anymore. Please use a pytz timezone instead." ) if timezone is None: timezone = self.__timezone instrument = build_instrument(instrument) rowParser = RowParser( instrument, self.getDailyBarTime(), self.getFrequency(), timezone, self.__sanitizeBars, self.__barClass ) super(Feed, self).addBarsFromCSV(path, rowParser)
def channel_to_instrument(channel): assert len(channel) == 6 ret = "%s/%s" % (channel[0:3], channel[3:]) ret = ret.upper() ret = build_instrument(ret) assert ret in SUPPORTED_INSTRUMENTS, "Invalid channel %s" % channel return ret
def __init__(self, instrument, dateTime, open_, high, low, close, volume, adjClose, frequency, extra={}): if high < low: raise Exception("high < low on %s" % (dateTime)) elif high < open_: raise Exception("high < open on %s" % (dateTime)) elif high < close: raise Exception("high < close on %s" % (dateTime)) elif low > open_: raise Exception("low > open on %s" % (dateTime)) elif low > close: raise Exception("low > close on %s" % (dateTime)) self.__instrument = build_instrument(instrument) self.__dateTime = dateTime self.__open = open_ self.__close = close self.__high = high self.__low = low self.__volume = volume self.__adjClose = adjClose self.__frequency = frequency self.__useAdjustedValue = False self.__extra = extra
def getLastPrice(self, instrument): ret = None instrument = build_instrument(instrument) bar = self.getFeed().getLastBar(instrument) if bar is not None: ret = bar.getPrice() return ret
def __init__( self, instrument, dailyBarTime, frequency, timezone=None, sanitize=False, barClass=bar.BasicBar ): self.__instrument = build_instrument(instrument) self.__dailyBarTime = dailyBarTime self.__frequency = frequency self.__timezone = timezone self.__sanitize = sanitize self.__barClass = barClass
def getActiveOrders(self, instrument=None): if instrument is None: ret = list(self._activeOrders.values()) else: instrument = build_instrument(instrument) ret = [ order for order in self._activeOrders.values() if order.getInstrument() == instrument ] return ret
def getLastBar(self, instrument): """ Returns the last :class:`pyalgotrade.bar.Bar` for a given instrument, or None. :param instrument: Instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. """ instrument = build_instrument(instrument) return self.__lastBarByInstrument.get(instrument)
def __init__(self, instrument, maxLen=None): super(BarDataSeries, self).__init__(maxLen) self._instrument = build_instrument(instrument) self._openDS = dataseries.SequenceDataSeries(maxLen) self._closeDS = dataseries.SequenceDataSeries(maxLen) self._highDS = dataseries.SequenceDataSeries(maxLen) self._lowDS = dataseries.SequenceDataSeries(maxLen) self._volumeDS = dataseries.SequenceDataSeries(maxLen) self._adjCloseDS = dataseries.SequenceDataSeries(maxLen) self._extraDS = {} self._useAdjustedValues = False
def createMarketOrder(self, action, instrument, quantity, onClose=False): # In order to properly support market-on-close with intraday feeds I'd need to know about different # exchange/market trading hours and support specifying routing an order to a specific exchange/market. # Even if I had all this in place it would be a problem while paper-trading with a live feed since # I can't tell if the next bar will be the last bar of the market session or not. if onClose is True and self._barFeed.isIntraday(): raise Exception( "Market-on-close not supported with intraday feeds") instrument = build_instrument(instrument) return MarketOrder(action, instrument, quantity, onClose, self.getInstrumentTraits())
def getDataSeries(self, instrument): """ Returns the :class:`pyalgotrade.dataseries.bards.BarDataSeries` for a given instrument or None if it was not found. :param instrument: Instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. :rtype: :class:`pyalgotrade.dataseries.bards.BarDataSeries`. """ instrument = build_instrument(instrument) return super(BaseBarFeed, self).getDataSeries(instrument)
def addBarsFromSequence(self, instrument, bars): if self.__started: raise Exception( "Can't add more bars once you started consuming bars") instrument = build_instrument(instrument) self.__bars.setdefault(instrument, []) self.__nextPos.setdefault(instrument, 0) # Add and sort the bars self.__bars[instrument].extend(bars) self.__bars[instrument].sort(key=lambda b: b.getDateTime()) self.registerDataSeries(instrument)
def __init__(self, instruments, maxLen=None): super(LiveTradeFeed, self).__init__(bar.Frequency.TRADE, maxLen) self.__tradeBars = [] self.__channels = [] for instrument in instruments: instrument = build_instrument(instrument) self.__channels.append(common.instrument_to_channel(instrument)) self.registerDataSeries(instrument) self.__thread = None self.__enableReconnection = True self.__stopped = False self.__orderBookUpdateEvent = observer.Event()
def createLimitOrder(self, action, instrument, limitPrice, quantity): instrument = build_instrument(instrument) if action == broker.Order.Action.BUY_TO_COVER: action = broker.Order.Action.BUY elif action == broker.Order.Action.SELL_SHORT: action = broker.Order.Action.SELL validTrade, reason = self._tradeValidatorPredicate.isValidTrade( action, instrument, limitPrice, quantity) if not validTrade: raise Exception("Invalid trade: %s" % reason) return super(BacktestingBroker, self).createLimitOrder(action, instrument, limitPrice, quantity)
def setShares(self, instrument, quantity, price): """ Set existing shares before the strategy starts executing. :param instrument: Instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. :param quantity: The number of shares for the given instrument. :param price: The price for each share. """ assert not self._started, "Can't setShares once the strategy started executing" instrument = build_instrument(instrument) self._balances[instrument.symbol] = quantity self._instrumentPrice[instrument] = price
def __init__(self, frequency, instruments, bars, maxLen=None): super(OptimizerBarFeed, self).__init__(frequency, maxLen) for instrument in instruments: instrument = build_instrument(instrument) self.registerDataSeries(instrument) self.__bars = bars self.__nextPos = 0 self.__currDateTime = None # Check if bars have adjusted close. self.__barsHaveAdjClose = False for item in bars: for b in item: self.__barsHaveAdjClose = b.getAdjClose() is not None break break
def __init__(self, type_, action, instrument, quantity, instrumentTraits): if quantity is not None and quantity <= 0: raise Exception("Invalid quantity %s" % quantity) self.__id = None self.__type = type_ self.__action = action self.__instrument = build_instrument(instrument) self.__quantity = quantity self.__instrumentTraits = instrumentTraits self.__filled = 0 self.__avgFillPrice = None self.__executionInfo = None self.__goodTillCanceled = False self.__commissions = 0 self.__allOrNone = False self.__state = Order.State.INITIAL self.__submitDateTime = None
def addBarsFromCSV(self, path, instrument="BTC/USD", timezone=None, fromDateTime=None, toDateTime=None): """Loads bars from a trades CSV formatted file. :param path: The path to the file. :type path: string. :param instrument: The instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. :param timezone: An optional timezone to use to localize bars. By default bars are loaded in UTC. :type timezone: A pytz timezone. :param fromDateTime: An optional datetime to use to filter bars to load. If supplied only those bars whose datetime is greater than or equal to fromDateTime are loaded. :type fromDateTime: datetime.datetime. :param toDateTime: An optional datetime to use to filter bars to load. If supplied only those bars whose datetime is lower than or equal to toDateTime are loaded. :type toDateTime: datetime.datetime. .. note:: * Every file that you load bars from must have trades in the same currency. * If fromDateTime or toDateTime are naive, they are treated as UTC. """ if timezone is None: timezone = self.__timezone instrument = build_instrument(instrument) rowParser = RowParser(instrument, self.__unixTimeFix, timezone) # Save the barfilter to restore it later. prevBarFilter = self.getBarFilter() try: if fromDateTime or toDateTime: self.setBarFilter( csvfeed.DateRangeFilter(to_utc_if_naive(fromDateTime), to_utc_if_naive(toDateTime))) super(CSVTradeFeed, self).addBarsFromCSV(path, rowParser) finally: self.setBarFilter(prevBarFilter)
def stopLimitOrder(self, instrument, stopPrice, limitPrice, quantity, goodTillCanceled=False, allOrNone=False): """ Submits a stop limit order. :param instrument: Instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. :param stopPrice: Stop price. :type stopPrice: float. :param limitPrice: Limit price. :type limitPrice: float. :param quantity: The amount of shares. Positive means buy, negative means sell. :type quantity: int/float. :param goodTillCanceled: True if the order is good till canceled. If False then the order gets automatically canceled when the session closes. :type goodTillCanceled: boolean. :param allOrNone: True if the order should be completely filled or not at all. :type allOrNone: boolean. :rtype: The :class:`pyalgotrade.broker.StopLimitOrder` submitted. """ ret = None instrument = build_instrument(instrument) if quantity > 0: ret = self.getBroker().createStopLimitOrder( pyalgotrade.broker.Order.Action.BUY, instrument, stopPrice, limitPrice, quantity) elif quantity < 0: ret = self.getBroker().createStopLimitOrder( pyalgotrade.broker.Order.Action.SELL, instrument, stopPrice, limitPrice, quantity * -1) if ret: ret.setGoodTillCanceled(goodTillCanceled) ret.setAllOrNone(allOrNone) self.getBroker().submitOrder(ret) return ret
def createLimitOrder(self, action, instrument, limitPrice, quantity): instrument = build_instrument(instrument) if instrument not in common.SUPPORTED_INSTRUMENTS: raise Exception("Unsupported instrument %s" % instrument) if action == broker.Order.Action.BUY_TO_COVER: action = broker.Order.Action.BUY elif action == broker.Order.Action.SELL_SHORT: action = broker.Order.Action.SELL if action not in [broker.Order.Action.BUY, broker.Order.Action.SELL]: raise Exception("Only BUY/SELL orders are supported") instrumentTraits = self.getInstrumentTraits() limitPrice = instrumentTraits.round(limitPrice, instrument.priceCurrency) quantity = instrumentTraits.round(quantity, instrument.symbol) return broker.LimitOrder(action, instrument, limitPrice, quantity, instrumentTraits)
def __init__(self, strategy, instrument, stopPrice, limitPrice, quantity, goodTillCanceled, allOrNone): instrument = build_instrument(instrument) if limitPrice is None and stopPrice is None: entryOrder = strategy.getBroker().createMarketOrder( broker.Order.Action.BUY, instrument, quantity, False) elif limitPrice is not None and stopPrice is None: entryOrder = strategy.getBroker().createLimitOrder( broker.Order.Action.BUY, instrument, limitPrice, quantity) elif limitPrice is None and stopPrice is not None: entryOrder = strategy.getBroker().createStopOrder( broker.Order.Action.BUY, instrument, stopPrice, quantity) else: assert limitPrice is not None and stopPrice is not None entryOrder = strategy.getBroker().createStopLimitOrder( broker.Order.Action.BUY, instrument, stopPrice, limitPrice, quantity) super(LongPosition, self).__init__(strategy, entryOrder, goodTillCanceled, allOrNone)
def marketOrder(self, instrument, quantity, onClose=False, goodTillCanceled=False, allOrNone=False): """ Submits a market order. :param instrument: Instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. :param quantity: The amount of shares. Positive means buy, negative means sell. :type quantity: int/float. :param onClose: True if the order should be filled as close to the closing price as possible (Market-On-Close order). Default is False. :type onClose: boolean. :param goodTillCanceled: True if the order is good till canceled. If False then the order gets automatically canceled when the session closes. :type goodTillCanceled: boolean. :param allOrNone: True if the order should be completely filled or not at all. :type allOrNone: boolean. :rtype: The :class:`pyalgotrade.broker.MarketOrder` submitted. """ ret = None instrument = build_instrument(instrument) if quantity > 0: ret = self.getBroker().createMarketOrder( pyalgotrade.broker.Order.Action.BUY, instrument, quantity, onClose) elif quantity < 0: ret = self.getBroker().createMarketOrder( pyalgotrade.broker.Order.Action.SELL, instrument, quantity * -1, onClose) if ret: ret.setGoodTillCanceled(goodTillCanceled) ret.setAllOrNone(allOrNone) self.getBroker().submitOrder(ret) return ret
def addBarsFromCSV(self, instrument, path, timezone=None, skipMalformedBars=False): """Loads bars for a given instrument from a CSV formatted file. The instrument gets registered in the bar feed. :param instrument: Instrument identifier. :type instrument: A :class:`pyalgotrade.instrument.Instrument` or a string formatted like QUOTE_SYMBOL/PRICE_CURRENCY. :param path: The path to the CSV file. :type path: string. :param timezone: The timezone to use to localize bars. Check :mod:`pyalgotrade.marketsession`. :type timezone: A pytz timezone. :param skipMalformedBars: True to skip errors while parsing bars. :type skipMalformedBars: boolean. """ if timezone is None: timezone = self.__timezone instrument = build_instrument(instrument) rowParser = GenericRowParser(instrument, self.__columnNames, self.__dateTimeFormat, self.getDailyBarTime(), self.getFrequency(), timezone, self.__barClass) super(GenericBarFeed, self).addBarsFromCSV(path, rowParser, skipMalformedBars=skipMalformedBars) if rowParser.barsHaveAdjClose(): self.__haveAdjClose = True elif self.__haveAdjClose: raise Exception( "Previous bars had adjusted close and these ones don't have.")
def __init__(self, instrument, columnNames, dateTimeFormat, dailyBarTime, frequency, timezone, barClass=bar.BasicBar): self.__instrument = build_instrument(instrument) self.__dateTimeFormat = dateTimeFormat self.__dailyBarTime = dailyBarTime self.__frequency = frequency self.__timezone = timezone self.__haveAdjClose = False self.__barClass = barClass # Column names. self.__dateTimeColName = columnNames["datetime"] self.__openColName = columnNames["open"] self.__highColName = columnNames["high"] self.__lowColName = columnNames["low"] self.__closeColName = columnNames["close"] self.__volumeColName = columnNames["volume"] self.__adjCloseColName = columnNames["adj_close"] self.__columnNames = columnNames
def createStopLimitOrder(self, action, instrument, stopPrice, limitPrice, quantity): instrument = build_instrument(instrument) return StopLimitOrder(action, instrument, stopPrice, limitPrice, quantity, self.getInstrumentTraits())
# See the License for the specific language governing permissions and # limitations under the License. """ .. moduleauthor:: Gabriel Martin Becedillas Ruiz <*****@*****.**> """ import pyalgotrade.logger from pyalgotrade.instrument import build_instrument logger = pyalgotrade.logger.getLogger("bitstamp") SUPPORTED_INSTRUMENTS = { build_instrument(pair) for pair in [ "BCH/BTC", "BCH/EUR", "BCH/USD", "BTC/EUR", "BTC/USD", "ETH/BTC", "ETH/EUR", "ETH/USD", "EUR/USD", "LTC/BTC", "LTC/EUR", "LTC/USD", "XRP/BTC", "XRP/EUR", "XRP/USD",
def __init__(self, instrument, frequency, dailyBarTime, timezone=None): self.__instrument = build_instrument(instrument) self.__frequency = frequency self.__dailyBarTime = dailyBarTime self.__timezone = timezone
def __init__(self, instrument, instrumentTraits): self.__instrument = build_instrument(instrument) self.__instrumentTraits = instrumentTraits self.reset()