def testCommandLineWeeklyCreatingDir(self): tmpPath = tempfile.mkdtemp() shutil.rmtree(tmpPath) try: instrument = "AAPL" subprocess.call([ "python", "-m", "quantworks.tools.quandl", "--source-code=WIKI", "--table-code=%s" % instrument, "--from-year=2010", "--to-year=2010", "--storage=%s" % tmpPath, "--frequency=weekly", "--auth-token=%s" % QUANDL_API_KEY ]) bf = quandlfeed.Feed() bf.addBarsFromCSV(instrument, os.path.join(tmpPath, "WIKI-AAPL-2010-quandl.csv")) bf.loadAll() self.assertEqual(bf[instrument][-1].getDateTime(), datetime.datetime(2010, 12, 26)) self.assertEqual(bf[instrument][-1].getOpen(), 325.0) self.assertEqual(bf[instrument][-1].getHigh(), 325.15) self.assertEqual(bf[instrument][-1].getLow(), 323.17) self.assertEqual(bf[instrument][-1].getClose(), 323.6) self.assertEqual(bf[instrument][-1].getVolume(), 7969900) self.assertEqual(bf[instrument][-1].getPrice(), 323.6) finally: shutil.rmtree(tmpPath)
def testDownloadAndParseDailyUsingApiKey(self): with common.TmpDir() as tmpPath: instrument = "ORCL" path = os.path.join(tmpPath, "quandl-daily-orcl-2010.csv") quandl.download_daily_bars("WIKI", instrument, 2010, path, authToken=QUANDL_API_KEY) bf = quandlfeed.Feed() bf.addBarsFromCSV(instrument, path) bf.loadAll() self.assertEqual(bf[instrument][-1].getDateTime(), datetime.datetime(2010, 12, 31)) self.assertEqual(bf[instrument][-1].getOpen(), 31.22) self.assertEqual(bf[instrument][-1].getHigh(), 31.33) self.assertEqual(bf[instrument][-1].getLow(), 30.93) self.assertEqual(bf[instrument][-1].getClose(), 31.3) self.assertEqual(bf[instrument][-1].getVolume(), 11716300) self.assertEqual(bf[instrument][-1].getPrice(), 31.3) # Not checking against a specific value since this is going to change # as time passes by. self.assertNotEqual(bf[instrument][-1].getAdjClose(), None)
def testDownloadAndParseDailyNoAdjClose(self): with common.TmpDir() as tmpPath: instrument = "IWG" year = 2017 path = os.path.join(tmpPath, "quandl-daily-%s-%s.csv" % (instrument, year)) quandl.download_daily_bars("LSE", instrument, year, path, authToken=QUANDL_API_KEY) bf = quandlfeed.Feed() bf.setNoAdjClose() bf.setColumnName("open", "Price") bf.setColumnName("close", "Price") bf.addBarsFromCSV(instrument, path, skipMalformedBars=True) bf.loadAll() self.assertEqual(bf[instrument][0].getDateTime(), datetime.datetime(year, 1, 3)) self.assertEqual(bf[instrument][0].getOpen(), 237.80) self.assertEqual(bf[instrument][0].getHigh(), 247.00) self.assertEqual(bf[instrument][0].getLow(), 236.30) self.assertEqual(bf[instrument][0].getClose(), 237.80) self.assertEqual(bf[instrument][0].getVolume(), 3494173) self.assertEqual(bf[instrument][0].getAdjClose(), None) self.assertEqual(bf[instrument][0].getPrice(), 237.80)
def testDownloadAndParseDaily_UseAdjClose(self): with common.TmpDir() as tmpPath: instrument = "ORCL" path = os.path.join(tmpPath, "quandl-daily-orcl-2010.csv") quandl.download_daily_bars("WIKI", instrument, 2010, path, authToken=QUANDL_API_KEY) bf = quandlfeed.Feed() bf.addBarsFromCSV(instrument, path) # Need to setUseAdjustedValues(True) after loading the file because we # can't tell in advance if adjusted values are there or not. bf.setUseAdjustedValues(True) bf.loadAll() self.assertEqual(bf[instrument][-1].getDateTime(), datetime.datetime(2010, 12, 31)) self.assertEqual(bf[instrument][-1].getOpen(), 31.22) self.assertEqual(bf[instrument][-1].getHigh(), 31.33) self.assertEqual(bf[instrument][-1].getLow(), 30.93) self.assertEqual(bf[instrument][-1].getClose(), 31.3) self.assertEqual(bf[instrument][-1].getVolume(), 11716300) self.assertEqual(bf[instrument][-1].getPrice(), bf[instrument][-1].getAdjClose()) # Not checking against a specific value since this is going to change # as time passes by. self.assertNotEqual(bf[instrument][-1].getAdjClose(), None)
def testDownloadAndParseWeekly(self): with common.TmpDir() as tmpPath: instrument = "AAPL" path = os.path.join(tmpPath, "quandl-aapl-weekly-2010.csv") quandl.download_weekly_bars("WIKI", instrument, 2010, path, authToken=QUANDL_API_KEY) bf = quandlfeed.Feed(frequency=bar.Frequency.WEEK) bf.addBarsFromCSV(instrument, path) bf.loadAll() # Quandl used to report 2010-1-3 as the first week of 2010. self.assertTrue( bf[instrument][0].getDateTime() in [datetime.datetime(2010, 1, 3), datetime.datetime(2010, 1, 10)] ) self.assertEqual(bf[instrument][-1].getDateTime(), datetime.datetime(2010, 12, 26)) self.assertEqual(bf[instrument][-1].getOpen(), 325.0) self.assertEqual(bf[instrument][-1].getHigh(), 325.15) self.assertEqual(bf[instrument][-1].getLow(), 323.17) self.assertEqual(bf[instrument][-1].getClose(), 323.6) self.assertEqual(bf[instrument][-1].getVolume(), 7969900) self.assertEqual(bf[instrument][-1].getPrice(), 323.6) # Not checking against a specific value since this is going to change # as time passes by. self.assertNotEqual(bf[instrument][-1].getAdjClose(), None)
from quantworks import plotter from quantworks.barfeed import quandlfeed from quantworks.stratanalyzer import returns import sma_crossover # Load the bar feed from the CSV file feed = quandlfeed.Feed() feed.addBarsFromCSV("orcl", "WIKI-ORCL-2000-quandl.csv") # Evaluate the strategy with the feed's bars. myStrategy = sma_crossover.SMACrossOver(feed, "orcl", 20) # Attach a returns analyzers to the strategy. returnsAnalyzer = returns.Returns() myStrategy.attachAnalyzer(returnsAnalyzer) # Attach the plotter to the strategy. plt = plotter.StrategyPlotter(myStrategy) # Include the SMA in the instrument's subplot to get it displayed along with the closing prices. plt.getInstrumentSubplot("orcl").addDataSeries("SMA", myStrategy.getSMA()) # Plot the simple returns on each bar. plt.getOrCreateSubplot("returns").addDataSeries("Simple returns", returnsAnalyzer.getReturns()) # Run the strategy. myStrategy.run() myStrategy.info("Final portfolio value: $%.2f" % myStrategy.getResult()) # Plot the strategy. plt.plot()
def build_feed(sourceCode, tableCodes, fromYear, toYear, storage, frequency=bar.Frequency.DAY, timezone=None, skipErrors=False, authToken=None, columnNames={}, forceDownload=False, skipMalformedBars=False ): """Build and load a :class:`quantworks.barfeed.quandlfeed.Feed` using CSV files downloaded from Quandl. CSV files are downloaded if they haven't been downloaded before. :param sourceCode: The dataset source code. :type sourceCode: string. :param tableCodes: The dataset table codes. :type tableCodes: list. :param fromYear: The first year. :type fromYear: int. :param toYear: The last year. :type toYear: int. :param storage: The path were the files will be loaded from, or downloaded to. :type storage: string. :param frequency: The frequency of the bars. Only **quantworks.bar.Frequency.DAY** or **quantworks.bar.Frequency.WEEK** are supported. :param timezone: The default timezone to use to localize bars. Check :mod:`quantworks.marketsession`. :type timezone: A pytz timezone. :param skipErrors: True to keep on loading/downloading files in case of errors. :type skipErrors: boolean. :param authToken: Optional. An authentication token needed if you're doing more than 50 calls per day. :type authToken: string. :param columnNames: Optional. A dictionary to map column names. Valid key values are: * datetime * open * high * low * close * volume * adj_close :type columnNames: dict. :param skipMalformedBars: True to skip errors while parsing bars. :type skipMalformedBars: boolean. :rtype: :class:`quantworks.barfeed.quandlfeed.Feed`. """ logger = quantworks.logger.getLogger("quandl") ret = quandlfeed.Feed(frequency, timezone) # Additional column names. for col, name in six.iteritems(columnNames): ret.setColumnName(col, name) if not os.path.exists(storage): logger.info("Creating %s directory" % (storage)) os.mkdir(storage) for year in range(fromYear, toYear+1): for tableCode in tableCodes: fileName = os.path.join(storage, "%s-%s-%d-quandl.csv" % (sourceCode, tableCode, year)) if not os.path.exists(fileName) or forceDownload: logger.info("Downloading %s %d to %s" % (tableCode, year, fileName)) try: if frequency == bar.Frequency.DAY: download_daily_bars(sourceCode, tableCode, year, fileName, authToken) else: assert frequency == bar.Frequency.WEEK, "Invalid frequency" download_weekly_bars(sourceCode, tableCode, year, fileName, authToken) except Exception as e: if skipErrors: logger.error(str(e)) continue else: raise e ret.addBarsFromCSV(tableCode, fileName, skipMalformedBars=skipMalformedBars) return ret
def testInvalidFrequency(self): with self.assertRaisesRegex(Exception, "Invalid frequency.*"): quandlfeed.Feed(frequency=bar.Frequency.MINUTE)