// Update the current EMAdifference (see design documentation), perform // required steps at the current state and then find the next FSM state void PairsTrading::doPairsTrading(double current_money, void *m_pclient) { // Calculate EMAdifference and return if EMAs are not yet valid if (calculateDiff() == false) return; // Debugging only fTest << "Entering state " << state << ", EMA diff: " << EMAdifference << ", ccount: " << correlatedCount; // handle current state if (state == 1) State1(); else if (state == 2) State2(); else if (state == 3) State3(current_money, m_pclient); else State4(m_pclient); // Debugging only fTest << ". Leaving state " << state << std::endl; }
void States_Task() { switch(State) { case 0: State0();break; case 1: State1();break; case 2: State2();break; case 3: State3();break; case 4: State4();break; case 10: State10();break; } }
// handle state 3, DIVERGED (we exploit this) // Based on how long we have been diverged (i.e. EMAdifference between // thresholds T1 and T2), place an order on each stock. The type of order // depends on if the stock is rising or falling. void PairsTrading::State3(double current_money,void *m_pclient) { // if the algorithm has failed or is back to the uncorrelated region if ( (EMAdifference > T2) || (EMAdifference < T1) || (divergedCount >= 100) ) { // undo all trades State4(m_pclient); // reset counts divergedCount = 0; // if we return from divergence, we are still correlated if (EMAdifference < T1) { state = CORRELATED; } // else failed because we are uncorrelated else { correlatedCount = 0; state = UNCORRELATED; } return; } // Increment how long we have been diverged so that we know to increase // the amount to invest this time step divergedCount++; s1Data.percentChangeSinceDiv = (s1Data.currentEMA - s1Data.EMAatDivergence) / 100; s2Data.percentChangeSinceDiv = (s2Data.currentEMA - s2Data.EMAatDivergence) / 100; // start buying/selling // if stock 1 is falling, buy it if (s1Data.percentChange < s2Data.percentChange) { // BUY STOCK 1, since we expect it to rise double buyAmount = getInvestmentAmount ("buy", s1Data.currentEMA - s1Data.EMAatDivergence, divergedCount, current_money); s1->placeOrder("BUY", buyAmount, m_pclient, s1Data.AmountBought); s1Data.OrderType[idListTop] = "SELL"; s1Data.OrderAmount[idListTop] = buyAmount; // SELL STOCK 2 double sellAmount = getInvestmentAmount ("sell", s2Data.currentEMA - s2Data.EMAatDivergence, divergedCount, current_money ); // placeOrder returns false if the stock is not shortable if (s2->placeOrder("SELL", sellAmount, m_pclient, s2Data.AmountBought)) { s2Data.OrderType[idListTop] = "BUY"; s2Data.OrderAmount[idListTop] = sellAmount; } else { s2Data.OrderType[idListTop] = "NONE"; s2Data.OrderAmount[idListTop] = 0; } } else { // BUY STOCK 2 double buyAmount = getInvestmentAmount ("buy", s2Data.currentEMA - s2Data.EMAatDivergence, divergedCount, current_money ); s2->placeOrder("BUY", buyAmount, m_pclient, s2Data.AmountBought); s2Data.OrderType[idListTop] = "SELL"; s2Data.OrderAmount[idListTop] = buyAmount; // SELL STOCK 1 double sellAmount = getInvestmentAmount ("sell", s1Data.currentEMA - s1Data.EMAatDivergence, divergedCount, current_money ); // placeOrder returns false if the stock is not shortable if (s1->placeOrder("SELL", sellAmount, m_pclient, s1Data.AmountBought)) { s1Data.OrderType[idListTop] = "BUY"; s1Data.OrderAmount[idListTop] = sellAmount; } else { s1Data.OrderType[idListTop] = "NONE"; s1Data.OrderAmount[idListTop] = 0; } } }