Spaces:
Sleeping
Sleeping
File size: 3,947 Bytes
ba6114e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #pragma once
#include "core/types.hpp"
#include "core/order_book.hpp"
#include "risk/risk_manager.hpp"
#include "journal/journal.hpp"
#include "strategy/strategy.hpp"
#include <unordered_map>
#include <atomic>
#include <memory>
#include <mutex>
#include <deque>
#include <functional>
namespace hft {
struct BacktestResult {
std::string strategy_name;
int64_t ticks_processed = 0;
int64_t orders_submitted = 0;
int64_t orders_filled = 0;
int64_t orders_rejected = 0;
int64_t trades_count = 0;
double total_pnl = 0;
double realized_pnl = 0;
double unrealized_pnl = 0;
double max_drawdown = 0;
double sharpe = 0;
LatencyStats order_latency;
LatencyStats tick_latency;
double throughput_eps = 0;
std::vector<double> equity_curve;
std::vector<Trade> trades;
};
class ExchangeSimulator {
public:
explicit ExchangeSimulator(RiskLimits limits = {});
void add_symbol(const std::string& symbol);
struct SubmitResult {
bool approved;
std::string reject_reason;
std::vector<Trade> trades;
};
// Fix: Takes const reference to avoid scope expiration
SubmitResult submit_order(const Order& order, double market_price = 0.0);
bool cancel_order(const std::string& symbol, OrderId id);
bool modify_order(const std::string& symbol, OrderId id, Price new_price, Quantity new_qty);
void on_tick(const MarketDataTick& tick);
OrderBookSnapshot get_snapshot(const std::string& symbol, int depth = 10) const;
std::vector<std::string> symbols() const;
Position get_position(const std::string& symbol) const;
std::unordered_map<std::string, Position> all_positions() const;
double total_pnl() const;
RiskManager& risk() { return risk_; }
void set_trade_callback(TradeCallback cb) { trade_cb_ = std::move(cb); }
void set_order_callback(OrderCallback cb) { order_cb_ = std::move(cb); }
LatencyStats& order_latency() { return order_lat_; }
LatencyStats& tick_latency() { return tick_lat_; }
int64_t total_orders() const { return total_orders_.load(std::memory_order_relaxed); }
int64_t total_trades() const { return total_trades_.load(std::memory_order_relaxed); }
int64_t total_rejects() const { return total_rejects_.load(std::memory_order_relaxed); }
OrderId next_order_id() { return ++next_oid_; }
private:
std::unordered_map<std::string, std::unique_ptr<OrderBook>> books_;
// Fix: Correct key type and properly controls memory lifetime
std::unordered_map<OrderId, std::unique_ptr<Order>> order_store_;
RiskManager risk_;
BinaryJournal journal_;
mutable std::mutex mtx_;
TradeCallback trade_cb_;
OrderCallback order_cb_;
std::atomic<OrderId> next_oid_{1000};
LatencyStats order_lat_, tick_lat_;
// Fix: Atomic counters for thread-safe operations in main.cpp
std::atomic<int64_t> total_orders_{0};
std::atomic<int64_t> total_trades_{0};
std::atomic<int64_t> total_rejects_{0};
};
class Backtester {
public:
explicit Backtester(RiskLimits limits = {});
void set_strategy(std::unique_ptr<IStrategy> strategy);
void add_symbol(const std::string& symbol);
BacktestResult run(const std::vector<MarketDataTick>& ticks,
bool enable_journal = true,
const std::string& journal_path = "replay.journal");
private:
std::unique_ptr<IStrategy> strategy_;
std::unique_ptr<ExchangeSimulator> sim_;
RiskLimits limits_;
std::vector<std::string> symbols_;
void process_signals(const std::vector<StrategySignal>& sigs,
const MarketDataTick& tick,
BacktestResult& result,
std::unordered_map<OrderId, Order>& live_orders);
};
} // namespace hft
|