Skip to content

Conversation

@hwde
Copy link
Contributor

@hwde hwde commented Sep 12, 2025

Describe Request

This fix #274, WMA calculation, which formulas wasn't correct implemented.

Fixed #274

Change Type

What is the type of this change.

Correct formular of WMA is, i.e. WMA(5):

(P1 * 5) + (P2 * 4) + (P3 * 3) + (P4 * 2) + (P5 * 1) / (5 + 4 + 3 + 2 + 1).
This makes it perfect for the divisor to be calulated only one (gauss formula: (n * (n + 1) / 2).

The testdata has been new caclulated manually via Excel, a WMA(3) and a WMA(5) … to be safe.

Summary by CodeRabbit

  • Bug Fixes

    • Corrected Weighted Moving Average calculation to use standard weighting and proper normalization, improving accuracy.
  • Improvements

    • Added input validation to prevent creating WMA with invalid periods, yielding clearer errors for bad configuration.
  • Tests

    • Expanded unit tests to validate WMA behavior for multiple periods (3 and 5) to increase reliability.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 12, 2025

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between a16a236 and ba94b67.

⛔ Files ignored due to path filters (3)
  • strategy/volatility/testdata/super_trend_strategy.csv is excluded by !**/*.csv
  • trend/testdata/hma.csv is excluded by !**/*.csv
  • volatility/testdata/super_trend.csv is excluded by !**/*.csv
📒 Files selected for processing (2)
  • momentum/README.md (2 hunks)
  • trend/README.md (2 hunks)
 __________________________________________________
< Brb...ordering more GPUs. CPUs are so last year. >
 --------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ

Tip

CodeRabbit can scan for known vulnerabilities in your dependencies using OSV Scanner.

OSV Scanner will automatically detect and report security vulnerabilities in your project's dependencies. No additional configuration is required.

Walkthrough

Updates WMA computation to use weights N..1 with proper normalization (divisor N*(N+1)/2), adds input validation that panics when period ≤ 0, and expands tests to validate WMA for periods 3 and 5. No public API signature changes.

Changes

Cohort / File(s) Summary
WMA algorithm update
trend/wma.go
Added validation (panic if period ≤ 0). Rewrote Compute to precompute divisor as T(N*(N+1)/2), apply weights N..1 (sum += window.At(i) * T(w.Period - i)), and return sum/divisor. Maintains ring buffer and channel Map/Skip flow. No exported signature changes.
Tests for multiple periods
trend/wma_test.go
Extended TestWma to validate periods 3 and 5 in one test: added separate expected fields for Wma3/Wma5, created wma3/wma5 calculators, advanced expectations by each IdlePeriod, and compared rounded outputs for both periods. TestWmaString unchanged.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant New as NewWmaWith
  participant Wma as Wma[T]
  participant Compute as Compute
  participant Ring as Ring[T]
  participant Helper as helper (Map/Skip)

  Caller->>New: NewWmaWith(period)
  alt period <= 0
    New-->>Caller: panic("period must be > 0")
  else
    New-->>Caller: Wma instance
  end

  Caller->>Compute: Compute(values <-chan T)
  Compute->>Ring: NewRing(period)
  Compute->>Helper: Map(values, fn)
  loop for each value
    Helper->>Compute: value
    Compute->>Ring: Put(value)
    alt Ring not full
      Compute-->>Helper: emit 0
    else Ring full
      Note right of Compute: divisor = N*(N+1)/2
      Compute->>Ring: At(i) for i=0..N-1
      Note right of Compute: sum += window.At(i) * (N - i)
      Compute-->>Helper: emit sum/divisor
    end
  end
  Compute->>Helper: Skip(wmas, IdlePeriod)
  Helper-->>Caller: <-chan T
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I weighed the waves from N down to one,
I guard the period — if it's wrong, I'm done.
Three and five I check with cheerful hops,
Sum, divide, emit — then off to my crops.
A rabbit's nod to tests that pass —🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The title "fix the calculation of the WMA" directly describes the primary change in this PR (correcting the WMA implementation) and is concise and focused for reviewers scanning history. It avoids extraneous detail and accurately reflects the main intent of the changeset.
Linked Issues Check ✅ Passed The Compute implementation now applies integer weights in the correct order (weights N..1 via T(w.Period - i)) and divides by the triangular-number divisor n*(n+1)/2, replacing the previous incorrect scaling; this matches the correction requested in issue #274. Unit tests were updated to validate WMA(3) and WMA(5) against recalculated expected values and input validation for invalid periods was added, covering the specified objectives and edge cases. These changes fulfill the coding requirements described in the linked issue.
Out of Scope Changes Check ✅ Passed The modifications are limited to trend/wma.go and trend/wma_test.go and focus on correcting the WMA computation, adding input validation, and updating tests; no other files or public API signatures were changed. There are no unrelated features, refactors, or extraneous changes present in the provided summary. No out-of-scope changes were detected.
Description Check ✅ Passed The description explains the problem being fixed, references Fixed #274, documents the corrected WMA formula and that testdata were recalculated, so the core information required by the template is present. However the "Change Type" template field is not populated and currently shows the prompt text rather than a chosen value. Please populate the "Change Type" (for example "Bugfix") and tidy minor wording/formatting to fully match the repository template.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

This fix cinar#274, WMA calculation was wrong, correct formular is, i.e. WMA(5):

(P1 * 5) + (P2 * 4) + (P3 * 3) + (P4 * 2) + (P5 * 1) / (5 + 4 + 3 + 2 + 1).

This makes it perfect for the divisor to be calulated only one (gauss formula: (n * (n + 1) / 2).

The testdata has been new caclulated manually via Excel, a WMA(3) and a WMA(5) … to be safe.

Signed-off-by: Heiko Weber <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
trend/wma.go (1)

13-17: Doc formula is incorrect and conflicts with the new implementation.

Update to the standard triangular-weighted form.

-//
-//	WMA = ((Value1 * 1/N) + (Value2 * 2/N) + ...) / 2
+//
+//	WMA = (P1*N + P2*(N-1) + ... + PN*1) / (N*(N+1)/2)
🧹 Nitpick comments (4)
trend/wma.go (2)

35-35: Minor literal nit: use an integer literal for 2.

Keeps conversions cleaner across T.

-divisor := T(w.Period) * (T(w.Period) + T(1)) / T(2.0)
+divisor := T(w.Period) * (T(w.Period) + T(1)) / T(2)

50-50: Guard against integer instantiation of T (precision loss).

If helper.Number allows ints, sum/divisor will truncate. Either constrain T to floats or do the division in float and cast back.

Option A (preferred): restrict T to floats in this indicator.

// in this file or via a shared constraint
type floatish interface{ ~float32 | ~float64 }
type Wma[T floatish] struct{ Period int }

Option B: compute in float64 and cast (only if T is convertible to float64 across the codebase).

- return sum / divisor
+ return T(float64(sum) / float64(divisor))
trend/wma_test.go (2)

38-39: Rounding precision check.

Ensure testdata/wma.csv values are at 3 decimals; otherwise, round expected too for strict equality.

-actualWma3 = helper.RoundDigits(actualWma3, 3)
-actualWma5 = helper.RoundDigits(actualWma5, 3)
+actualWma3 = helper.RoundDigits(actualWma3, 3)
+actualWma5 = helper.RoundDigits(actualWma5, 3)
+// if CSV has more precision, also round expected:
+// expectedWma3 = helper.RoundDigits(expectedWma3, 3)
+// expectedWma5 = helper.RoundDigits(expectedWma5, 3)

41-45: Verify helper.CheckEquals signature for multi-pair comparison.

If CheckEquals doesn’t accept 4 streams (two pairs), split into two asserts.

-err = helper.CheckEquals(actualWma3, expectedWma3, actualWma5, expectedWma5)
+if err = helper.CheckEquals(actualWma3, expectedWma3); err != nil {
+  t.Fatal(err)
+}
+if err = helper.CheckEquals(actualWma5, expectedWma5); err != nil {
+  t.Fatal(err)
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99dd399 and d2ecac9.

⛔ Files ignored due to path filters (1)
  • trend/testdata/wma.csv is excluded by !**/*.csv
📒 Files selected for processing (2)
  • trend/wma.go (3 hunks)
  • trend/wma_test.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
trend/wma_test.go (4)
helper/csv.go (1)
  • ReadFromCsvFile (310-317)
trend/wma.go (1)
  • NewWmaWith (23-30)
helper/skip.go (1)
  • Skip (15-30)
trend/vwma_test.go (1)
  • TestVwma (14-42)
🔇 Additional comments (5)
trend/wma.go (2)

24-26: Input validation LGTM.

Panic on non-positive period is consistent and keeps invalid configs out early.


46-48: Confirm ring ordering to ensure newest gets the highest weight.

This assumes window.At(0) returns the most recent value (weight N), decreasing to 1 at At(N-1). If At(0) is the oldest, the weights are reversed.

If At(0) is oldest, switch to:

- v := window.At(i)
- sum += v * T(w.Period-i)
+ v := window.At(i)
+ sum += v * T(i+1) // oldest=1 ... newest=N
trend/wma_test.go (3)

14-14: Clear test description. LGTM.


18-20: Schema aligns with CSV-driven expectations.

Fields Wma3/Wma5 mirror per-period expectations.


27-30: Channel duplication/map setup looks good.

Efficiently tees Close into two streams; expected channels sourced independently.

hwde and others added 3 commits September 13, 2025 18:32
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Heiko Weber <[email protected]>
@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 66.66667% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.79%. Comparing base (8ff5e12) to head (83c72fc).

Files with missing lines Patch % Lines
trend/wma.go 66.66% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #279      +/-   ##
==========================================
- Coverage   91.81%   91.79%   -0.03%     
==========================================
  Files         191      191              
  Lines        6794     6797       +3     
==========================================
+ Hits         6238     6239       +1     
- Misses        493      494       +1     
- Partials       63       64       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cinar cinar merged commit ca7b4cc into cinar:master Sep 14, 2025
2 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Sep 14, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WMA calculation formula error

3 participants