|
| 1 | +// Backtesting Engine in C++ |
| 2 | +// |
| 3 | +// (c) 2026 Ryan McCaffery | https://mccaffers.com |
| 4 | +// This code is licensed under MIT license (see LICENSE.txt for details) |
| 5 | +// --------------------------------------- |
| 6 | + |
| 7 | +#pragma once |
| 8 | +#include <cstddef> |
| 9 | +#include <optional> |
| 10 | +#include "models/priceData.hpp" |
| 11 | +#include "models/trade.hpp" |
| 12 | + |
| 13 | +// Forward declaration. We only refer to `TradeManager` by reference in |
| 14 | +// this header, so the compiler doesn't need its full definition here — |
| 15 | +// just to know "it's a class". Pulling in the full header would drag |
| 16 | +// every TradeManager dependency into every strategy. C# doesn't really |
| 17 | +// have an equivalent because it resolves types at the assembly level |
| 18 | +// rather than per file, but in C++ this is a standard way to keep |
| 19 | +// header dependencies (and compile times) under control. |
| 20 | +class TradeManager; |
| 21 | + |
| 22 | +// Abstract base class that every concrete strategy implements. |
| 23 | +// |
| 24 | +// C# parallels for readers from a C# background: |
| 25 | +// - This is the C++ equivalent of a C# `interface`. C++ has no |
| 26 | +// dedicated `interface` keyword, so you express it as a class |
| 27 | +// whose methods are all pure virtual (the `= 0` suffix). The |
| 28 | +// `I` prefix is borrowed from C# — C++ has no fixed convention, |
| 29 | +// but it's a useful hint because C++ classes routinely mix |
| 30 | +// virtual and concrete methods, so "is this an interface?" isn't |
| 31 | +// always obvious from the keyword alone. |
| 32 | +// - `virtual ~IStrategy() = default;` is mandatory. If you ever |
| 33 | +// delete a derived strategy through an `IStrategy*`, a non-virtual |
| 34 | +// destructor would skip the derived destructor and leak resources. |
| 35 | +// C# handles this for you; in C++ you opt in. |
| 36 | +// - `= 0` makes a method pure virtual, which makes the class |
| 37 | +// abstract — you cannot instantiate `IStrategy` directly, only |
| 38 | +// concrete subclasses. Same behaviour as a C# interface. |
| 39 | +// - Derived classes annotate their implementations with `override` |
| 40 | +// (see `RandomStrategy`). It's optional in C++ but catches |
| 41 | +// signature typos at compile time, exactly like C#'s `override`. |
| 42 | +class IStrategy { |
| 43 | +public: |
| 44 | + virtual ~IStrategy() = default; |
| 45 | + |
| 46 | + // Entry signal. Returns `std::nullopt` to mean "no trade". |
| 47 | + // Non-const because some implementations (e.g. RandomStrategy) |
| 48 | + // mutate internal RNG state on each call. |
| 49 | + virtual std::optional<Direction> decide(const PriceData& tick) = 0; |
| 50 | + |
| 51 | + // Called every tick. Receives the TradeManager by mutable |
| 52 | + // reference so strategies can both inspect open positions |
| 53 | + // (`tradeManager.getActiveTrades()`) and act on them |
| 54 | + // (`closeTrade`, future scale/adjust hooks). A reference signals |
| 55 | + // "borrow, don't own" — the strategy must not delete it. The C# |
| 56 | + // analogue is just passing the manager as a parameter; C# has no |
| 57 | + // distinction between reference and pointer so the by-ref nature |
| 58 | + // is implicit there. |
| 59 | + virtual void during(std::size_t tickValue, |
| 60 | + const PriceData& price, |
| 61 | + TradeManager& tradeManager) = 0; |
| 62 | +}; |
0 commit comments