7. Input Argument Parser Class

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.

In this section we’ll add our command line parser. Its primary purpose will be to parse input arguments and create a new model parameter class.

Add a new inputArgumentParser class to your project.

Be sure to enforce the camel case convention for the source and header file names.

Your Project Section outline should now look like this.

Here is the header file file, inputArgumentParser.h.


#ifndef INPUTARGUMENTPARSER_H
#define INPUTARGUMENTPARSER_H

#include <memory>

class QStringList;

// Class to parse command line arguments into model params

class modelParameters;

class inputArgumentParser
{
public:
    inputArgumentParser();
    std::shared_ptr<modelParameters> createModelParams(QStringList &);
};

#endif // INPUTARGUMENTPARSER_H

For now the only thing this class will do is parse command line arguments. But since parsing them is now contained in a class it’s possible to expand it to do other things later (eg., run in debug mode, etc.).

Note the #include <memory> directive. This is so that we can use the std::shared_ptr definition. We’ll be using smart pointers when necessary instead of raw pointers. They are a powerful addition to C++11. There has been a great deal written about how to use them. In this tutorial we will be using shared_ptr when an object is shared or returned by a function. We will be using unique_ptr when an object is only owned by one class.

Click here to read more about smart pointers.

We will also generally try to avoid including other header files inside the ones we create using forward declarations instead. Sometimes, however, it’s quite simply easier to use a particular include inside a header. There has been quite a bit written about this as well, but those discussions are well beyond the scope of this tutorial. The header guards in all of our .h files will prevent any multiple definitions and compile errors. The qtcreator IDE adds these automatically when you use it to create a new class definition.

Click here to read more about header guards.

Here is the source file, inputArgumentParser.cpp.


#include <QStringList>
#include <iostream>

#include "inputArgumentParser.h"
#include "modelParameters.h"

inputArgumentParser::inputArgumentParser()
{
}

// Parse command line args
std::shared_ptr<modelParameters> inputArgumentParser::createModelParams(QStringList & inArgs)
{
    std::shared_ptr<modelParameters> returnParams(new modelParameters());
    int nArgs = inArgs.length();

    // Traverse all the input args
    for (int i=1; i<nArgs; i++)
    {

        // dataFilename
        if (!qstrcmp(inArgs[i].toStdString().c_str(), "-df"))
        {
            i++;
            returnParams->setDataFilename(inArgs[i]);
        }

        // moving average length 1
        else if (!qstrcmp(inArgs[i].toStdString().c_str(), "-mAvgL1"))
        {
            i++;
            returnParams->setMovingAvgLen1(inArgs[i].toUInt());
        }

        // moving average length 2
        else if (!qstrcmp(inArgs[i].toStdString().c_str(), "-mAvgL2"))
        {
            i++;
            returnParams->setMovingAvgLen2(inArgs[i].toUInt());
        }

        // Unknown arguments
        else {
            std::cerr << "Unknown argument: " << inArgs[i].toStdString() << std::endl;
        }
    }
    return returnParams;
}

The createModelParams() method simply traverses the QStringList of arguments, matching each duplet to the corresponding modelParams element. So our program should be executed as:

algoTradingModel -df data.csv -mAvgL1 20 -MAvgL2 50

Where the command line flags map to the following model parameters:

-df <data file name>
   -mAvgL1 <length for moving average 1>
   -mAvgL2 <length for moving average 2>

We need to make a few changes to our mainCommandLine class and main.cpp files to execute the new code.

Here are the changes to the relevant files.

mainCommandLine.h


#include <QStringList>
...
    void run(QStringList &);

mainCommandLine.cpp


#include "modelParameters.h"
#include "inputArgumentParser.h"
...
// Run method
void mainCommandLine::run(QStringList & inputArgs)
{
    // Create model params from command line args
    std::unique_ptr<inputArgumentParser> inputArgParser = std::unique_ptr<inputArgumentParser>(new inputArgumentParser());

    // Test out the params
    std::shared_ptr<modelParameters> modelParams = inputArgParser->createModelParams(inputArgs);
     modelParams->test();
}

main.cpp

    
...
    // else run in command line mode via mainCommandLine.run()
    else
    {
        QStringList inputArgs = app->arguments();
        mainCommandLine mainCL;
        mainCL.run(inputArgs);
    }

Compile your code and check for errors.

Run the program with the three command line arguments we just added. You should see the following in the Application Output window.


$./algoTradingModel -df data.csv -mAvgL1 20 -mAvgL2 50
dataFilename = data.csv
movingAvgLen1 = 20
movingAvgLen2 = 50
$

In the next section we’ll start building up our trading model class.

< previous | next >