Disclaimer
Before reading this tutorial you, the reader, agree to the following. This tutorial and the code it contains are designed to be informational and educational tools only. They do not constitute investment advice. The author, Dave Topper, strongly recommends that you seek the advice of a financial services professional before making any type of investment. This model is provided as a rough approximation of future financial performance. The results presented are hypothetical and will likely not reflect the actual growth of your own investments. The author, Dave Topper, is not responsible for any human or mechanical errors or omissions. The author, Dave Topper, is not responsible for the consequences of any decisions or actions taken in reliance upon or as a direct or indirect result of the information provided by these tools.
With the basic infrastructure out of the way we can start by creating a top-down initial implementation of our trading model class, then fill in the blanks.
The basic execution sequence we will use is as follows.
1. Create model params from command line args. We have essentially already done this.
2. Create an instance of the trading model class.
3. Initialize the model with the input params. Note: this will also load data from the specified input file.
4. Run the model.
5. Print out relevant statistics from the model run.
Add a new tradingModel class to your project.
Be sure to enforce the camel case convention for the source and header file names.
Here is the header file tradingModel.h.
#ifndef TRADINGMODEL_H
#define TRADINGMODEL_H
#include <memory>
class modelParameters;
// Trading model class that executes trading logic for a crossover based strategy
// Enum for trade state machine
enum TRADE_STATE {
SOLD = 0,
SELL = 1,
BOUGHT = 2,
BUY = 3
};
// Class definition
class tradingModel
{
public:
tradingModel();
void test();
// Steps 3-5 of the basic paradigm
bool init(std::shared_ptr<modelParameters>);
void run();
void printStats();
private:
// We will use these internally
bool loadPriceData();
void setTradeState(TRADE_STATE);
TRADE_STATE getTradeState();
TRADE_STATE tradeState_;
std::shared_ptr<modelParameters> modelParams_;
unsigned movingAvgLen1_;
unsigned movingAvgLen2_;
};
#endif // TRADINGMODEL_H
Here is the source file tradingModel.cpp.
#include <QFile>
#include <iostream>
#include "tradingModel.h"
#include "modelParameters.h"
// Trading model class that executes trading logic for a crossover based strategy
tradingModel::tradingModel()
{
}
void tradingModel::test()
{
}
// Initialize the model
bool tradingModel::init(std::shared_ptr<modelParameters> inParams)
{
// We start out as sold
setTradeState(SOLD);
// Grab input parameters and store them to local var modelParams_
modelParams_ = inParams;
// File name -> price data load
bool priceDataLoaded = loadPriceData();
// Moving average lengths
movingAvgLen1_ = modelParams_->getMovingAvgLen1();
movingAvgLen2_ = modelParams_->getMovingAvgLen2();
// Moving averages implemented in section 11.
bool movingAverageLengthsValid = ((movingAvgLen1_ > 0) && (movingAvgLen2_ > 0));
return (priceDataLoaded && movingAverageLengthsValid);
}
// Read the data file and load it into a price data object
bool tradingModel::loadPriceData()
{
bool fileReadSuccess = false;
// Get the data filename
QString priceDataFilename = modelParams_->getDataFilename();
// Extra check to make sure we've received a file name
if (priceDataFilename.isEmpty())
return false;
// Price data set class implemented in section 9.
// Remainder implemented in secetion 10.
return fileReadSuccess;
}
// Functions to manage our model's trade state (eg., state machine)
void tradingModel::setTradeState(TRADE_STATE inState)
{
tradeState_ = inState;
}
TRADE_STATE tradingModel::getTradeState()
{
return tradeState_;
}
// Run the model
void tradingModel::run()
{
// Implemented in section 14.
}
// Print out various stats related to the most recent run
void tradingModel::printStats()
{
// Implemented in section 15.
}
If any of the above doesn’t make complete sense right now, don’t worry. We will be fleshing out each of the member functions above in the coming sections. For now, however, let’s look at a few parts of the class to get a better idea of how things will work.
Description of the trading logic phases (state machine)
Note the enum at the beginning of the header file. This is a very basic state definition for a trading model. Using a state machine will make it easier to build our model’s trading logic. The basic idea is that the model moves from one state to another when certain criteria are met.
The model starts out in a SOLD state. We don’t own any shares to begin with.
If the right conditions are met, the model moves from SOLD to BUY.
Once in a BUY state, we move to a BOUGHT state.
Once again, if the right conditions are met, the model moves from BOUGHT to SELL.
Once in a SELL state, we move once again to a SOLD state.
You might wonder, why not just have BUY and SELL states? You could in theory build a model like that but you would likely soon find that developing anything beyond the most basic logic rapidly becomes cumbersome.
The “thinking” for our model will execute in three phases.
- A DECISION phase. This is where we would move from SOLD to BUY or BOUGHT to SELL.
- An ACTION phase. This is where we would move from BUY to BOUGHT or SELL to SOLD.
- An UPDATE phase where we update various components of our model that do not necessarily affect our Trade State.
We will go over this again when we build our trading logic.
For now, build the project to ensure the code above has been input correctly. There is nothing new to run right now.
Build your project to check for errors. There is nothing new to run.
In the next section, we we build a price data class that will be used by our tradingModel’s loadPriceData() function.