14 int64_t init_timestamp = 0;
15 int64_t last_timestamp = 0;
16 double init_cash = 0.0;
17 double init_price = std::nan(
"");
18 double last_price = std::nan(
"");
19 std::vector<std::pair<int64_t, double>> equity_curve;
20 std::vector<Trade> trades;
21 uint16_t num_trades = 0;
22 uint16_t num_stop_loss = 0;
23 uint16_t num_take_profit = 0;
24 double total_costs = 0.0;
27 void initialize(int64_t timestamp,
double cash,
double price) {
28 init_timestamp = timestamp;
29 last_timestamp = timestamp;
33 equity_curve.emplace_back(timestamp, cash);
38 void record_equity(int64_t timestamp,
double total_value,
double price) {
39 last_timestamp = timestamp;
41 equity_curve.emplace_back(timestamp, total_value);
45 trades.push_back(
Trade{timestamp, 0, price, 0.0, quantity, 0.0,
false});
49 double open_price,
double close_price,
50 double profit,
bool is_stop_loss,
51 bool is_take_profit) {
52 if (is_stop_loss) ++num_stop_loss;
53 if (is_take_profit) ++num_take_profit;
54 trades.push_back(
Trade{0, timestamp, open_price, close_price, quantity,
60 void add_costs(
double cost) { total_costs += cost; }
64 for (
const auto& trade : trades) {
65 if (trade.closed && trade.profit > 0) ++wins;
72 for (
const auto& trade : trades) {
73 if (trade.closed && trade.profit <= 0) ++losses;
81 uint16_t total = wins + losses;
82 return total > 0 ?
static_cast<double>(wins) / total : 0.0;
85 void print_summary(std::ostream& os,
double curr_cash,
double holdings,
86 double qty,
double total_value)
const;
93 const std::vector<std::pair<int64_t, double>>& equity_curve) {
94 if (equity_curve.empty())
return 0.0;
96 double peak = equity_curve.front().second;
98 for (
const auto& point : equity_curve) {
99 if (point.second > peak) peak = point.second;
100 double dd = (peak - point.second) / peak;
101 if (dd > max_dd) max_dd = dd;
113 if (returns.size() < 2 || years <= 0.0)
return 0.0;
115 size_t n = returns.size();
116 double mean = std::accumulate(returns.begin(), returns.end(), 0.0) / n;
119 for (
double r : returns) {
120 var += (r - mean) * (r - mean);
123 double stddev = std::sqrt(var);
125 if (stddev <= 0.0)
return 0.0;
127 double periods_per_year =
static_cast<double>(n) / years;
128 return (mean / stddev) * std::sqrt(periods_per_year);
135 const std::vector<std::pair<int64_t, double>>& equity_curve) {
136 std::vector<double> returns;
137 if (equity_curve.size() < 2)
return returns;
139 returns.reserve(equity_curve.size() - 1);
140 for (
size_t i = 1; i < equity_curve.size(); ++i) {
141 double r = (equity_curve[i].second / equity_curve[i - 1].second) - 1.0;
142 returns.push_back(r);
151 const std::vector<std::pair<int64_t, double>>& equity_curve) {
153 if (equity_curve.empty())
return metrics;
155 double start_value = equity_curve.front().second;
156 double end_value = equity_curve.back().second;
160 if (equity_curve.size() >= 2) {
161 double seconds =
static_cast<double>(equity_curve.back().first -
162 equity_curve.front().first);
163 metrics.
years = seconds / (365.0 * 24.0 * 3600.0);
167 const double min_period_years = 30.0 / 365.0;
168 if (metrics.
years >= min_period_years) {
170 std::pow(end_value / start_value, 1.0 / metrics.
years) - 1.0;
178 if (equity_curve.size() >= 2) {
195 if (std::isnan(init_price) || init_price <= 0.0 ||
196 std::isnan(final_price) || final_price <= 0.0) {
200 metrics.
quantity = std::floor(init_cash / init_price);
205 const double min_period_years = 30.0 / 365.0;
206 if (years >= min_period_years) {
208 std::pow(metrics.
final_value / init_cash, 1.0 / years) - 1.0;
212 metrics.
valid =
true;
217 double holdings,
double qty,
218 double total_value)
const {
219 double profit_loss = total_value - init_cash;
221 os << std::fixed << std::setprecision(4) <<
"init_time:" << init_timestamp
222 <<
" curr_time:" << last_timestamp <<
" init_cash:" << init_cash
223 <<
" curr_cash:" << curr_cash <<
" num_trades:" << num_trades
226 <<
" win_rate:" <<
get_win_rate() <<
" num_stop_loss:" << num_stop_loss
227 <<
" num_take_profit:" << num_take_profit <<
" quantity:" << qty
228 <<
" holdings:" << holdings <<
" valuation:" << total_value
229 <<
" total_costs:" << total_costs <<
" profit:" << profit_loss;
232 double adjusted_total_return = (total_value / init_cash) - 1.0;
233 double adjusted_annual_return = 0.0;
234 bool has_adjusted_annual_return =
false;
236 const double min_period_years = 30.0 / 365.0;
237 if (perf.
years >= min_period_years) {
238 adjusted_annual_return =
239 std::pow(total_value / init_cash, 1.0 / perf.
years) - 1.0;
240 has_adjusted_annual_return =
true;
243 os <<
" total_return:" << adjusted_total_return;
245 if (has_adjusted_annual_return) {
246 os <<
" annual_return:" << adjusted_annual_return;
248 os <<
" annual_return:N/A";
252 last_price, perf.
years);
bool is_initialized() const
Definition stats.h:36
void record_trade_close(int64_t timestamp, double quantity, double open_price, double close_price, double profit, bool is_stop_loss, bool is_take_profit)
Definition stats.h:48
void add_costs(double cost)
Definition stats.h:60
uint16_t get_num_wins() const
Definition stats.h:62
void initialize(int64_t timestamp, double cash, double price)
Definition stats.h:27
void record_equity(int64_t timestamp, double total_value, double price)
Definition stats.h:38
void record_trade_open(int64_t timestamp, double quantity, double price)
Definition stats.h:44
void increment_trades()
Definition stats.h:58
uint16_t get_num_losses() const
Definition stats.h:70
void print_summary(std::ostream &os, double curr_cash, double holdings, double qty, double total_value) const
Definition stats.h:216
double get_win_rate() const
Definition stats.h:78
BuyAndHoldMetrics compute_buy_and_hold_metrics(double init_cash, double init_price, double final_price, double years)
Definition stats.h:189
PerformanceMetrics compute_performance_metrics(const std::vector< std::pair< int64_t, double > > &equity_curve)
Definition stats.h:150
std::vector< double > compute_returns(const std::vector< std::pair< int64_t, double > > &equity_curve)
Definition stats.h:134
double compute_max_drawdown(const std::vector< std::pair< int64_t, double > > &equity_curve)
Definition stats.h:92
double compute_sharpe_ratio(const std::vector< double > &returns, double years)
Definition stats.h:111
double final_value
Definition defs.h:202
double cash_left
Definition defs.h:201
double annual_return
Definition defs.h:204
bool has_annual_return
Definition defs.h:205
double total_return
Definition defs.h:203
bool valid
Definition defs.h:206
double quantity
Definition defs.h:200