Last active
February 17, 2016 13:51
-
-
Save cdfpaz/7d1c7ad16b21fa64650d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <set> | |
#include <iostream> | |
#include <complex> | |
#include <algorithm> | |
#include <stdexcept> | |
template <typename T> int sgn(T val) { | |
return (T(0) < val) - (val < T(0)); | |
} | |
class ProfitLoss { | |
public: | |
typedef std::set<std::pair<int, double> > Type; | |
ProfitLoss():m_net(0), m_realized(0), m_avgOpenPrice(0) { | |
} | |
ProfitLoss(const Type& initial) { | |
int buyQuantity = 0, sellQuantity = 0; | |
double averageBuyPrice = 0, averageSellPrice = 0; | |
Type::const_iterator fill = initial.begin(); | |
for(; fill != initial.end(); ++fill) { | |
if (fill->first > 0) { | |
buyQuantity += fill->first; | |
averageBuyPrice += fill->first * fill->second; | |
} | |
else if(fill->first < 0) { | |
int absQuantity = std::abs(fill->first); | |
sellQuantity += absQuantity; | |
averageSellPrice += absQuantity * fill->second; | |
} | |
} | |
if (buyQuantity > 0) | |
averageBuyPrice /= buyQuantity; | |
if (sellQuantity > 0) | |
averageSellPrice /= sellQuantity; | |
set_Net(buyQuantity - sellQuantity); | |
set_AverageOpenPrice(get_Net() > 0 ? averageBuyPrice : averageSellPrice); | |
set_Realized((averageSellPrice - averageBuyPrice) * std::min(buyQuantity, sellQuantity)); | |
} | |
double get_Realized() { | |
return m_realized; | |
} | |
void set_Realized(double v) { | |
m_realized = v; | |
} | |
double get_Net() { | |
return m_net; | |
} | |
void set_Net(double v) { | |
m_net = v; | |
} | |
double get_AverageOpenPrice() { | |
return m_avgOpenPrice; | |
} | |
void set_AverageOpenPrice(double v) { | |
m_avgOpenPrice = v; | |
} | |
void AddFill(int fillQty, double fillPrice) { | |
if (fillQty == 0) | |
throw std::logic_error("Quantity must be non-zero."); | |
if ((sgn(get_Net()) != sgn(fillQty))) { | |
int absNet = std::abs(get_Net()); | |
int absQuantity = std::abs(fillQty); | |
if (absNet == absQuantity) { // flat | |
set_Realized(get_Realized() + (fillPrice - get_AverageOpenPrice()) * get_Net()); | |
set_AverageOpenPrice(0); | |
} | |
else if (absNet > absQuantity) { // decrease | |
set_Realized(get_Realized() + (fillPrice - get_AverageOpenPrice()) * -fillQty); | |
} | |
else { // reverse | |
set_Realized(get_Realized() + (fillPrice - get_AverageOpenPrice()) * get_Net()); | |
set_AverageOpenPrice(fillPrice); | |
} | |
} | |
else { | |
set_AverageOpenPrice((get_Net() * get_AverageOpenPrice() + fillQty * fillPrice) / (get_Net() + fillQty)); | |
} | |
set_Net(get_Net() + fillQty); | |
} | |
double FloatingForTheoriticalExit(double exitPrice) { | |
return (exitPrice - get_AverageOpenPrice()) * get_Net(); | |
} | |
void Dump() { | |
std::cout << std::endl << "\tRealized " << get_Realized() << std::endl; | |
std::cout << "\tNet " << get_Net() << std::endl; | |
std::cout << "\tAverageOpenPrice " << get_AverageOpenPrice() << std::endl; | |
} | |
private: | |
int m_net; | |
double m_realized; | |
double m_avgOpenPrice; | |
}; | |
int main(void) { | |
std::cout << std::endl; | |
std::cout << "*** calling constructor PL" << std::endl; | |
ProfitLoss::Type t; | |
t.insert(std::pair<int, double>(12, 100.0)); | |
t.insert(std::pair<int, double>(17, 99.0)); | |
t.insert(std::pair<int, double>(-9, 101.0)); | |
t.insert(std::pair<int, double>(-4, 105.0)); | |
t.insert(std::pair<int, double>(3, 103.0)); | |
ProfitLoss pa(t); | |
pa.Dump(); | |
try { | |
//pa.AddFill(10, 100.0); | |
//pa.AddFill(-12, 101.0); | |
//pa.AddFill(-19, 101.0); | |
//pa.AddFill(-22, 101.0); | |
} | |
catch(std::exception& ex) { | |
std::cout << "error: " << ex.what() << std::endl; | |
} | |
//pa.Dump(); | |
std::cout << std::endl << "*** calling add fill PL" << std::endl; | |
ProfitLoss pb; | |
try { | |
pb.AddFill(12, 100.0); | |
pb.AddFill(17, 99.0); | |
pb.AddFill(-9, 101.0); | |
pb.AddFill(-4, 105.0); | |
pb.AddFill(3, 103.0); | |
} | |
catch(std::exception& ex) { | |
std::cout << "error: " << ex.what() << std::endl; | |
} | |
pb.Dump(); | |
std::cout << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment