WU Trading Library 0.2.0
A backtesting and trading strategy library
Loading...
Searching...
No Matches
sharpe.c
Go to the documentation of this file.
1/**
2 * The Sharpe Ratio measures risk-adjusted return by comparing excess return
3 * (over risk-free rate) to total volatility (standard deviation).
4 *
5 * Formula: Sharpe = (R_p - R_f) / σ_p
6 * where:
7 *
8 * R_p = mean portfolio return (annualized)
9 * R_f = risk-free rate (annualized)
10 * σ_p = portfolio standard deviation (annualized)
11 */
12
13#include <stdlib.h>
14#include <math.h>
15#include <stdio.h>
16#include "wu.h"
17
18/**
19 * Minimum number of observations required for statistically meaningful
20 * Sharpe ratio calculation. Below this threshold, the ratio is unreliable.
21 */
22#define SHARPE_MIN_OBSERVATIONS 30
23
24/**
25 * Updates the Sharpe Ratio calculation with a new portfolio value.
26 *
27 * @param self The Sharpe Ratio object
28 * @param perf Performance update containing portfolio value and timestamp
29 * @return The updated Sharpe Ratio value, or NAN if insufficient data
30 */
31static double wu_sharpe_ratio_update(WU_SharpeRatio self,
33 if (!self) return NAN;
34
35 double portfolio_value = perf.portfolio_value;
36
37 /* initialize on first observation */
38 if (self->count == 0) {
39 self->start_time = perf.timestamp.mark;
40 self->time_unit = perf.timestamp.units;
41 self->prev_value = portfolio_value;
42 self->count++;
43 self->value = NAN;
44 return self->value;
45 }
46
47 /* calculate simple return from previous period */
48 double ret = (portfolio_value - self->prev_value) / self->prev_value;
49 self->prev_value = portfolio_value;
50 self->end_time = perf.timestamp.mark;
51 self->count++;
52
53 /* update running statistics */
54 double mean = wu_indicator_update(self->mean, ret);
55 double stdev = wu_indicator_update(self->stdev, ret);
56
57 /* need minimum observations for reliable calculation */
58 if (self->count < SHARPE_MIN_OBSERVATIONS) {
59 self->value = NAN;
60 return self->value;
61 }
62
63 /* validate standard deviation */
64 if (isnan(stdev) || stdev <= 0.0) {
65 self->value = NAN;
66 return self->value;
67 }
68
69 /* calculate annualization factor */
70 double annualization_factor = wu_annualization_factor(
71 perf.timestamp.units);
72 double periods_elapsed = self->end_time - self->start_time;
73
74 /* avoid division by zero or negative time */
75 if (periods_elapsed <= 0) {
76 self->value = NAN;
77 return self->value;
78 }
79
80 double periods_per_year = (annualization_factor * self->count)
81 / periods_elapsed;
82 if (periods_per_year <= 0) {
83 self->value = NAN;
84 return self->value;
85 }
86
87 double annualized_stdev = stdev * sqrt(periods_per_year);
88 double per_period_rf = self->risk_free_rate / periods_per_year;
89 self->value = (mean - per_period_rf) / annualized_stdev;
90 return self->value;
91}
92
93/**
94 * Frees resources allocated by the Sharpe Ratio object.
95 */
96static void wu_sharpe_ratio_free(WU_SharpeRatio self) {
97 if (!self) return;
98 wu_indicator_delete(self->mean);
99 wu_indicator_delete(self->stdev);
100 free(self);
101}
102
103/**
104 * Creates a new Sharpe Ratio calculator.
105 */
106WU_SharpeRatio wu_sharpe_ratio_new(double initial_value,
107 double risk_free_rate) {
108 WU_SharpeRatio sr = malloc(sizeof(struct WU_SharpeRatio_));
109 if (!sr) return NULL;
110
111 sr->mean = wu_mean_new();
112 if (!sr->mean) {
113 fprintf(stderr, "Sharpe Ratio Error: mean object creation failed\n");
114 free(sr);
115 return NULL;
116 }
117
118 sr->stdev = wu_stdev_new(1); /* Sample standard deviation (dof=1) */
119 if (!sr->stdev) {
120 fprintf(stderr, "Sharpe Ratio Error: stdev object creation failed\n");
121 wu_indicator_delete(sr->mean);
122 free(sr);
123 return NULL;
124 }
125
126 sr->risk_free_rate = risk_free_rate;
127 sr->initial_value = initial_value;
128 sr->value = NAN;
129 sr->prev_value = initial_value;
130 sr->count = 0;
131 sr->start_time = 0;
132 sr->end_time = 0;
133 sr->time_unit = WU_TIME_UNIT_SECONDS;
134 sr->update = wu_sharpe_ratio_update;
135 sr->delete = wu_sharpe_ratio_free;
136
137 return sr;
138}
#define wu_indicator_delete(indicator)
Delete the indicator and free any resources allocated by it.
Definition indicators.h:56
#define wu_indicator_update(indicator, value)
Header file for technical indicators.
Definition indicators.h:41
WU_StDev wu_stdev_new(int dof)
Creates a new standard deviation indicator.
Definition var.c:49
WU_Mean wu_mean_new(void)
Creates a new WU_Mean indicator.
Definition mean.c:15
#define SHARPE_MIN_OBSERVATIONS
The Sharpe Ratio measures risk-adjusted return by comparing excess return (over risk-free rate) to to...
Definition sharpe.c:22
WU_SharpeRatio wu_sharpe_ratio_new(double initial_value, double risk_free_rate)
Creates a new Sharpe Ratio calculator.
Definition sharpe.c:106
static double wu_sharpe_ratio_update(WU_SharpeRatio self, WU_PerformanceUpdate perf)
Updates the Sharpe Ratio calculation with a new portfolio value.
Definition sharpe.c:31
static void wu_sharpe_ratio_free(WU_SharpeRatio self)
Frees resources allocated by the Sharpe Ratio object.
Definition sharpe.c:96
Performance Update - value and timestamp for performance metric calculations.
Definition indicators.h:239
WU_TimeStamp timestamp
Definition indicators.h:241
Sharpe ratio is the relation between the risk-free rate discounted retuns and the volatility of an in...
Definition stats.h:12
int64_t mark
Definition timeutils.h:22
WU_TimeUnit units
Definition timeutils.h:23
@ WU_TIME_UNIT_SECONDS
Definition timeutils.h:11
double wu_annualization_factor(WU_TimeUnit unit)
Returns the number of units (seconds, millis, micros, or nanos) contained in a year.
Definition timeutils.c:3