### Server Console Output Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md Example log output from the optimizer server. ```text 2017-07-21 22:56:51,944 pyalgotrade.optimizer.server [INFO] Starting server 2017-07-21 22:56:51,944 pyalgotrade.optimizer.xmlrpcserver [INFO] Loading bars 2017-07-21 22:56:52,609 pyalgotrade.optimizer.xmlrpcserver [INFO] Started serving 2017-07-21 22:58:50,073 pyalgotrade.optimizer.xmlrpcserver [INFO] Best result so far 1261295.07089 with parameters ('ibm', 150, 5, 2, 83, 24) . . ``` -------------------------------- ### Install PyAlgoTrade via pip Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/intro.md Use this command to install the library and its dependencies in your Python environment. ```bash pip install pyalgotrade ``` -------------------------------- ### Local Optimizer Console Output Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md Example log output from the local optimizer. ```text 2017-07-21 22:59:26,921 pyalgotrade.optimizer.local [INFO] Starting server 2017-07-21 22:59:26,922 pyalgotrade.optimizer.xmlrpcserver [INFO] Loading bars 2017-07-21 22:59:26,922 pyalgotrade.optimizer.local [INFO] Starting workers 2017-07-21 22:59:27,642 pyalgotrade.optimizer.xmlrpcserver [INFO] Started serving 2017-07-21 23:01:14,306 pyalgotrade.optimizer.xmlrpcserver [INFO] Best result so far 1261295.07089 with parameters ('ibm', 150, 5, 2, 83, 24) . . ``` -------------------------------- ### Example output logs Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/twitter_example.md Sample console output showing the strategy processing both Twitter events and market price updates. ```default 2014-03-15 02:42:07,696 bitstamp [INFO] Initializing client. 2014-03-15 02:42:08,174 bitstamp [INFO] Connection established. 2014-03-15 02:42:08,175 bitstamp [INFO] Initialization ok. 2014-03-15 02:42:08,175 twitter [INFO] Initializing client. 2014-03-15 02:42:09,238 twitter [INFO] Connected. 2014-03-15 02:42:15,107 strategy [INFO] Twitter: Warren Buffett Urges Investors to ‘Stay Away’ from Bitcoin http://t.co/WWRCr3rfob 2014-03-15 02:42:22,926 strategy [INFO] Twitter: FundingUnion Inc. Bitcoin MLM Social Build - The Currently in BETA version - Join Today : http://t.co/bxcfoBV0I4 #Bitcoin #MLM #SocialMedia 2014-03-15 02:42:23,577 strategy [INFO] Twitter: #News Alleged Bitcoin creator denies he's the one http://t.co/gmilO85smQ #DailyNews 2014-03-15 02:42:29,378 strategy [INFO] Twitter: RT @Tom_Cruis3: #News Alleged Bitcoin creator denies he's the one http://t.co/gmilO85smQ #DailyNews 2014-03-15 02:42:38,012 strategy [INFO] Twitter: Need for speed dulu at BTC XXI 2014-03-15 02:42:40,162 strategy [INFO] Price: 632.97. Volume: 0.51896614. 2014-03-15 02:42:45,867 strategy [INFO] Twitter: Analysis of the leaked MTGOX database http://t.co/6ty8EupGh9 via @Reddit 2014-03-15 02:42:46,761 strategy [INFO] Twitter: [ANN] After MtGox implosion, this is the first exchange to implement transparent cold storage http://t.co/EyafH5jXsM #reddit #bitcoin 2014-03-15 02:42:46,825 strategy [INFO] Twitter: @abatalion @naval @cdixon you guys remember CentMail? http://t.co/iihgCS4OwJ would be interesting with a BTC twist. 2014-03-15 02:42:47,285 strategy [INFO] Twitter: Help me convince my Dad to mine Bitcoins! http://t.co/fxboBooINu #reddit #bitcoin 2014-03-15 02:42:47,492 strategy [INFO] Twitter: RT @VentureBeat: Warren Buffett: Bitcoin is a 'mirage' http://t.co/B1FcvZKJQS by @xBarryLevine ``` -------------------------------- ### Example Final Portfolio Value Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md Displays the final portfolio value after running a strategy. This is a sample output and not executable code. ```text Final portfolio value: $1071.03 ``` -------------------------------- ### CSV Data Format Example Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/feed.md Example of the expected CSV file structure for loading data into a feed. ```default Date,USD,GBP,EUR 2013-09-29,1333.0,831.203,986.75 2013-09-22,1349.25,842.755,997.671 2013-09-15,1318.5,831.546,993.969 2013-09-08,1387.0,886.885,1052.911 . . . ``` -------------------------------- ### Strategy execution output logs Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md Example log output showing closing prices over time. ```text 2000-01-03 00:00:00 strategy [INFO] 118.1 2000-01-04 00:00:00 strategy [INFO] 107.7 2000-01-05 00:00:00 strategy [INFO] 103.5 . . . 2000-12-27 00:00:00 strategy [INFO] 30.69 2000-12-28 00:00:00 strategy [INFO] 31.06 2000-12-29 00:00:00 strategy [INFO] 29.06 ``` -------------------------------- ### Worker Console Output Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md Example log output from an optimizer worker. ```text 2017-07-21 22:56:57,884 localworker [INFO] Started running 2017-07-21 22:56:57,884 localworker [INFO] Started running 2017-07-21 22:56:58,439 localworker [INFO] Running strategy with parameters ('ibm', 150, 5, 2, 84, 15) 2017-07-21 22:56:58,498 localworker [INFO] Running strategy with parameters ('ibm', 150, 5, 2, 94, 5) 2017-07-21 22:56:58,918 localworker [INFO] Result 1137855.88871 2017-07-21 22:56:58,918 localworker [INFO] Running strategy with parameters ('ibm', 150, 5, 2, 84, 14) 2017-07-21 22:56:58,996 localworker [INFO] Result 1027761.85581 2017-07-21 22:56:58,997 localworker [INFO] Running strategy with parameters ('ibm', 150, 5, 2, 93, 25) 2017-07-21 22:56:59,427 localworker [INFO] Result 1092194.67448 2017-07-21 23:01:14,306 pyalgotrade.optimizer.xmlrpcserver [INFO] Result 1260766.64479 . . ``` -------------------------------- ### Implement Twitter-integrated strategy Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/twitter_example.md A complete example showing how to subscribe to Twitter events and process them alongside live market data. Requires valid Twitter API credentials and a live feed source like Bitstamp. ```python from pyalgotrade import strategy from pyalgotrade.bitstamp import barfeed from pyalgotrade.bitstamp import broker from pyalgotrade.twitter import feed as twitterfeed class Strategy(strategy.BaseStrategy): def __init__(self, feed, brk, twitterFeed): super(Strategy, self).__init__(feed, brk) self.__instrument = "BTC" # Subscribe to Twitter events. twitterFeed.subscribe(self.__onTweet) def __onTweet(self, data): # Refer to https://dev.twitter.com/docs/streaming-apis/messages#Public_stream_messages for # the information available in data. try: self.info("Twitter: %s" % (data["text"])) except KeyError: pass def onBars(self, bars): bar = bars[self.__instrument] self.info("Price: %s. Volume: %s." % (bar.getClose(), bar.getVolume())) def main(): # Go to http://dev.twitter.com and create an app. # The consumer key and secret will be generated for you after that. consumer_key = "" consumer_secret = "" # After the step above, you will be redirected to your app's page. # Create an access token under the the "Your access token" section access_token = "" access_token_secret = "" # Create a twitter feed to track BitCoin related events. track = ["bitcoin", "btc", "mtgox", "bitstamp", "xapo"] follow = [] languages = ["en"] twitterFeed = twitterfeed.TwitterFeed(consumer_key, consumer_secret, access_token, access_token_secret, track, follow, languages) barFeed = barfeed.LiveTradeFeed() brk = broker.PaperTradingBroker(1000, barFeed) strat = Strategy(barFeed, brk, twitterFeed) # It is VERY important to add twitterFeed to the event dispatch loop before running the strategy. strat.getDispatcher().addSubject(twitterFeed) strat.run() if __name__ == "__main__": main() ``` -------------------------------- ### Example Output for Event Profiler Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/eventprofiler.md Shows the console output generated after running the event profiler analysis. ```text 2017-07-22 00:26:06,574 quandl [INFO] Downloading IBM 2008 to ./WIKI-IBM-2008-quandl.csv 2017-07-22 00:26:08,299 quandl [INFO] Downloading AES 2008 to ./WIKI-AES-2008-quandl.csv 2017-07-22 00:26:09,849 quandl [INFO] Downloading AIG 2008 to ./WIKI-AIG-2008-quandl.csv 2017-07-22 00:26:11,513 quandl [INFO] Downloading IBM 2009 to ./WIKI-IBM-2009-quandl.csv 2017-07-22 00:26:13,128 quandl [INFO] Downloading AES 2009 to ./WIKI-AES-2009-quandl.csv 2017-07-22 00:26:14,626 quandl [INFO] Downloading AIG 2009 to ./WIKI-AIG-2009-quandl.csv 15 events found ``` -------------------------------- ### CSV Feed Output Example Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/feed.md Expected output format when iterating over a loaded CSV feed. ```default 1968-04-07 00:00:00 {'USD': 37.0, 'GBP': 15.3875, 'EUR': ''} 1968-04-14 00:00:00 {'USD': 38.0, 'GBP': 15.8208, 'EUR': ''} 1968-04-21 00:00:00 {'USD': 37.65, 'GBP': 15.6833, 'EUR': ''} 1968-04-28 00:00:00 {'USD': 38.65, 'GBP': 16.1271, 'EUR': ''} 1968-05-05 00:00:00 {'USD': 39.1, 'GBP': 16.3188, 'EUR': ''} 1968-05-12 00:00:00 {'USD': 39.6, 'GBP': 16.5625, 'EUR': ''} 1968-05-19 00:00:00 {'USD': 41.5, 'GBP': 17.3958, 'EUR': ''} 1968-05-26 00:00:00 {'USD': 41.75, 'GBP': 17.5104, 'EUR': ''} 1968-06-02 00:00:00 {'USD': 41.95, 'GBP': 17.6, 'EUR': ''} 1968-06-09 00:00:00 {'USD': 41.25, 'GBP': 17.3042, 'EUR': ''} . . . 2013-07-28 00:00:00 {'USD': 1331.0, 'GBP': 864.23, 'EUR': 1001.505} 2013-08-04 00:00:00 {'USD': 1309.25, 'GBP': 858.637, 'EUR': 986.921} 2013-08-11 00:00:00 {'USD': 1309.0, 'GBP': 843.156, 'EUR': 979.79} 2013-08-18 00:00:00 {'USD': 1369.25, 'GBP': 875.424, 'EUR': 1024.964} 2013-08-25 00:00:00 {'USD': 1377.5, 'GBP': 885.738, 'EUR': 1030.6} 2013-09-01 00:00:00 {'USD': 1394.75, 'GBP': 901.292, 'EUR': 1055.749} 2013-09-08 00:00:00 {'USD': 1387.0, 'GBP': 886.885, 'EUR': 1052.911} 2013-09-15 00:00:00 {'USD': 1318.5, 'GBP': 831.546, 'EUR': 993.969} 2013-09-22 00:00:00 {'USD': 1349.25, 'GBP': 842.755, 'EUR': 997.671} 2013-09-29 00:00:00 {'USD': 1333.0, 'GBP': 831.203, 'EUR': 986.75} ``` -------------------------------- ### Strategy Execution Log Output Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md Example log output showing indicator values, where initial periods result in None values due to insufficient data for calculation. ```text 2000-01-03 00:00:00 strategy [INFO] 118.1 None None 2000-01-04 00:00:00 strategy [INFO] 107.7 None None 2000-01-05 00:00:00 strategy [INFO] 103.5 None None 2000-01-06 00:00:00 strategy [INFO] 96.0 None None 2000-01-07 00:00:00 strategy [INFO] 103.4 None None 2000-01-10 00:00:00 strategy [INFO] 115.8 None None 2000-01-11 00:00:00 strategy [INFO] 112.4 None None 2000-01-12 00:00:00 strategy [INFO] 105.6 None None 2000-01-13 00:00:00 strategy [INFO] 105.1 None None 2000-01-14 00:00:00 strategy [INFO] 106.8 None None 2000-01-18 00:00:00 strategy [INFO] 111.3 None None 2000-01-19 00:00:00 strategy [INFO] 57.13 None None 2000-01-20 00:00:00 strategy [INFO] 59.25 None None 2000-01-21 00:00:00 strategy [INFO] 59.69 None None 2000-01-24 00:00:00 strategy [INFO] 54.19 23.6 None 2000-01-25 00:00:00 strategy [INFO] 56.44 25.1 None 2000-01-26 00:00:00 strategy [INFO] 55.06 24.78 None 2000-01-27 00:00:00 strategy [INFO] 51.81 24.0 None 2000-01-28 00:00:00 strategy [INFO] 47.38 22.94 None 2000-01-31 00:00:00 strategy [INFO] 49.95 25.01 None 2000-02-01 00:00:00 strategy [INFO] 54.0 28.27 None 2000-02-02 00:00:00 strategy [INFO] 54.31 28.53 None 2000-02-03 00:00:00 strategy [INFO] 56.69 30.58 None 2000-02-04 00:00:00 strategy [INFO] 57.81 31.58 None 2000-02-07 00:00:00 strategy [INFO] 59.94 33.53 None 2000-02-08 00:00:00 strategy [INFO] 59.56 33.35 None 2000-02-09 00:00:00 strategy [INFO] 59.94 33.73 None 2000-02-10 00:00:00 strategy [INFO] 62.31 36.23 None 2000-02-11 00:00:00 strategy [INFO] 59.69 34.68 29.06 2000-02-14 00:00:00 strategy [INFO] 62.19 37.44 29.98 . . . 2000-12-27 00:00:00 strategy [INFO] 30.69 51.31 49.85 2000-12-28 00:00:00 strategy [INFO] 31.06 52.16 50.0 2000-12-29 00:00:00 strategy [INFO] 29.06 47.37 50.08 ``` -------------------------------- ### Download Stock Data with PyAlgoTrade Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/compinvpart1.md Use these commands to download daily historical stock data for specific tickers from Quandl for the year 2011. Ensure you have PyAlgoTrade installed. ```bash python -m "pyalgotrade.tools.quandl" --source-code="WIKI" --table-code="IBM" --from-year=2011 --to-year=2011 --storage=. --force-download --frequency=daily ``` ```bash python -m "pyalgotrade.tools.quandl" --source-code="WIKI" --table-code="AES" --from-year=2011 --to-year=2011 --storage=. --force-download --frequency=daily ``` ```bash python -m "pyalgotrade.tools.quandl" --source-code="WIKI" --table-code="AIG" --from-year=2011 --to-year=2011 --storage=. --force-download --frequency=daily ``` ```bash python -m "pyalgotrade.tools.quandl" --source-code="WIKI" --table-code="ORCL" --from-year=2011 --to-year=2011 --storage=. --force-download --frequency=daily ``` -------------------------------- ### Example Trading Strategy Output Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md This output shows the sequence of buy and sell orders executed by the trading strategy, along with the final portfolio value. It is generated after running the Python script with specific parameters. ```text 2000-01-26 00:00:00 strategy [INFO] BUY at $25.84 2000-01-28 00:00:00 strategy [INFO] SELL at $23.45 2000-02-03 00:00:00 strategy [INFO] BUY at $25.22 2000-02-22 00:00:00 strategy [INFO] SELL at $26.92 2000-02-23 00:00:00 strategy [INFO] BUY at $27.41 2000-03-31 00:00:00 strategy [INFO] SELL at $36.51 2000-04-07 00:00:00 strategy [INFO] BUY at $38.11 2000-04-12 00:00:00 strategy [INFO] SELL at $35.49 2000-04-19 00:00:00 strategy [INFO] BUY at $35.80 2000-04-20 00:00:00 strategy [INFO] SELL at $33.61 2000-04-28 00:00:00 strategy [INFO] BUY at $35.74 2000-05-05 00:00:00 strategy [INFO] SELL at $33.70 2000-05-08 00:00:00 strategy [INFO] BUY at $34.29 2000-05-09 00:00:00 strategy [INFO] SELL at $33.55 2000-05-16 00:00:00 strategy [INFO] BUY at $35.35 2000-05-19 00:00:00 strategy [INFO] SELL at $32.78 2000-05-31 00:00:00 strategy [INFO] BUY at $33.35 2000-06-23 00:00:00 strategy [INFO] SELL at $36.80 2000-06-27 00:00:00 strategy [INFO] BUY at $37.51 2000-06-28 00:00:00 strategy [INFO] SELL at $37.37 2000-06-29 00:00:00 strategy [INFO] BUY at $37.37 2000-06-30 00:00:00 strategy [INFO] SELL at $36.60 2000-07-03 00:00:00 strategy [INFO] BUY at $36.94 2000-07-05 00:00:00 strategy [INFO] SELL at $34.97 2000-07-21 00:00:00 strategy [INFO] BUY at $35.26 2000-07-24 00:00:00 strategy [INFO] SELL at $35.12 2000-07-26 00:00:00 strategy [INFO] BUY at $34.06 2000-07-28 00:00:00 strategy [INFO] SELL at $34.21 2000-08-01 00:00:00 strategy [INFO] BUY at $34.24 2000-08-02 00:00:00 strategy [INFO] SELL at $33.24 2000-08-04 00:00:00 strategy [INFO] BUY at $35.66 2000-09-11 00:00:00 strategy [INFO] SELL at $39.19 2000-09-29 00:00:00 strategy [INFO] BUY at $37.05 2000-10-02 00:00:00 strategy [INFO] SELL at $36.31 2000-10-20 00:00:00 strategy [INFO] BUY at $32.90 2000-10-31 00:00:00 strategy [INFO] SELL at $29.72 2000-11-20 00:00:00 strategy [INFO] BUY at $22.14 2000-11-21 00:00:00 strategy [INFO] SELL at $22.59 2000-12-01 00:00:00 strategy [INFO] BUY at $24.02 2000-12-15 00:00:00 strategy [INFO] SELL at $26.81 2000-12-18 00:00:00 strategy [INFO] BUY at $27.32 2000-12-21 00:00:00 strategy [INFO] SELL at $25.33 2000-12-22 00:00:00 strategy [INFO] BUY at $27.67 Final portfolio value: $974.87 ``` -------------------------------- ### Custom Technical Indicator: Accumulator Source: https://context7.com/gbeced/pyalgotrade/llms.txt Demonstrates creating a custom technical indicator by subclassing EventWindow and using EventBasedFilter. This example creates an accumulator that sums values over a specified window size. It requires sequence data series and shows how to append values and access results. ```python from pyalgotrade import dataseries from pyalgotrade import technical # Custom accumulator indicator class AccumulatorWindow(technical.EventWindow): def getValue(self): ret = None if self.windowFull(): ret = self.getValues().sum() return ret # Build indicator from sequence data series seqDS = dataseries.SequenceDataSeries() accumulator = technical.EventBasedFilter(seqDS, AccumulatorWindow(3)) # Add values for i in range(50): seqDS.append(i) # Access results print(accumulator[0]) # None - not enough values print(accumulator[1]) # None - not enough values print(accumulator[2]) # 3.0 (0 + 1 + 2) print(accumulator[3]) # 6.0 (1 + 2 + 3) print(accumulator[-1]) # 144.0 (47 + 48 + 49) ``` -------------------------------- ### Run a basic backtesting strategy Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md Executes a strategy instance using a pre-loaded feed. ```python myStrategy = MyStrategy(feed, "orcl") myStrategy.run() ``` -------------------------------- ### Download and Build Feed Programmatically Source: https://context7.com/gbeced/pyalgotrade/llms.txt Builds a market data feed by programmatically downloading data from Quandl for specified instruments and date ranges, then saving it to a local directory. This is an alternative to using the command-line tool. ```python from pyalgotrade.tools import quandl # Method 2: Download and build feed programmatically feed = quandl.build_feed("WIKI", ["AAPL", "GOOG"], 2011, 2012, "./data") ``` -------------------------------- ### Resampled CSV Data Format Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/bitcoincharts_example.md Example of the expected output format for resampled bar data. ```text Date Time,Open,High,Low,Close,Volume,Adj Close 2014-01-01 00:00:00,732.0,738.25,729.01,734.81,266.17955488, 2014-01-01 00:30:00,734.81,739.9,734.47,739.02,308.96802502, 2014-01-01 01:00:00,739.02,739.97,737.65,738.11,65.66924473, 2014-01-01 01:30:00,738.0,742.0,737.65,741.89,710.27165024, 2014-01-01 02:00:00,741.89,757.99,741.89,752.23,1085.13335011, 2014-01-01 02:30:00,752.23,755.0,747.0,747.2,272.03949342, 2014-01-01 04:00:00,744.98,748.02,744.98,747.19,104.65989075, . . ``` -------------------------------- ### Execute Strategy with Analyzers Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/stratanalyzer.md Configures the data feed, initializes the strategy, and attaches multiple performance analyzers before execution. ```python from __future__ import print_function from pyalgotrade.barfeed import yahoofeed from pyalgotrade.stratanalyzer import returns from pyalgotrade.stratanalyzer import sharpe from pyalgotrade.stratanalyzer import drawdown from pyalgotrade.stratanalyzer import trades from . import sma_crossover # Load the bars. This file was manually downloaded from Yahoo Finance. feed = yahoofeed.Feed() feed.addBarsFromCSV("orcl", "orcl-2000-yahoofinance.csv") # Evaluate the strategy with the feed's bars. myStrategy = sma_crossover.SMACrossOver(feed, "orcl", 20) # Attach different analyzers to a strategy before executing it. retAnalyzer = returns.Returns() myStrategy.attachAnalyzer(retAnalyzer) sharpeRatioAnalyzer = sharpe.SharpeRatio() myStrategy.attachAnalyzer(sharpeRatioAnalyzer) drawDownAnalyzer = drawdown.DrawDown() myStrategy.attachAnalyzer(drawDownAnalyzer) tradesAnalyzer = trades.Trades() myStrategy.attachAnalyzer(tradesAnalyzer) ``` -------------------------------- ### Download Market Data using Quandl CLI Source: https://context7.com/gbeced/pyalgotrade/llms.txt Demonstrates how to download historical market data for a specific instrument using the pyalgotrade command-line tool for Quandl. This command-line approach is useful for pre-downloading data before running backtests. ```python # Download data using command line: # python -m "pyalgotrade.tools.quandl" --source-code="WIKI" --table-code="ORCL" \ # --from-year=2000 --to-year=2000 --storage=. --force-download --frequency=daily ``` -------------------------------- ### Run VWAP Momentum Strategy with Plotting Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/bitcoincharts_example.md This snippet demonstrates how to set up and run the VWAPMomentum strategy. It includes configuring the bar feed, backtesting broker, and optionally enabling plotting for visualization. ```python sellThreshold = 0.01 barFeed = csvfeed.GenericBarFeed(bar.Frequency.MINUTE*30) barFeed.addBarsFromCSV(instrument, "30min-bitstampUSD.csv") brk = broker.BacktestingBroker(initialCash, barFeed) strat = VWAPMomentum(barFeed, brk, instrument, vwapWindowSize, buyThreshold, sellThreshold) if plot: plt = plotter.StrategyPlotter(strat) plt.getInstrumentSubplot(instrument).addDataSeries("VWAP", strat.getVWAP()) strat.run() if plot: plt.plot() if __name__ == "__main__": main(True) ``` -------------------------------- ### Basic PyAlgoTrade Strategy Implementation Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/tutorial.md Implement a simple backtesting strategy in PyAlgoTrade that logs the closing price of a given instrument on each bar. Requires importing strategy and feed modules. ```python from pyalgotrade import strategy from pyalgotrade.barfeed import quandlfeed class MyStrategy(strategy.BacktestingStrategy): def __init__(self, feed, instrument): super(MyStrategy, self).__init__(feed) self.__instrument = instrument def onBars(self, bars): bar = bars[self.__instrument] self.info(bar.getClose()) # Load the bar feed from the CSV file feed = quandlfeed.Feed() feed.addBarsFromCSV("orcl", "WIKI-ORCL-2000-quandl.csv") ``` -------------------------------- ### Custom Technical Indicator: Range Source: https://context7.com/gbeced/pyalgotrade/llms.txt Shows how to create a custom technical indicator within a strategy to calculate the range (high - low) of prices over a window. This example uses a custom RangeWindow class and applies it to a data series within a BacktestingStrategy. ```python from pyalgotrade import strategy from pyalgotrade.barfeed import quandlfeed class CustomIndicatorStrategy(strategy.BacktestingStrategy): def __init__(self, feed, instrument): super(CustomIndicatorStrategy, self).__init__(feed) self.__instrument = instrument # Create custom volatility indicator (high - low range) class RangeWindow(technical.EventWindow): def getValue(self): if self.windowFull(): return max(self.getValues()) - min(self.getValues()) return None self.__range = technical.EventBasedFilter( feed[instrument].getCloseDataSeries(), RangeWindow(5) ) def onBars(self, bars): rangeValue = self.__range[-1] if rangeValue is not None: self.info("5-bar range: %.2f" % rangeValue) ``` -------------------------------- ### Loading CSV Data with PyAlgoTrade Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/feed.md Demonstrates initializing a csvfeed.Feed and loading data from a file. ```default from __future__ import print_function from pyalgotrade.feed import csvfeed feed = csvfeed.Feed("Date", "%Y-%m-%d") feed.addValuesFromCSV("quandl_gold_2.csv") for dateTime, value in feed: print(dateTime, value) ``` -------------------------------- ### Live SMA Crossover Strategy with Bitstamp Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/bitstamp_example.md Implements a live SMA crossover strategy using Bitstamp's realtime feeds. It subscribes to order book updates to get current bid and ask prices for trading. This strategy uses `BaseStrategy` for live trading, not backtesting. ```python from pyalgotrade.bitstamp import barfeed from pyalgotrade.bitstamp import broker from pyalgotrade import strategy from pyalgotrade.technical import ma from pyalgotrade.technical import cross class Strategy(strategy.BaseStrategy): def __init__(self, feed, brk): super(Strategy, self).__init__(feed, brk) smaPeriod = 20 self.__instrument = "BTC" self.__prices = feed[self.__instrument].getCloseDataSeries() self.__sma = ma.SMA(self.__prices, smaPeriod) self.__bid = None self.__ask = None self.__position = None self.__posSize = 0.05 # Subscribe to order book update events to get bid/ask prices to trade. feed.getOrderBookUpdateEvent().subscribe(self.__onOrderBookUpdate) def __onOrderBookUpdate(self, orderBookUpdate): bid = orderBookUpdate.getBidPrices()[0] ask = orderBookUpdate.getAskPrices()[0] if bid != self.__bid or ask != self.__ask: self.__bid = bid self.__ask = ask self.info("Order book updated. Best bid: %s. Best ask: %s" % (self.__bid, self.__ask)) def onEnterOk(self, position): self.info("Position opened at %s" % (position.getEntryOrder().getExecutionInfo().getPrice())) def onEnterCanceled(self, position): self.info("Position entry canceled") self.__position = None def onExitOk(self, position): self.__position = None self.info("Position closed at %s" % (position.getExitOrder().getExecutionInfo().getPrice())) def onExitCanceled(self, position): # If the exit was canceled, re-submit it. self.__position.exitLimit(self.__bid) def onBars(self, bars): bar = bars[self.__instrument] self.info("Price: %s. Volume: %s." % (bar.getClose(), bar.getVolume())) # Wait until we get the current bid/ask prices. if self.__ask is None: return # If a position was not opened, check if we should enter a long position. if self.__position is None: if cross.cross_above(self.__prices, self.__sma) > 0: self.info("Entry signal. Buy at %s" % (self.__ask)) self.__position = self.enterLongLimit(self.__instrument, self.__ask, self.__posSize, True) # Check if we have to close the position. elif not self.__position.exitActive() and cross.cross_below(self.__prices, self.__sma) > 0: self.info("Exit signal. Sell at %s" % (self.__bid)) self.__position.exitLimit(self.__bid) def main(): barFeed = barfeed.LiveTradeFeed() brk = broker.PaperTradingBroker(1000, barFeed) strat = Strategy(barFeed, brk) strat.run() if __name__ == "__main__": main() ``` -------------------------------- ### Build and Run Market Timing Strategy Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/sample_market_timing.md Builds the MarketTiming strategy, attaches performance analyzers (Sharpe Ratio, Returns), and optionally sets up a plotter for visualizing strategy performance. The strategy is then executed using the loaded data feed. ```python # Build the strategy and attach some metrics. strat = MarketTiming(feed, instrumentsByClass, initialCash) sharpeRatioAnalyzer = sharpe.SharpeRatio() strat.attachAnalyzer(sharpeRatioAnalyzer) returnsAnalyzer = returns.Returns() strat.attachAnalyzer(returnsAnalyzer) if plot: plt = plotter.StrategyPlotter(strat, False, False, True) plt.getOrCreateSubplot("cash").addCallback("Cash", lambda x: strat.getBroker().getCash()) # Plot strategy vs. SPY cumulative returns. plt.getOrCreateSubplot("returns").addDataSeries("SPY", cumret.CumulativeReturn(feed["SPY"].getPriceDataSeries())) plt.getOrCreateSubplot("returns").addDataSeries("Strategy", returnsAnalyzer.getCumulativeReturns()) strat.run() print("Sharpe ratio: %.2f" % sharpeRatioAnalyzer.getSharpeRatio(0.05)) print("Returns: %.2f %%" % (returnsAnalyzer.getCumulativeReturns()[-1] * 100)) if plot: plt.plot() if __name__ == "__main__": main(True) ``` -------------------------------- ### Implement Statistical Arbitrage Strategy Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/sample_statarb_erniechan.md Uses statsmodels for OLS regression to calculate hedge ratios and PyAlgoTrade for backtesting the spread between two instruments. ```python from __future__ import print_function from pyalgotrade import strategy from pyalgotrade import dataseries from pyalgotrade.dataseries import aligned from pyalgotrade import plotter from pyalgotrade.barfeed import yahoofeed from pyalgotrade.stratanalyzer import sharpe import numpy as np import statsmodels.api as sm def get_beta(values1, values2): # http://statsmodels.sourceforge.net/stable/regression.html model = sm.OLS(values1, values2) results = model.fit() return results.params[0] class StatArbHelper: def __init__(self, ds1, ds2, windowSize): # We're going to use datetime aligned versions of the dataseries. self.__ds1, self.__ds2 = aligned.datetime_aligned(ds1, ds2) self.__windowSize = windowSize self.__hedgeRatio = None self.__spread = None self.__spreadMean = None self.__spreadStd = None self.__zScore = None def getSpread(self): return self.__spread def getSpreadMean(self): return self.__spreadMean def getSpreadStd(self): return self.__spreadStd def getZScore(self): return self.__zScore def getHedgeRatio(self): return self.__hedgeRatio def __updateHedgeRatio(self, values1, values2): self.__hedgeRatio = get_beta(values1, values2) def __updateSpreadMeanAndStd(self, values1, values2): if self.__hedgeRatio is not None: spread = values1 - values2 * self.__hedgeRatio self.__spreadMean = spread.mean() self.__spreadStd = spread.std(ddof=1) def __updateSpread(self): if self.__hedgeRatio is not None: self.__spread = self.__ds1[-1] - self.__hedgeRatio * self.__ds2[-1] def __updateZScore(self): if self.__spread is not None and self.__spreadMean is not None and self.__spreadStd is not None: self.__zScore = (self.__spread - self.__spreadMean) / float(self.__spreadStd) def update(self): if len(self.__ds1) >= self.__windowSize: values1 = np.asarray(self.__ds1[-1*self.__windowSize:]) values2 = np.asarray(self.__ds2[-1*self.__windowSize:]) self.__updateHedgeRatio(values1, values2) self.__updateSpread() self.__updateSpreadMeanAndStd(values1, values2) self.__updateZScore() class StatArb(strategy.BacktestingStrategy): def __init__(self, feed, instrument1, instrument2, windowSize): super(StatArb, self).__init__(feed) self.setUseAdjustedValues(True) self.__statArbHelper = StatArbHelper(feed[instrument1].getAdjCloseDataSeries(), feed[instrument2].getAdjCloseDataSeries(), windowSize) self.__i1 = instrument1 self.__i2 = instrument2 # These are used only for plotting purposes. self.__spread = dataseries.SequenceDataSeries() self.__hedgeRatio = dataseries.SequenceDataSeries() def getSpreadDS(self): return self.__spread def getHedgeRatioDS(self): return self.__hedgeRatio def __getOrderSize(self, bars, hedgeRatio): cash = self.getBroker().getCash(False) price1 = bars[self.__i1].getAdjClose() price2 = bars[self.__i2].getAdjClose() size1 = int(cash / (price1 + hedgeRatio * price2)) size2 = int(size1 * hedgeRatio) return (size1, size2) def buySpread(self, bars, hedgeRatio): amount1, amount2 = self.__getOrderSize(bars, hedgeRatio) self.marketOrder(self.__i1, amount1) self.marketOrder(self.__i2, amount2 * -1) def sellSpread(self, bars, hedgeRatio): amount1, amount2 = self.__getOrderSize(bars, hedgeRatio) self.marketOrder(self.__i1, amount1 * -1) self.marketOrder(self.__i2, amount2) def reducePosition(self, instrument): currentPos = self.getBroker().getShares(instrument) if currentPos > 0: self.marketOrder(instrument, currentPos * -1) elif currentPos < 0: self.marketOrder(instrument, currentPos * -1) def onBars(self, bars): self.__statArbHelper.update() # These is used only for plotting purposes. self.__spread.appendWithDateTime(bars.getDateTime(), self.__statArbHelper.getSpread()) self.__hedgeRatio.appendWithDateTime(bars.getDateTime(), self.__statArbHelper.getHedgeRatio()) if bars.getBar(self.__i1) and bars.getBar(self.__i2): hedgeRatio = self.__statArbHelper.getHedgeRatio() zScore = self.__statArbHelper.getZScore() if zScore is not None: ``` -------------------------------- ### Build a custom filter with EventWindow and EventBasedFilter Source: https://github.com/gbeced/pyalgotrade/blob/master/doc/technical.md Demonstrates creating a custom accumulator filter that sums a window of values from a SequenceDataSeries. ```python from __future__ import print_function from pyalgotrade import dataseries from pyalgotrade import technical # An EventWindow is responsible for making calculations using a window of values. class Accumulator(technical.EventWindow): def getValue(self): ret = None if self.windowFull(): ret = self.getValues().sum() return ret # Build a sequence based DataSeries. seqDS = dataseries.SequenceDataSeries() # Wrap it with a filter that will get fed as new values get added to the underlying DataSeries. accum = technical.EventBasedFilter(seqDS, Accumulator(3)) # Put in some values. for i in range(0, 50): seqDS.append(i) # Get some values. print(accum[0]) # Not enough values yet. print(accum[1]) # Not enough values yet. print(accum[2]) # Ok, now we should have at least 3 values. print(accum[3]) # Get the last value, which should be equal to 49 + 48 + 47. print(accum[-1]) ``` ```default None None 3.0 6.0 144.0 ```