diff --git a/README.md b/README.md
index 24131a4..6863583 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,6 @@ The following list of indicators are currently supported by this package:
### 📈 Trend Indicators
- [Absolute Price Oscillator (APO)](trend/README.md#Apo)
-- [Alligator Indicator](trend/README.md#Alligator)
- [Aroon Indicator](trend/README.md#Aroon)
- [Balance of Power (BoP)](trend/README.md#Bop)
- [Chande Forecast Oscillator (CFO)](trend/README.md#Cfo)
@@ -50,6 +49,7 @@ The following list of indicators are currently supported by this package:
- [Moving Sum](trend/README.md#MovingSum)
- [Pivot Point](trend/README.md#PivotPoint)
- [Random Index (KDJ)](trend/README.md#Kdj)
+- [Rate of Change (ROC)](trend/README.md#Roc)
- [Stochastic](trend/README.md#Stochastic)
- [Slow Stochastic](trend/README.md#SlowStochastic)
- [Schaff Trend Cycle (STC)](trend/README.md#Stc)
@@ -76,15 +76,17 @@ The following list of indicators are currently supported by this package:
- [Elder-Ray Index](momentum/README.md#ElderRay)
- [Fisher Transform](momentum/README.md#Fisher)
- [Ichimoku Cloud](momentum/README.md#IchimokuCloud)
+- [Martin Pring's Special K](momentum/README.md#PringsSpecialK)
- [Percentage Price Oscillator (PPO)](momentum/README.md#Ppo)
- [Percentage Volume Oscillator (PVO)](momentum/README.md#Pvo)
-- [Martin Pring's Special K](momentum/README.md#PringsSpecialK)
+- [Qstick](momentum/README.md#Qstick)
- [Relative Strength Index (RSI)](momentum/README.md#Rsi)
- [Relative Vigor Index (RVI)](momentum/README.md#Rvi)
-- [Qstick](momentum/README.md#Qstick)
- [Stochastic Oscillator](momentum/README.md#StochasticOscillator)
- [Stochastic RSI](momentum/README.md#StochasticRsi)
- [TD Sequential](momentum/README.md#TdSequential)
+- [Ultimate Oscillator](momentum/README.md#UltimateOscillator)
+- [Williams R](momentum/README.md#WilliamsR)
### 🎢 Volatility Indicators
@@ -161,6 +163,7 @@ The following list of strategies are currently supported by this package:
- [RSI Strategy](strategy/momentum/README.md#RsiStrategy)
- [Stochastic RSI Strategy](strategy/momentum/README.md#StochasticRsiStrategy)
- [Triple RSI Strategy](strategy/momentum/README.md#TripleRsiStrategy)
+- [Williams R Strategy](strategy/momentum/README.md#WilliamsRStrategy)
### 🎢 Volatility Strategies
@@ -174,6 +177,7 @@ The following list of strategies are currently supported by this package:
- [Force Index Strategy](strategy/volume/README.md#ForceIndexStrategy)
- [Money Flow Index Strategy](strategy/volume/README.md#MoneyFlowIndexStrategy)
- [Negative Volume Index Strategy](strategy/volume/README.md#NegativeVolumeIndexStrategy)
+- [On-Balance Volume (OBV) Strategy](strategy/volume/README.md#ObvStrategy)
- [Percent Band and MFI Strategy](strategy/volume/README.md#PercentBandMFIStrategy)
- [Weighted Average Price Strategy](strategy/volume/README.md#WeightedAveragePriceStrategy)
diff --git a/helper/README.md b/helper/README.md
index c3e83c9..290ae75 100644
--- a/helper/README.md
+++ b/helper/README.md
@@ -167,7 +167,7 @@ const (
func Abs[T Number](c <-chan T) <-chan T
```
-Abs calculates the absolute value of each value in a channel of float64.
+Abs calculates the absolute value of each value in a channel of type T.
Example:
@@ -183,7 +183,7 @@ fmt.Println(helper.ChanToSlice(abs)) // [10, 20, 4, 5]
func Add[T Number](ac, bc <-chan T) <-chan T
```
-Add adds each pair of values from the two input channels of float64 and returns a new channel containing the sums.
+Add adds each pair of values from the two input channels of type T and returns a new channel containing the sums.
Example:
@@ -212,7 +212,7 @@ AppendOrWriteToCsvFile writes the provided rows of data to the specified file, a
func Apply[T Number](c <-chan T, f func(T) T) <-chan T
```
-Apply applies the given transformation function to each element in the input channel and returns a new channel containing the transformed values. The transformation function takes a float64 value as input and returns a float64 value as output.
+Apply applies the given transformation function to each element in the input channel and returns a new channel containing the transformed values. The transformation function takes a value of type T as input and returns a value of type T as output.
Example:
@@ -261,7 +261,7 @@ fmt.Println(buffer.String())
func ChanToSlice[T any](c <-chan T) []T
```
-ChanToSlice converts a channel of float64 to a slice of float64.
+ChanToSlice converts a channel of type T to a slice of type T.
Example:
@@ -457,7 +457,7 @@ fmt.Println(helper.ChanToSlice(substractOne)) // [0, 1, 2, 3]
func Divide[T Number](ac, bc <-chan T) <-chan T
```
-Divide takes two channels of float64 and divides the values from the first channel with the values from the second one. It returns a new channel containing the results of the division.
+Divide takes two channels of type T and divides the values from the first channel with the values from the second one. It returns a new channel containing the results of the division.
Example:
@@ -477,7 +477,7 @@ fmt.Println(helper.ChanToSlice(division)) // [1, 4, 2, 4, 2]
func DivideBy[T Number](c <-chan T, d T) <-chan T
```
-DivideBy divides each element in the input channel of float64 values by the given divider and returns a new channel containing the divided values.
+DivideBy divides each element in the input channel of type T values by the given divider and returns a new channel containing the divided values.
Example:
@@ -547,7 +547,7 @@ Field extracts a specific field from a channel of struct pointers and delivers i
func Filter[T any](c <-chan T, p func(T) bool) <-chan T
```
-Filter filters the items from the input channel based on the provided predicate function. The predicate function takes a float64 value as input and returns a boolean value indicating whether the value should be included in the output channel.
+Filter filters the items from the input channel based on the provided predicate function. The predicate function takes a value of type T as input and returns a boolean value indicating whether the value should be included in the output channel.
Example:
@@ -582,7 +582,7 @@ Gcd calculates the Greatest Common Divisor of the given numbers.
func Head[T Number](c <-chan T, count int) <-chan T
```
-Head retrieves the specified number of elements from the given channel of float64 values and delivers them through a new channel.
+Head retrieves the specified number of elements from the given channel of type T values and delivers them through a new channel.
Example:
@@ -643,7 +643,7 @@ JSONToChanWithLogger reads values from the specified reader in JSON format into
func KeepNegatives[T Number](c <-chan T) <-chan T
```
-KeepNegatives processes a stream of float64 values, retaining negative values unchanged and replacing positive values with zero.
+KeepNegatives processes a stream of type T values, retaining negative values unchanged and replacing positive values with zero.
Example:
@@ -660,7 +660,7 @@ fmt.Println(helper.ChanToSlice(negatives)) // [-10, 0, 0, -5]
func KeepPositives[T Number](c <-chan T) <-chan T
```
-KeepPositives processes a stream of float64 values, retaining positive values unchanged and replacing negative values with zero.
+KeepPositives processes a stream of type T values, retaining positive values unchanged and replacing negative values with zero.
Example:
@@ -704,7 +704,7 @@ Lowest returns a channel that emits the lowest value within a sliding window of
func Map[F, T any](c <-chan F, f func(F) T) <-chan T
```
-Map applies the given transformation function to each element in the input channel and returns a new channel containing the transformed values. The transformation function takes a float64 value as input and returns a float64 value as output.
+Map applies the given transformation function to each element in the input channel and returns a new channel containing the transformed values. The transformation function takes a value of type F as input and returns a value of type T as output.
Example:
@@ -756,7 +756,7 @@ MinSince returns a channel of T indicating since when \(number of previous value
func Multiply[T Number](ac, bc <-chan T) <-chan T
```
-Multiply takes two channels of float64 and multiples the values from the first channel with the values from the second channel. It returns a new channel containing the results of the multiplication.
+Multiply takes two channels of type T and multiples the values from the first channel with the values from the second channel. It returns a new channel containing the results of the multiplication.
Example:
@@ -776,7 +776,7 @@ fmt.Println(helper.ChanToSlice(multiplication)) // [2, 4, 6, 8, 10]
func MultiplyBy[T Number](c <-chan T, m T) <-chan T
```
-MultiplyBy multiplies each element in the input channel of float64 values by the given multiplier and returns a new channel containing the multiplied values.
+MultiplyBy multiplies each element in the input channel of type T values by the given multiplier and returns a new channel containing the multiplied values.
Example:
@@ -888,7 +888,7 @@ fmt.println(helper.ChanToSlice(output)) // [2, 4, 6, 8]
func Pow[T Number](c <-chan T, y T) <-chan T
```
-Pow takes a channel of float64 values and returns the element\-wise base\-value exponential of y.
+Pow takes a channel of type T values and returns the element\-wise base\-value exponential of y.
Example:
@@ -948,7 +948,7 @@ fmt.Println(n) // 10.12
func RoundDigits[T Number](c <-chan T, d int) <-chan T
```
-RoundDigits takes a channel of float64 numbers and rounds them to d decimal places.
+RoundDigits takes a channel of type T numbers and rounds them to d decimal places.
Example:
@@ -1003,7 +1003,7 @@ fmt.Println(helper.ChanToSlice(output)) // [0, 0, 0, 0, 2, 4, 6, 8]
func Sign[T Number](c <-chan T) <-chan T
```
-Sign takes a channel of float64 values and returns their signs as \-1 for negative, 0 for zero, and 1 for positive.
+Sign takes a channel of type T values and returns their signs as \-1 for negative, 0 for zero, and 1 for positive.
Example:
@@ -1029,7 +1029,7 @@ Since counts the number of periods since the last change of value in a channel o
func Skip[T any](c <-chan T, count int) <-chan T
```
-Skip skips the specified number of elements from the given channel of float64.
+Skip skips the specified number of elements from the given channel of type T.
Example:
@@ -1063,7 +1063,7 @@ fmt.Println(helper.ChanToSlice(actual)) // [2, 4]
func SliceToChan[T any](slice []T) <-chan T
```
-SliceToChan converts a slice of float64 to a channel of float64.
+SliceToChan converts a slice of type T to a channel of type T.
Example:
@@ -1101,7 +1101,7 @@ SortedPercentRank returns a channel that emits the percentile rank by sorting th
func Sqrt[T Number](c <-chan T) <-chan T
```
-Sqrt calculates the square root of each value in a channel of float64.
+Sqrt calculates the square root of each value in a channel of type T.
Example:
@@ -1118,7 +1118,7 @@ fmt.Println(helper.ChanToSlice(sqrt)) // [3, 9, 4, 10]
func Subtract[T Number](ac, bc <-chan T) <-chan T
```
-Subtract takes two channels of float64 and subtracts the values from the second channel from the first one. It returns a new channel containing the results of the subtractions.
+Subtract takes two channels of type T and subtracts the values from the second channel from the first one. It returns a new channel containing the results of the subtractions.
Example:
diff --git a/momentum/GEMINI.md b/momentum/GEMINI.md
index a93218a..ac66c77 100644
--- a/momentum/GEMINI.md
+++ b/momentum/GEMINI.md
@@ -4,7 +4,7 @@ The `momentum` package provides a collection of indicators for analyzing price m
## Key Indicators
-- **Oscillators:** `AwesomeOscillator`, `ChaikinOscillator`, `StochasticOscillator`, `Rsi` (Relative Strength Index), `Rvi` (Relative Vigor Index), `WilliamsR`.
+- **Key Indicators:** `AwesomeOscillator`, `ChaikinOscillator`, `StochasticOscillator`, `UltimateOscillator`, `Rsi` (Relative Strength Index), `Rvi` (Relative Vigor Index), `WilliamsR`.
- **Specialized:** `ConnorsRSI`, `Fisher` (Fisher Transform), `IchimokuCloud`, `Ppo` (Percentage Price Oscillator), `Pvo` (Percentage Volume Oscillator), `Qstick`.
- **Trends:** `PringsSpecialK`, `TdSequential`.
diff --git a/momentum/README.md b/momentum/README.md
index c8faa8a..ded0fe2 100644
--- a/momentum/README.md
+++ b/momentum/README.md
@@ -102,6 +102,12 @@ The information provided on this project is strictly for informational purposes
- [func NewTdSequential\[T helper.Number\]\(\) \*TdSequential\[T\]](<#NewTdSequential>)
- [func \(t \*TdSequential\[T\]\) Compute\(closings \<\-chan T\) \(\<\-chan T, \<\-chan T, \<\-chan T, \<\-chan T\)](<#TdSequential[T].Compute>)
- [func \(t \*TdSequential\[T\]\) IdlePeriod\(\) int](<#TdSequential[T].IdlePeriod>)
+- [type UltimateOscillator](<#UltimateOscillator>)
+ - [func NewUltimateOscillator\[T helper.Number\]\(\) \*UltimateOscillator\[T\]](<#NewUltimateOscillator>)
+ - [func NewUltimateOscillatorWithPeriods\[T helper.Number\]\(shortPeriod, mediumPeriod, longPeriod int\) \*UltimateOscillator\[T\]](<#NewUltimateOscillatorWithPeriods>)
+ - [func \(u \*UltimateOscillator\[T\]\) Compute\(highs, lows, closings \<\-chan T\) \<\-chan T](<#UltimateOscillator[T].Compute>)
+ - [func \(u \*UltimateOscillator\[T\]\) IdlePeriod\(\) int](<#UltimateOscillator[T].IdlePeriod>)
+ - [func \(u \*UltimateOscillator\[T\]\) String\(\) string](<#UltimateOscillator[T].String>)
- [type WilliamsR](<#WilliamsR>)
- [func NewWilliamsR\[T helper.Number\]\(\) \*WilliamsR\[T\]](<#NewWilliamsR>)
- [func \(w \*WilliamsR\[T\]\) Compute\(highs, lows, closings \<\-chan T\) \<\-chan T](<#WilliamsR[T].Compute>)
@@ -270,6 +276,21 @@ const (
)
```
+
+
+```go
+const (
+ // DefaultUltimateOscillatorShortPeriod is the default short period for the Ultimate Oscillator (UO).
+ DefaultUltimateOscillatorShortPeriod = 7
+
+ // DefaultUltimateOscillatorMediumPeriod is the default medium period for the Ultimate Oscillator (UO).
+ DefaultUltimateOscillatorMediumPeriod = 14
+
+ // DefaultUltimateOscillatorLongPeriod is the default long period for the Ultimate Oscillator (UO).
+ DefaultUltimateOscillatorLongPeriod = 28
+)
+```
+
```go
@@ -1365,6 +1386,85 @@ func (t *TdSequential[T]) IdlePeriod() int
IdlePeriod is the initial period that TD Sequential won't yield meaningful results.
+
+## type [UltimateOscillator]()
+
+UltimateOscillator represents the configuration parameter for calculating the Ultimate Oscillator \(UO\). It was developed by Larry Williams in 1976 to measure the price momentum of an asset across multiple timeframes. By using the weighted average of three different timeframes the indicator has less volatility and fewer trade signals compared to other oscillators that rely on a single timeframe.
+
+```
+BP = Close - Minimum(Low, Prior Close)
+TR = Maximum(High, Prior Close) - Minimum(Low, Prior Close)
+Average7 = Sum(BP for 7 periods) / Sum(TR for 7 periods)
+Average14 = Sum(BP for 14 periods) / Sum(TR for 14 periods)
+Average28 = Sum(BP for 28 periods) / Sum(TR for 28 periods)
+UO = 100 * [(4 * Average7) + (2 * Average14) + Average28] / (4 + 2 + 1)
+```
+
+Example:
+
+```
+uo := momentum.NewUltimateOscillator[float64]()
+values := uo.Compute(highs, lows, closings)
+```
+
+```go
+type UltimateOscillator[T helper.Number] struct {
+ // ShortPeriod is the short period for the UO.
+ ShortPeriod int
+
+ // MediumPeriod is the medium period for the UO.
+ MediumPeriod int
+
+ // LongPeriod is the long period for the UO.
+ LongPeriod int
+}
+```
+
+
+### func [NewUltimateOscillator]()
+
+```go
+func NewUltimateOscillator[T helper.Number]() *UltimateOscillator[T]
+```
+
+NewUltimateOscillator function initializes a new Ultimate Oscillator instance.
+
+
+### func [NewUltimateOscillatorWithPeriods]()
+
+```go
+func NewUltimateOscillatorWithPeriods[T helper.Number](shortPeriod, mediumPeriod, longPeriod int) *UltimateOscillator[T]
+```
+
+NewUltimateOscillatorWithPeriods function initializes a new Ultimate Oscillator instance with the given periods.
+
+
+### func \(\*UltimateOscillator\[T\]\) [Compute]()
+
+```go
+func (u *UltimateOscillator[T]) Compute(highs, lows, closings <-chan T) <-chan T
+```
+
+Compute function takes a channel of numbers and computes the Ultimate Oscillator.
+
+
+### func \(\*UltimateOscillator\[T\]\) [IdlePeriod]()
+
+```go
+func (u *UltimateOscillator[T]) IdlePeriod() int
+```
+
+IdlePeriod is the initial period that Ultimate Oscillator won't yield any results.
+
+
+### func \(\*UltimateOscillator\[T\]\) [String]()
+
+```go
+func (u *UltimateOscillator[T]) String() string
+```
+
+
+
## type [WilliamsR]()