55// ---------------------------------------
66
77#include " operations.hpp"
8- // std headers
9- #include < iostream>
108#include < vector>
119#include < memory>
12- #include < optional>
1310#include < stdexcept>
1411#include < string>
15- #include < utility>
16- #include < iomanip>
17- #include < cstdio>
18- #include < ctime>
19- #include < boost/decimal.hpp>
2012#include " tradeManager.hpp"
21- #include " exitRules .hpp"
22- #include " models/symbolScale .hpp"
13+ #include " reviewStopAndLimit .hpp"
14+ #include " reporting .hpp"
2315#include " strategies/strategy.hpp"
2416#include " strategies/randomStrategy.hpp"
2517
2618namespace {
2719
28- // Walk every active trade, close any whose SL/TP has been hit on this
29- // tick. Two-phase to avoid invalidating the map iterator while erasing.
30- void reviewStopAndLimit (TradeManager& tradeManager, const PriceData& tick) {
31- const auto & openTrades = tradeManager.getActiveTrades ();
32- if (openTrades.empty ()) return ;
33-
34- std::vector<std::pair<std::string, boost::decimal::decimal64_t >> toClose;
35- toClose.reserve (openTrades.size ());
36- for (const auto & [id, trade] : openTrades) {
37- if (auto exitPrice = trading::exit_rules::checkExit (trade, tick)) {
38- toClose.emplace_back (id, *exitPrice);
39- }
40- }
41- for (const auto & [id, exitPrice] : toClose) {
42- tradeManager.closeTrade (id, exitPrice, tick);
43- }
44- }
45-
4620// Adding a new strategy means adding one branch here; nothing else in
4721// Operations needs to know about the concrete type.
4822std::unique_ptr<IStrategy>
@@ -69,13 +43,9 @@ void Operations::run(const std::vector<PriceData>& ticks,
6943 // Close any trade whose stop-loss or take-profit fired on this tick
7044 // before we consider opening a new one — otherwise an exit and an
7145 // entry could race within the same tick.
72- reviewStopAndLimit (*tradeManager, tick);
46+ trading:: reviewStopAndLimit (*tradeManager, tick);
7347
74- size_t openTrades = tradeManager->reviewAccount ();
75-
76- // only open a trade if there is zero
77- if (openTrades == 0 ) {
78- // optional is false
48+ if (!tradeManager->hasActiveTradeForSymbol (tick.symbol )) {
7949 if (auto signal = strategy->decide (tick)) {
8050 tradeManager->openTrade (tick,
8151 tradingVars.TRADING_SIZE ,
@@ -92,51 +62,5 @@ void Operations::run(const std::vector<PriceData>& ticks,
9262 strategy->during (tick, *tradeManager);
9363 }
9464
95- std::cout << " Final PnL: " << std::fixed << std::setprecision (2 ) << tradeManager->calculatePnl () << std::endl;
96-
97- const auto & activeTrades = tradeManager->getActiveTrades ();
98- const auto & closedTrades = tradeManager->getClosedTrades ();
99-
100- const std::size_t openedCount = activeTrades.size () + closedTrades.size ();
101- const std::size_t closedCount = closedTrades.size ();
102-
103- std::size_t openedLong = 0 ;
104- std::size_t openedShort = 0 ;
105- for (const auto & [id, trade] : activeTrades) {
106- if (trade.direction == Direction::LONG ) ++openedLong;
107- else ++openedShort;
108- }
109-
110- std::size_t closedLong = 0 ;
111- std::size_t closedShort = 0 ;
112- std::size_t winners = 0 ;
113- std::size_t losers = 0 ;
114- std::size_t breakeven = 0 ;
115- boost::decimal::decimal64_t pnlSum{0 };
116- const boost::decimal::decimal64_t zero{0 };
117- for (const auto & trade : closedTrades) {
118- if (trade.direction == Direction::LONG ) ++closedLong;
119- else ++closedShort;
120- if (trade.pnl > zero) ++winners;
121- else if (trade.pnl < zero) ++losers;
122- else ++breakeven;
123- pnlSum += trade.pnl ;
124- }
125- openedLong += closedLong;
126- openedShort += closedShort;
127-
128- std::cout << " Trades opened: " << openedCount
129- << " (LONG: " << openedLong << " , SHORT: " << openedShort << " )" << std::endl;
130- std::cout << " Trades closed: " << closedCount
131- << " (LONG: " << closedLong << " , SHORT: " << closedShort << " )" << std::endl;
132- std::cout << " Winners: " << winners
133- << " Losers: " << losers
134- << " Breakeven: " << breakeven << std::endl;
135- if (closedCount == 0 ) {
136- std::cout << " Average PnL per closed trade: n/a (0 closed)" << std::endl;
137- } else {
138- const auto avgPnl = pnlSum / boost::decimal::decimal64_t {static_cast <long long >(closedCount)};
139- std::cout << " Average PnL per closed trade: "
140- << std::fixed << std::setprecision (2 ) << avgPnl << std::endl;
141- }
65+ Reporting::summarise (*tradeManager);
14266}
0 commit comments