Statistical arbitrage

StratArb finds two or a set of stocks or ETFs that are cointegrated. When the supposed mean reversion portfolio deviates from the historical mean, positions are open and otherwise closed.

The parameters are specified in json files. An example is

{
	"strategy":"statisticalArbitrage",
	"symbols":["DOD","AOA"],
	"nLookback":20,
	"entryScore":2,
	"exitScore":0.05,
	"nPosition":100,
	"initialization":1,
	"histDataPath":"DOD_AOA.csv"
}

Factor models

Factor models use machine learning algorithms, mostly regressions, to estimate equity returns and their covariances. Based on these estimations, optimal weights of the equities in the portfolio are calculated and the portfolio is submited for execution.

The portfolio is rebalanced weekly. The portfolio is constructed using MATLAB and then read into GradientFlows for execution. An example is

Symbol AVY COL DGX DTE ED EQR KO MSFT NEE PPL RAI ROP SWK SYK UTX VRSN XEL XL
Quantity 79 72 62 47 56 98 182 85 34 138 119 27 46 44 68 67 99 197

Gamma Scalping

Gamma scalping establishes a long position in straddle and long or short position in the underlying. The stragegy shorts the underlying when it moves higher and longs the underlying when it moves lower. Profits are made from mean reversion. Below are the code used for real trading.

class StratGammaScalping : public Strategy
{
	std::string    m_symbol;                    //underlying symbol
	double         m_strike;                    //strike                
	Date           m_expiry;                    //expiry
	Contract       m_contract;                  //option contract of symbol
	Order          m_buyOrder;                  //buy order
	Order          m_sellOrder;                 //sell order
	int            m_currentTotalPosition;      //current total number of contracts
	StratOptionPtr m_stratOpt;                  //option trading module
	std::string    m_jsonFilename;              //strategy setting file
public:
	StratGammaScalping
	(
		const std::string& id,                                 //strategy id
		const std::string& filename,                           //strategy setting file
		OrderExecutionEnginePtr orderExecutionEngine,          //order execution engine
		MarketDataEnginePtr mktDataEngine,                     //market data engine
		StratOptionPtr m_stratOpt                              //option trading module
	)
	:Strategy(id, "StratGammaScalping", orderExecutionEngine, mktDataEngine), m_stratOpt(stratOpt), m_jsonFilename(filename)
	{

		CELLDictPtr dict = jsonFromFile(filename);
		m_symbol = dict->toString("symbol");
		m_strike = dict->toDouble("strike");
		m_expiry = str::toDate(dict->toString("expiry"),"");
		m_currentTotalPosition = dict->toDouble("currentTotalPosition");

		m_contract = TradingUtility::strToContract(m_symbol);

		m_buyOrder.action = "BUY";
		m_buyOrder.totalQuantity = 1;
		m_buyOrder.orderType = "MKT";
		m_buyOrder.lmtPrice = 0;

		m_sellOrder.action = "SELL";
		m_sellOrder.totalQuantity = 1;
		m_sellOrder.orderType = "MKT";
		m_sellOrder.lmtPrice = 0;


		m_stratOpt->reqMktData(m_strike, m_expiry);
	}

	//apply function will be called everytime market data updates. This function
	//is to determine if the updates concerns the symbol
	bool symbolInPortfolio(const std::string& symbol)
	{ 
		if (symbol == m_symbol)
			return true;
		return false; 
	};


	//calculate delta of the straddle
	double calcDelta()
	{
		double impliedVolCall, deltaCall, gammaCall, thetaCall, vegaCall;
		double impliedVolPut, deltaPut, gammaPut, thetaPut, vegaPut;

		m_stratOpt->calculate(m_strike, m_expiry, OptionStrategyType::CALL, impliedVolCall, deltaCall, gammaCall, thetaCall, vegaCall);
		m_stratOpt->calculate(m_strike, m_expiry, OptionStrategyType::PUT, impliedVolPut, deltaPut, gammaPut, thetaPut, vegaPut);

		double delta = deltaCall + deltaPut + m_currentTotalPosition / 100.0;
		return delta;
	}

	//hedge the straddle
	void deltaHedge()
	{
		double delta = calcDelta();
		if (delta > 0.2)
		{
			m_sellOrder.totalQuantity = (int)(delta * 100);
			m_currentTotalPosition -= m_sellOrder.totalQuantity;
			getOrderExecutionEngine()->addOrder(m_contract, m_sellOrder, "StratGammaScalping " + m_id);
			writeFile(m_currentTotalPosition);
		}
		else if (delta < -0.2)
		{
			m_buyOrder.totalQuantity = (int)(-delta * 100);
			m_currentTotalPosition += m_buyOrder.totalQuantity;
			getOrderExecutionEngine()->addOrder(m_contract, m_buyOrder, "StratGammaScalping " + m_id);
			writeFile(m_currentTotalPosition);
		}       
	}

	//display the status of the current position
	const std::string status() 
	{ 
		double delta = calcDelta();
		return str::fromNumber(delta); 
	}

	//save position to file at end of day
	void writeFile(int currentTotalPosition)
	{
		CELLDictPtr dict = jsonFromFile(m_jsonFilename);
		dict->set("currentTotalPosition", (double)currentTotalPosition);
		std::ofstream file(m_jsonFilename, 'w');
		if (file.is_open())
		{
			file << *dict;
			file.close();
		}
	}

	//the entry point. This function gets called every time market data updates
	void apply(const std::string& symbol) 
	{       
		if (isRunning() && symbolInPortfolio(symbol))
		{           
			utl::Log("StratGammaScalping::apply") << m_symbol << " deltaHedge Called\n";
			deltaHedge();
		}

	}

	//manually call delta hedge
	void applyOnce(const std::string& parameters) 
	{
		deltaHedge();
	}
};

The settings are read from json files. Below is an example

{
	"currentTotalPosition" : -65,
	"expiry" : "20170324",
	"strategy" : "gammaScalping",
	"strike" : 139,
	"symbol" : "AAPL"
}