diff --git a/internal/calculator/factor_expression.service.go b/internal/calculator/factor_expression.service.go index 502380a..43d8db2 100644 --- a/internal/calculator/factor_expression.service.go +++ b/internal/calculator/factor_expression.service.go @@ -680,7 +680,7 @@ func (h factorMetricsHandler) PricePercentChange(pr *data.PriceCache, symbol str } func percentChange(end, start float64) float64 { - return ((end - start) / end) * 100 + return ((end - start) / start) * 100 } func (h factorMetricsHandler) AnnualizedStdevOfDailyReturns(ctx context.Context, pr *data.PriceCache, symbol string, start, end time.Time) (float64, error) { diff --git a/internal/calculator/metrics.service.go b/internal/calculator/metrics.service.go index 626d178..5a0d3db 100644 --- a/internal/calculator/metrics.service.go +++ b/internal/calculator/metrics.service.go @@ -54,7 +54,7 @@ func CalculateMetrics(backtestResults []BacktestResult, relevantTradingDays []ti numYears := numHours / (365 * 24) annualizedReturn := math.Pow((endValue/startValue), 1/numYears) - 1 - sharpeRatio := annualizedReturn / stdev + sharpeRatio := annualizedReturn / annualizedStdev return &CalculateMetricsResult{ AnnualizedStdev: annualizedStdev, diff --git a/internal/calculator/percent_change_test.go b/internal/calculator/percent_change_test.go new file mode 100644 index 0000000..20e116d --- /dev/null +++ b/internal/calculator/percent_change_test.go @@ -0,0 +1,55 @@ +package calculator + +import ( + "math" + "testing" +) + +func Test_percentChange(t *testing.T) { + tests := []struct { + name string + end float64 + start float64 + expected float64 + }{ + { + name: "simple increase", + end: 110, + start: 100, + expected: 10.0, + }, + { + name: "simple decrease", + end: 90, + start: 100, + expected: -10.0, + }, + { + name: "no change", + end: 100, + start: 100, + expected: 0.0, + }, + { + name: "double", + end: 200, + start: 100, + expected: 100.0, + }, + { + name: "50 percent drop", + end: 50, + start: 100, + expected: -50.0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := percentChange(tt.end, tt.start) + if math.Abs(got-tt.expected) > 0.0001 { + t.Errorf("percentChange(%v, %v) = %v, want %v", tt.end, tt.start, got, tt.expected) + } + }) + } +} diff --git a/internal/data/percent_change_test.go b/internal/data/percent_change_test.go new file mode 100644 index 0000000..ebf2d15 --- /dev/null +++ b/internal/data/percent_change_test.go @@ -0,0 +1,49 @@ +package data + +import ( + "math" + "testing" +) + +func Test_percentChange(t *testing.T) { + tests := []struct { + name string + end float64 + start float64 + expected float64 + }{ + { + name: "simple increase", + end: 110, + start: 100, + expected: 10.0, + }, + { + name: "simple decrease", + end: 90, + start: 100, + expected: -10.0, + }, + { + name: "no change", + end: 100, + start: 100, + expected: 0.0, + }, + { + name: "double", + end: 200, + start: 100, + expected: 100.0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := percentChange(tt.end, tt.start) + if math.Abs(got-tt.expected) > 0.0001 { + t.Errorf("percentChange(%v, %v) = %v, want %v", tt.end, tt.start, got, tt.expected) + } + }) + } +} diff --git a/internal/data/price.service.go b/internal/data/price.service.go index db51c98..a001173 100644 --- a/internal/data/price.service.go +++ b/internal/data/price.service.go @@ -97,7 +97,7 @@ func (pr *PriceCache) Get(symbol string, date time.Time) (float64, error) { } func percentChange(end, start float64) float64 { - return ((end - start) / end) * 100 + return ((end - start) / start) * 100 } func stdevsFromPriceMap(minMaxMap map[string]*minMax, priceCache map[string]map[string]float64, stdevInputs []LoadStdevCacheInput, tradingDays []time.Time) (*stdevCache, error) {