├── bin ├── .gitignore └── SmartOrderRouter.exe ├── .gitignore ├── lib └── .gitignore ├── spike ├── .gitignore ├── Main.cpp ├── makefile └── FixMessage.h ├── test └── .gitignore ├── doc ├── IT100916.pdf └── References.txt ├── include ├── Side.h ├── OrderType.h ├── TimeInForce.h ├── ExecType.h ├── OrderStatus.h ├── SerialRouter.h ├── VenueManager.h ├── Execution.h ├── Venue.h ├── VenueRank.h ├── Order.h └── Logger.h ├── makefile ├── src ├── SerialRouter.cpp ├── Main.cpp └── VenueManager.cpp └── README.md /bin/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .noop 2 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | .noop 2 | -------------------------------------------------------------------------------- /spike/.gitignore: -------------------------------------------------------------------------------- 1 | .noop 2 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | .noop 2 | -------------------------------------------------------------------------------- /doc/IT100916.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asim2025/SmartOrderRouter/HEAD/doc/IT100916.pdf -------------------------------------------------------------------------------- /bin/SmartOrderRouter.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asim2025/SmartOrderRouter/HEAD/bin/SmartOrderRouter.exe -------------------------------------------------------------------------------- /include/Side.h: -------------------------------------------------------------------------------- 1 | #ifndef SIDE_H 2 | #define SIDE_H 3 | 4 | enum class SIDE : char 5 | { 6 | BUY = '1', 7 | SELL = '2' 8 | }; 9 | #endif 10 | -------------------------------------------------------------------------------- /include/OrderType.h: -------------------------------------------------------------------------------- 1 | #ifndef ORDER_TYPE_H 2 | #define ORDER_TYPE_H 3 | 4 | enum class ORDER_TYPE : char 5 | { 6 | MARKET = '1', 7 | LIMIT = '2' 8 | }; 9 | #endif 10 | -------------------------------------------------------------------------------- /include/TimeInForce.h: -------------------------------------------------------------------------------- 1 | #ifndef TIME_IN_FORCE_H 2 | #define TIME_IN_FORCE_H 3 | 4 | enum class TIME_IN_FORCE : char 5 | { 6 | DAY = '0', 7 | GTC = '1', 8 | IOC = '3' 9 | // add others 10 | }; 11 | #endif 12 | -------------------------------------------------------------------------------- /spike/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "FixMessage.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main(void) 7 | { 8 | string s("8=FIX.4.49=156535=D"); 9 | FixMessage fm; 10 | fm.parse(s); 11 | string msg = fm.create(); 12 | fm.parse(msg); 13 | } 14 | -------------------------------------------------------------------------------- /doc/References.txt: -------------------------------------------------------------------------------- 1 | References 2 | 3 | 1) Multi Agent Smart Order Router PDF 4 | https://www.inf.ed.ac.uk/publications/thesis/online/IT100916.pdf 5 | 6 | 2) C++ Project Structure 7 | http://hiltmon.com/blog/2013/07/03/a-simple-c-plus-plus-project-structure/ 8 | 9 | 10 | -------------------------------------------------------------------------------- /include/ExecType.h: -------------------------------------------------------------------------------- 1 | #ifndef ExEc_TYPE_H 2 | #define ExEc_TYPE_H 3 | 4 | enum class EXEC_TYPE : char 5 | { 6 | NEW = '0', 7 | DONE = '3', 8 | CANCELLED = '4', 9 | TRADE = 'F', 10 | REJECTED = '8', 11 | EXPIRED = 'C' 12 | 13 | 14 | }; 15 | #endif 16 | -------------------------------------------------------------------------------- /include/OrderStatus.h: -------------------------------------------------------------------------------- 1 | #ifndef ORDER_STATUS_H 2 | #define ORDER_STATUS_H 3 | 4 | enum class ORDER_STATUS : char 5 | { 6 | NEW = '0', 7 | PARTIAL = '1', 8 | FILLED = '2', 9 | CANCELLED = '4', 10 | REJECTED = '8', 11 | EXPIRED = 'C' 12 | 13 | 14 | }; 15 | #endif 16 | -------------------------------------------------------------------------------- /spike/makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-g -Wall -std=c++11 3 | LDFLAGS= 4 | BIN=Main 5 | SRC=$(wildcard *.cpp) 6 | OBJ=$(SRC:%.cpp=%.o) 7 | 8 | all: $(OBJ) 9 | $(CXX) $(CXXFLAGS) -o $(BIN) $^ 10 | 11 | %.o: %.c 12 | $(CXX) $(CXXFLAGS) $@ -c $< 13 | 14 | clean: 15 | rm -f *.o 16 | rm $(BIN) 17 | 18 | 19 | -------------------------------------------------------------------------------- /include/SerialRouter.h: -------------------------------------------------------------------------------- 1 | #ifndef SERIAL_ROUTER_H 2 | #define SERIAL_ROUTER_H 3 | #include "VenueManager.h" 4 | #include "OrderStatus.h" 5 | #include "TimeInForce.h" 6 | #include "OrderType.h" 7 | #include "Side.h" 8 | #include "Order.h" 9 | #include "Logger.h" 10 | #include "Venue.h" 11 | 12 | 13 | /* 14 | * 15 | * Serial Router 16 | * 17 | * Split parent order and send orders serially 18 | * to multiple venues. 19 | * 20 | */ 21 | class SerialRouter 22 | { 23 | public: 24 | SerialRouter(const VenueManager & vm) : VenueManager( vm ), Log("SerialRouter") 25 | { } 26 | 27 | void route(const Order & order); 28 | 29 | private: 30 | VenueManager VenueManager; 31 | Logger Log; 32 | }; 33 | 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-g -Wall -std=c++11 3 | LDFLAGS= 4 | BUILDDIR=build 5 | TARGET=bin 6 | SRCEXT=cpp 7 | SRCDIR=src 8 | SOURCES=$(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) 9 | OBJECTS=$(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) 10 | LIB= 11 | INC=-I include 12 | 13 | 14 | 15 | all: $(TARGET) 16 | mv $(TARGET).exe $(TARGET)/SmartOrderRouter.exe 17 | 18 | $(TARGET): $(OBJECTS) 19 | $(CXX) $(CXXFLAGS) $^ -o $(TARGET) $(LIB) 20 | 21 | $(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) 22 | mkdir -p $(BUILDDIR) 23 | $(CXX) $(CXXFLAGS) $(INC) -c -o $@ $< 24 | 25 | 26 | clean: 27 | rm -rf $(BUILDDIR)/* 28 | rm -rf $(TARGET)/* 29 | rm -rf *stackdump* 30 | 31 | debug: 32 | echo "Sources: $(SOURCES) " 33 | echo "Objects: $(OBJECTS)" 34 | echo "Target: $(TARGET)" 35 | echo "Buil Dir: $(BUILDDIR)" 36 | 37 | -------------------------------------------------------------------------------- /include/VenueManager.h: -------------------------------------------------------------------------------- 1 | #ifndef VENUE_MANAGER_H 2 | #define VENUE_MANAGER_H 3 | #include 4 | #include 5 | #include 6 | #include "Venue.h" 7 | #include "Logger.h" 8 | #include "Order.h" 9 | #include "Execution.h" 10 | 11 | class VenueManager 12 | { 13 | public: 14 | explicit VenueManager(std::vector & venues ) : Venues( venues ), Log("VenueManager") 15 | { init(); } 16 | 17 | 18 | void add_venue(const Venue & venue); 19 | void remove_venue(Venue & venue); 20 | std::vector venues(const std::string & symbol); 21 | void send_order(const Venue & venue, const Order & order); 22 | void process_exec(const Execution & exec); 23 | private: 24 | std::vector Venues; 25 | std::map> SymbolVenues; 26 | Logger Log; 27 | void init(); 28 | 29 | 30 | }; 31 | #endif 32 | -------------------------------------------------------------------------------- /spike/FixMessage.h: -------------------------------------------------------------------------------- 1 | #ifndef FIX_MESSAGE_H 2 | #define FIX_MESSAGE_H 3 | #include 4 | #include 5 | #include 6 | 7 | class FixMessage 8 | { 9 | public: 10 | explicit FixMessage( ) 11 | { } 12 | 13 | void parse(const std::string & msg) 14 | { 15 | raw_msg = msg; 16 | std::cout << "printing..." << std::endl; 17 | for (unsigned int i = 0; i < msg.length(); ++i) 18 | { 19 | if (msg[i] == '\001') 20 | std::cout << "delemiter found" << std::endl; 21 | std::cout << i << ":" << msg[ i ] << std::endl; 22 | } 23 | std::cout << "end." << std::endl; 24 | } 25 | 26 | 27 | std::string create() 28 | { 29 | char * arr = new char[100]; 30 | arr[0] = '8'; arr[1] = '='; arr[2]='F'; 31 | arr[3] = 'I'; arr[4] = 'X'; arr[5]='\001'; 32 | arr[6] = '\0'; 33 | std::cout << "create " << arr << std::endl; 34 | std::string s(arr); 35 | return s; 36 | } 37 | 38 | void addTag(std::string tag, std::string value) 39 | { } 40 | 41 | void print( ) const 42 | { 43 | std::cout << raw_msg << std::endl; 44 | } 45 | 46 | private: 47 | std::string raw_msg; 48 | }; 49 | #endif 50 | 51 | -------------------------------------------------------------------------------- /src/SerialRouter.cpp: -------------------------------------------------------------------------------- 1 | #include "SerialRouter.h" 2 | #include "Logger.h" 3 | #include "Venue.h" 4 | #include "VenueManager.h" 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | 11 | /* 12 | * 13 | * Serial Router 14 | * 15 | * Split parent order and send orders serially 16 | * to multiple venues. 17 | * 18 | */ 19 | void SerialRouter::route(const Order & prnt) 20 | { 21 | Log.info("routing ..."); 22 | 23 | if ( prnt.is_terminal() ) 24 | { 25 | Log.error("order is in terminal state."); 26 | return; 27 | } 28 | 29 | int leavesQty = prnt.leavesQty(); 30 | if ( leavesQty == 0 ) 31 | { 32 | Log.error("order is fully filled."); 33 | return; 34 | } 35 | 36 | Log.info("leavesQty: ", leavesQty); 37 | 38 | string symbol = prnt.symbol(); 39 | Log.info("symbol: ", symbol); 40 | 41 | vector venues = VenueManager.venues( symbol ); 42 | if (venues.empty()) 43 | { 44 | Log.error("no venues found for symbol:", symbol); 45 | return; 46 | } 47 | 48 | for (auto v : venues) 49 | { 50 | int child_qty = leavesQty * v.exec_prob(); 51 | cout << "v: " << v << ", prob:" << v.exec_prob() << ", child_qty: " << child_qty << endl; 52 | Order child( prnt ); 53 | child.set_qty( child_qty ); 54 | VenueManager.send_order( v, child); 55 | } 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /include/Execution.h: -------------------------------------------------------------------------------- 1 | #ifndef EXECUTION_H 2 | #define EXECUTION_H 3 | #include "Side.h" 4 | #include "OrderType.h" 5 | #include "OrderStatus.h" 6 | #include "TimeInForce.h" 7 | #include "ExecType.h" 8 | #include 9 | #include 10 | 11 | 12 | class Execution 13 | { 14 | public: 15 | explicit Execution(std::string orderID, std::string execID, EXEC_TYPE execType, ORDER_STATUS ordStatus, 16 | std::string symbol, SIDE side, int leavesQty, int cumQty, double avgPx) : 17 | OrderID( orderID ), 18 | ExecID( execID ), 19 | ExecType( execType), 20 | OrdStatus( ordStatus ), 21 | Symbol( symbol ), 22 | Side( side ), 23 | LeavesQty( leavesQty ), 24 | CumQty( cumQty ), 25 | AvgPx( avgPx ) 26 | { } 27 | 28 | 29 | int leavesQty() const 30 | { return LeavesQty; } 31 | 32 | 33 | std::string symbol() const 34 | { return Symbol; } 35 | 36 | std::string exec_id() const 37 | { return ExecID; } 38 | 39 | std::string order_id() const 40 | { return OrderID; } 41 | 42 | 43 | private: 44 | // --- fix fields --- 45 | std::string OrderID; // 37 46 | std::string ExecID; // 17 47 | EXEC_TYPE ExecType; // 150 48 | ORDER_STATUS OrdStatus; // 39 49 | std::string Symbol; // 55 50 | SIDE Side; // 54=1 (buy), =2(sell) 51 | int LeavesQty; // 151 52 | int CumQty; // 14, filled qty 53 | double AvgPx; // 6 54 | }; 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /include/Venue.h: -------------------------------------------------------------------------------- 1 | #ifndef VENUE_H 2 | #define VENUE_H 3 | #include "VenueRank.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 10 | * 11 | * A Venue is either an Exchange or a Dark Pool 12 | * 13 | * 14 | */ 15 | class Venue 16 | { 17 | public: 18 | explicit Venue(std::string name, bool available, std::vector symbols) 19 | : Name( name ), Available( available ), Symbols( symbols ), Probability( 0.0 ) 20 | { } 21 | 22 | std::string name() const 23 | { return Name; } 24 | 25 | bool available() const 26 | { return Available; } 27 | 28 | std::vector symbols() const 29 | { return Symbols; } 30 | 31 | VenueRank ranking(const std::string & symbol) 32 | { return SymbolRankings[ symbol ]; } 33 | 34 | void update_rank(const std::string & symbol, const VenueRank & rank) 35 | { SymbolRankings[ symbol ] = rank; } 36 | 37 | void set_exec_prob(double p) 38 | { Probability = p; } 39 | 40 | const double exec_prob() 41 | { return Probability; } 42 | 43 | private: 44 | std::string Name; // venue name 45 | bool Available; // venue availablility flag 46 | std::vector Symbols; // symbols supported by venue 47 | std::map SymbolRankings; // symbol ranking 48 | double Probability; // execution probability 49 | 50 | friend std::ostream& operator<< (std::ostream & os, const Venue & v) 51 | { 52 | os << "Venue: [" << v.name() << "," << v.available() << "," ; 53 | for (auto i : v.symbols()) 54 | os << i << ","; 55 | os << "]"; 56 | return os; 57 | } 58 | }; 59 | #endif 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SmartOrderRouter 2 | A Smart Order Router implementation based on research paper by A. Adhami (see doc folder). This project does not 'copy-n-paste' design and implementation discussed in the paper. I plan on highlighting my changes. 3 | 4 | ### Motivation 5 | I had following questions:
6 | Why do we need Smart Order Router (SOR)?
7 | Why not send orders directly to markets just like in the past?
8 | Are there any programming languages for low latency development?
9 | What is new in C++11?
10 | 11 | ### Objective 12 | Develop an *ultra low latency Smart Order Router (SOR)* for *Linux*. Use *test driven development* methodology and use *C++11* as the prmary implemenation language. Use *multi-threading* and *lock free* datastructures to acheive *micro-second* performance. 13 | 14 | ### Conflict Of Interest 15 | There are none with my day job. All research and work is done outside of office hours. My day job is developing *Algo trading* application in *Java* where trading algorithms (VWAP,TWAP etc.) run. I have knowledge of trading algos but I don't implement them in my day job. That is done by a separate team.
16 | SOR development team is different and I don't have access to any part of that system. 17 | 18 | ### Timeline 19 | A solid implementaiton will take some time since I have a day job and a family. However, my mindset is that I will learn something even if I don't get to finish. 20 | 21 | ### Environment 22 | 1) Intel i7-6500, 16gb ram, 512 gb SSD
23 | 2) Windows 10 - cheaper than other alternatives (where I live) and easier to carry on the go.
24 | 3) RedHat Cygwin 64 bit
25 | 4) g++ 2.9.3 w/ C++11 flags
26 | 5) Git and GitHub
27 | -------------------------------------------------------------------------------- /include/VenueRank.h: -------------------------------------------------------------------------------- 1 | #ifndef VENUE_RANK_H 2 | #define VENUE_RANK_H 3 | 4 | class VenueRank 5 | { 6 | 7 | public: 8 | explicit VenueRank() : VenueTradingCost(0.0), RouterHistTradingVolume(0.0), 9 | MarketHistTradingVolume(0.0), ImmediateTradingActivity(0.0), PriceImprovementIndicator(0.0) 10 | { } 11 | 12 | explicit VenueRank(double vtc, double rhtv, double mhtv, double ita, double pii) : 13 | VenueTradingCost( vtc ), RouterHistTradingVolume( rhtv ), MarketHistTradingVolume( mhtv ), 14 | ImmediateTradingActivity( ita ), PriceImprovementIndicator( pii ) 15 | { } 16 | 17 | void update_trading_cost(double v) 18 | { 19 | VenueTradingCost = v; 20 | } 21 | 22 | void update_router_hist_trading_volume(double v) 23 | { 24 | RouterHistTradingVolume += v; 25 | } 26 | 27 | void update_market_hist_trading_volume(double v) 28 | { 29 | MarketHistTradingVolume += v; 30 | } 31 | 32 | void update_immediate_trading_activity(double v) 33 | { 34 | ImmediateTradingActivity += v; 35 | } 36 | 37 | void update_price_improvement_indicator(double v) 38 | { 39 | PriceImprovementIndicator += v; 40 | } 41 | 42 | double rank() const 43 | { 44 | return (VenueTradingCost * 0.15) + 45 | (RouterHistTradingVolume * 0.2) + 46 | (MarketHistTradingVolume * 0.1) + 47 | (PriceImprovementIndicator * 0.15) + 48 | (ImmediateTradingActivity * 0.4); 49 | } 50 | 51 | private: 52 | double VenueTradingCost; // in basis points 53 | double RouterHistTradingVolume; // rHTV 54 | double MarketHistTradingVolume; // mHTV 55 | double ImmediateTradingActivity; // ITA 56 | double PriceImprovementIndicator; // PII 57 | 58 | }; 59 | #endif 60 | -------------------------------------------------------------------------------- /include/Order.h: -------------------------------------------------------------------------------- 1 | #ifndef ORDER_H 2 | #define ORDER_H 3 | #include "Side.h" 4 | #include "OrderType.h" 5 | #include "OrderStatus.h" 6 | #include "TimeInForce.h" 7 | #include 8 | #include 9 | 10 | 11 | class Order 12 | { 13 | public: 14 | explicit Order(SIDE side, std::string symbol, int orderQty, ORDER_TYPE orderType, double price, 15 | TIME_IN_FORCE timeInForce) : 16 | Side( side ), 17 | Symbol( symbol ), 18 | OrderQty( orderQty ), 19 | OrderType( orderType ), 20 | Price( price ), 21 | TimeInForce( timeInForce ) 22 | { 23 | MinQty = orderQty; 24 | CumQty = 0 ; 25 | OrdStatus = ORDER_STATUS::NEW; 26 | } 27 | 28 | Order(const Order & o) : 29 | Side( o.Side ), 30 | Symbol( o.Symbol ), 31 | OrderQty( o.OrderQty ), 32 | OrderType( o.OrderType ), 33 | Price( o.Price ), 34 | TimeInForce( o.TimeInForce ) 35 | { 36 | MinQty = o.OrderQty; 37 | CumQty = o.CumQty; 38 | OrdStatus = ORDER_STATUS::NEW; 39 | } 40 | 41 | int leavesQty() const 42 | { 43 | return OrderQty - CumQty; 44 | } 45 | 46 | bool is_terminal() const 47 | { 48 | if ( leavesQty() == 0 ) 49 | return true; 50 | 51 | return false; 52 | } 53 | 54 | std::string symbol() const 55 | { return Symbol; } 56 | 57 | void set_qty(int qty) 58 | { OrderQty = qty; } 59 | 60 | 61 | private: 62 | // --- fix fields --- 63 | SIDE Side; // 54=1 (buy), =2(sell) 64 | std::string Symbol; // 55 65 | int OrderQty; // 38 66 | ORDER_TYPE OrderType; // 40=1 (Mkt), 2(Limit) 67 | double Price; // 44 68 | TIME_IN_FORCE TimeInForce; // 59=3 (IOC) 69 | 70 | std::string Account; // 1 71 | std::string ClOrdID; // 11 72 | std::string MsgType; // 35=D 73 | std::string Text; // 58 74 | std::string TransactTime; // 60 75 | std::string TradeDate; // 75 76 | std::string ExDestination; // 100 77 | std::string MinQty; // 110 78 | 79 | // --- instance fields --- 80 | int CumQty; // filled qty 81 | ORDER_STATUS OrdStatus; 82 | }; 83 | #endif 84 | 85 | -------------------------------------------------------------------------------- /src/Main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Order.h" 6 | #include "VenueManager.h" 7 | #include "Venue.h" 8 | #include "SerialRouter.h" 9 | #include "Logger.h" 10 | using namespace std; 11 | 12 | 13 | // forward declarations 14 | VenueManager create_venue_manager(); 15 | 16 | /* 17 | * 18 | * Main program 19 | * 20 | */ 21 | int main(void) 22 | { 23 | Logger Log("Main"); 24 | 25 | // step 1 - create venue manager 26 | VenueManager vm = create_venue_manager(); 27 | 28 | 29 | // step 2 - create order: BUY IBM 100 @ market DAY 30 | Order prnt(SIDE::BUY, "IBM", 100, ORDER_TYPE::MARKET, 0.0, TIME_IN_FORCE::DAY); 31 | 32 | 33 | // step 3 - route order (serial way) 34 | SerialRouter sr(vm); 35 | 36 | // step 4 - time slice strategy 37 | int ncount = 0; 38 | while ( ! prnt.is_terminal() ) 39 | { 40 | Log.info("======================================="); 41 | Log.info("timeslice:", ++ncount); 42 | sr.route( prnt ); 43 | Log.info("======================================="); 44 | std::this_thread::sleep_for(std::chrono::milliseconds( 5 * 1000 )); 45 | } 46 | 47 | 48 | Log.info("done."); 49 | } 50 | 51 | /* 52 | * Create Venue Manager 53 | */ 54 | VenueManager create_venue_manager() 55 | { 56 | VenueRank vr1(0.1, 0.5, 0.1, 0.5, 0.5); 57 | VenueRank vr2(0.2, 0.5, 0.3, 0.4, 0.2); 58 | VenueRank vr3(0.3, 0.5, 0.5, 0.3, 0.2); 59 | VenueRank vr4(0.4, 0.5, 0.4, 0.2, 0.1); 60 | 61 | vector venues; 62 | 63 | Venue v1( "DPa", true, {"IBM", "GOOG"} ); 64 | v1.update_rank("IBM", vr1); 65 | v1.update_rank("GOOG", vr2); 66 | venues.push_back( v1 ); 67 | 68 | Venue v2( "DPb", true, {"IBM", "GOOG"} ); 69 | v2.update_rank("IBM", vr3); 70 | v2.update_rank("GOOG", vr4); 71 | venues.push_back( v2 ); 72 | 73 | Venue v3( "DPc", true, {"IBM", "GOOG"} ); 74 | v3.update_rank("IBM", vr3); 75 | v3.update_rank("GOOG", vr3); 76 | venues.push_back( v3 ); 77 | 78 | Venue v4( "DPd", true, {"IBM", "GOOG", "MSFT"} ); 79 | v4.update_rank("IBM", vr3); 80 | v4.update_rank("GOOG", vr2); 81 | v4.update_rank("MSFT", vr1); 82 | venues.push_back( v4 ); 83 | 84 | VenueManager vm( venues ); 85 | return vm; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /include/Logger.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGGER_H 2 | #define LOGGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class Logger 11 | { 12 | public: 13 | enum class LEVEL {DEBUG, INFO, WARN, ERROR}; 14 | 15 | explicit Logger(const std::string & clz) : clazz(clz) 16 | { } 17 | 18 | void info(const std::string & msg) 19 | { log(LEVEL::INFO, msg); } 20 | 21 | 22 | void info(const std::string & msg, const std::string &x) 23 | { log(LEVEL::INFO, msg, x); } 24 | 25 | 26 | void info(const std::string & msg, int v) 27 | { log(LEVEL::INFO, msg, to_string(v)); } 28 | 29 | 30 | void info(const std::string & msg, double v) 31 | { log(LEVEL::INFO, msg, to_string(v)); } 32 | 33 | void info(const std::string & msg, const std::vector v) 34 | { log(LEVEL::INFO, msg, to_string(v)); } 35 | 36 | 37 | void debug(const std::string & msg) 38 | { log(LEVEL::DEBUG, msg); } 39 | 40 | 41 | void warn(const std::string & msg) 42 | { log(LEVEL::DEBUG, msg); } 43 | 44 | 45 | void error(const std::string & msg) 46 | { log(LEVEL::ERROR, msg); } 47 | 48 | void error(const std::string & msg, const std::string & s) 49 | { log(LEVEL::ERROR, msg, s); } 50 | 51 | 52 | private: 53 | std::string clazz; 54 | 55 | 56 | void log (const LEVEL level, const std::string & msg, const std::string & o1 = "") 57 | { 58 | switch( level ) 59 | { 60 | case LEVEL::DEBUG: 61 | std::cout << "[DEBUG] "; break; 62 | case LEVEL::INFO: 63 | std::cout << "[INFO] "; break; 64 | case LEVEL::WARN: 65 | std::cout << "[WARN] "; break; 66 | case LEVEL::ERROR: 67 | std::cout << "[ERROR] "; break; 68 | default: 69 | std::cout << "[NO LEVEL]"; 70 | } 71 | 72 | std::cout << clazz << " - " << msg << " " << o1 << std::endl; 73 | } 74 | 75 | // hack since std::to_string() not supported 76 | std::string to_string(int v) 77 | { 78 | std::ostringstream ss; 79 | ss << v; 80 | return ss.str(); 81 | } 82 | 83 | std::string to_string(double v) 84 | { 85 | std::ostringstream ss; 86 | ss << v; 87 | return ss.str(); 88 | } 89 | 90 | std::string to_string(std::vector v) 91 | { 92 | std::ostringstream ss; 93 | for (auto i : v) 94 | ss << i << ","; 95 | return ss.str(); 96 | } 97 | 98 | 99 | }; 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/VenueManager.cpp: -------------------------------------------------------------------------------- 1 | #include "Venue.h" 2 | #include "VenueManager.h" 3 | #include "Order.h" 4 | #include "Execution.h" 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | /* 11 | * Add a venue 12 | */ 13 | void VenueManager::add_venue(const Venue & venue) 14 | { 15 | Log.info("adding venue:", venue.name()); 16 | Venues.push_back( venue ); 17 | } 18 | 19 | 20 | /* 21 | * Remove a venue 22 | */ 23 | void VenueManager::remove_venue(Venue & venue) 24 | { 25 | Log.info("removing venue:", venue.name()); 26 | if (Venues.empty()) 27 | return; 28 | 29 | for ( auto it = Venues.begin(); it != Venues.end(); ) 30 | { 31 | Venue v = *it; 32 | if ( v.name() == venue.name() ) 33 | { 34 | it = Venues.erase( it ); 35 | Log.info("removed:", v.name()); 36 | } 37 | else 38 | ++it; 39 | } 40 | } 41 | 42 | 43 | /* 44 | * Return a list of Venues and execution probability that 45 | * can execute incoming order 46 | */ 47 | vector VenueManager::venues(const string & symbol) 48 | { 49 | vector venues = SymbolVenues[ symbol ]; 50 | if (venues.empty()) 51 | return venues; 52 | 53 | vector rankings; 54 | double totalRank = 0.0; 55 | 56 | for (auto v : venues) 57 | { 58 | VenueRank vr = v.ranking( symbol ); 59 | totalRank += vr.rank(); 60 | } 61 | 62 | for (auto v : venues) 63 | { 64 | VenueRank vr = v.ranking( symbol ); 65 | double probability = vr.rank() / totalRank; 66 | v.set_exec_prob( probability ); 67 | Log.info("add ranking for venue:", v.name()); 68 | rankings.push_back(v); 69 | } 70 | 71 | return rankings; 72 | } 73 | 74 | 75 | /* 76 | * Internally segregate Venues by symbol 77 | */ 78 | void VenueManager::init() 79 | { 80 | for ( auto it1 = Venues.begin(); it1 != Venues.end(); ++it1 ) 81 | { 82 | Venue v = *it1; 83 | Log.info("v:", v.name()); 84 | 85 | vector symbols = v.symbols(); 86 | for ( auto it2 = symbols.begin(); it2 != symbols.end(); ++it2 ) 87 | { 88 | string symbol = *it2; 89 | vector venues = SymbolVenues[ symbol ]; 90 | Log.info("adding to symbol:", symbol); 91 | venues.push_back( v ); 92 | SymbolVenues[ symbol ] = venues; 93 | } 94 | } 95 | } 96 | 97 | 98 | /* 99 | * Send Order to a Venue (Market) 100 | */ 101 | void VenueManager::send_order(const Venue & venue, const Order & order) 102 | { 103 | Log.info("order sent to venue:", venue.name()); 104 | } 105 | 106 | /* 107 | * Process Ack/Fill from Venue (Market) 108 | */ 109 | void VenueManager::process_exec(const Execution & exec) 110 | { 111 | Log.info("recevied exec:", exec.exec_id()); 112 | } 113 | --------------------------------------------------------------------------------