mirror of
https://github.com/lukewilson2002/autotrader.git
synced 2025-06-14 16:03:51 +00:00
70 lines
2.6 KiB
Go
70 lines
2.6 KiB
Go
package autotrader
|
|
|
|
import (
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
// RSI calculates the Relative Strength Index for a given Series. Typically, the input series is the Close column of a DataFrame. Returns a Series of RSI values of the same length as the input.
|
|
//
|
|
// Traditionally, an RSI reading of 70 or above indicates an overbought condition, and a reading of 30 or below indicates an oversold condition.
|
|
//
|
|
// Typically, the RSI is calculated with a period of 14 days.
|
|
func RSI(series *FloatSeries, periods int) *FloatSeries {
|
|
// Calculate the difference between each day's close and the previous day's close.
|
|
delta := series.Copy().MapReverse(func(i int, v float64) float64 {
|
|
if i == 0 {
|
|
return 0
|
|
}
|
|
return v - series.Value(i-1)
|
|
})
|
|
// Calculate the average gain and average loss.
|
|
avgGain := &FloatSeries{delta.Copy().
|
|
Map(func(i int, val float64) float64 { return math.Max(val, 0) }).
|
|
Rolling(periods).Average()}
|
|
avgLoss := &FloatSeries{delta.Copy().
|
|
Map(func(i int, val float64) float64 { return math.Abs(math.Min(val, 0)) }).
|
|
Rolling(periods).Average()}
|
|
|
|
// Calculate the RSI.
|
|
return avgGain.Map(func(i int, val float64) float64 {
|
|
loss := avgLoss.Float(i)
|
|
if loss == 0 {
|
|
return float64(100)
|
|
}
|
|
return float64(100 - 100/(1+val/loss))
|
|
}).SetName("RSI")
|
|
}
|
|
|
|
// Ichimoku calculates the Ichimoku Cloud for a given Series. Returns a DataFrame of the same length as the input with float64 values. The series input must contain only float64 values, which are traditionally the close prices.
|
|
//
|
|
// The standard values:
|
|
// - convPeriod: 9
|
|
// - basePeriod: 26
|
|
// - leadingPeriods: 52
|
|
//
|
|
// DataFrame columns:
|
|
// - Conversion
|
|
// - Base
|
|
// - LeadingA
|
|
// - LeadingB
|
|
// - Lagging
|
|
func Ichimoku(price *IndexedFrame[UnixTime], convPeriod, basePeriod, leadingPeriods int, frequency time.Duration) *IndexedFrame[UnixTime] {
|
|
// TODO: make this run concurrently.
|
|
|
|
conv := price.Highs().Copy().Rolling(convPeriod).Max().Add(price.Lows().Copy().Rolling(convPeriod).Min()).DivFloat(2)
|
|
base := price.Highs().Copy().Rolling(basePeriod).Max().Add(price.Lows().Copy().Rolling(basePeriod).Min()).DivFloat(2)
|
|
leadingA := conv.Copy().Add(base).DivFloat(2)
|
|
leadingB := price.Highs().Copy().Rolling(leadingPeriods).Max().Add(price.Lows().Copy().Rolling(leadingPeriods).Min()).DivFloat(2)
|
|
lagging := price.Closes().Copy()
|
|
|
|
// Return a DataFrame of the results.
|
|
return NewIndexedFrame(
|
|
conv.SetName("Conversion"),
|
|
base.SetName("Base"),
|
|
leadingA.SetName("LeadingA").ShiftIndex(leadingPeriods, UnixTimeStep(frequency)),
|
|
leadingB.SetName("LeadingB").ShiftIndex(leadingPeriods, UnixTimeStep(frequency)),
|
|
lagging.SetName("Lagging").ShiftIndex(-basePeriod, UnixTimeStep(frequency)),
|
|
)
|
|
}
|