Go to the file
lesson1.py
and at the bottom of the file find this:
if __name__=='__main__': run_csv()
python lesson1.py
You'll notice that it does something and finally stop. So what's happening here?
First, have a look at the algo definition by finding in the file the following lines:
def initialize_csv(context): csv_fetcher(context,'data/MSFT.csv','signals')
def handle_data_csv(context): if random.randint(0,100) == 23: order(context,'MSFT',1) if random.randint(0,100) == 23: order(context,'AAPL',1) def run_csv(): data = CSVDataFactory(['data/MSFT.csv','data/AAPL.csv'])() strategy = Strategy(config,
handle_data=handle_data_csv,
initialize=initialize_csv) strategy.run(data,
start=datetime(2012,1,1),
finish=datetime(2014,12,12))
This is all Toboggan needs to run. Let's take this apart a little. The crucial bit is our run_csv()function and the first line says:
data = CSVDataFactory(['data/MSFT.csv','data/AAPL.csv'])()
This line instantiates our data source, which is a bunch of sample csv files that live in the data/directory of the Toboggan repo. CSVDataFactory is a class in the data_factory.py file. I'll talk about the data factory in detail later. What you need to know for now is that the funny parenthesis at the end of the command call a function within the class that creates a data object that can be used by the algo engine for processing. If the notion of objects, classes and functions slightly confuses you, it's not really that important for now. So don't worry too much.
After we created a data object, we instantiate the strategy with
strategy = Strategy(config,handle_data=handle_data_csv,initialize=initialize_csv)
When we do this we pass in several other objects, namely config, handle_data and initialise.
config is a file that contains configuration values for the strategy and this file lives in the config folder. In many cases, algos have a long list of configuration parameters and it's advisable to separate them from the rest of the code, so the code does not change when we want to run a bunch of other values.
With initialise we can set the initial conditions for our simulation. In our case we fetch some external data with a fetcher. This will be explained later. In this algo, the fetcher doesn't actually do anything. So, our initialize() function is effectively empty.
Finally, we have handle_data() which is called every time a new tick comes in. This is where we define what the algo needs to do. In our case, we just order a random number of either AAPL or MSFT shares whenever our if-condition is true.
You notice that there is a mysterious context variable. This is kind of the donkey that you can attach all sorts of baggage to and it will hardly ever complain. More on this in the next blog.
Finally, we run our algo with
strategy.run(data,start=datetime(2012,1,1),finish=datetime(2014,12,12))
run() is a function that is part of the strategy object. It processes block data (rather than streaming data). Block data are simply lines that are read into memory at once as a block. The Strategy() class lives in the engine.py file. Have a look if you like. I will explain more on that later.
Finally you'll see some lines like this:
Order Loaded AAPL 2014-10-29 00:00:00(datetime.datetime(2014, 10, 30, 0, 0), 'ORDERING instrument:', 'AAPL', ' quantity:', 0, ' price:', 106.98, ' positions:', 4, 'pnl:', 144.70000000000002)
Here, the algo tells us that we've submitted some trades with "Order Loaded" and executed them on the next available bar. In order for these trades to show up, we open the file config_lesson1.py in the config directory and set PRINT_TRADES = True.
Easy! Please leave your comments. Again, if you have trouble installing Python packages, please try to solve this yourself and, by all means, use Stackoverflow.