Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chaging the type of Volume from int64 to float64. #127

Merged
merged 1 commit into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions momentum_indicators.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func AwesomeOscillator(low, high []float64) []float64 {
// CO = Ema(fastPeriod, AD) - Ema(slowPeriod, AD)
//
// Returns co, ad.
func ChaikinOscillator(fastPeriod, slowPeriod int, low, high, closing []float64, volume []int64) ([]float64, []float64) {
func ChaikinOscillator(fastPeriod, slowPeriod int, low, high, closing, volume []float64) ([]float64, []float64) {
ad := AccumulationDistribution(high, low, closing, volume)
co := subtract(Ema(fastPeriod, ad), Ema(slowPeriod, ad))

Expand All @@ -41,7 +41,7 @@ func ChaikinOscillator(fastPeriod, slowPeriod int, low, high, closing []float64,
// periods, 3 and 10.
//
// Returns co, ad.
func DefaultChaikinOscillator(low, high, closing []float64, volume []int64) ([]float64, []float64) {
func DefaultChaikinOscillator(low, high, closing, volume []float64) ([]float64, []float64) {
return ChaikinOscillator(3, 10, low, high, closing, volume)
}

Expand Down Expand Up @@ -102,10 +102,9 @@ func DefaultPercentagePriceOscillator(price []float64) ([]float64, []float64, []
// Histogram = PVO - Signal
//
// Returns pvo, signal, histogram
func PercentageVolumeOscillator(fastPeriod, slowPeriod, signalPeriod int, volume []int64) ([]float64, []float64, []float64) {
volumeAsFloat := asFloat64(volume)
fastEma := Ema(fastPeriod, volumeAsFloat)
slowEma := Ema(slowPeriod, volumeAsFloat)
func PercentageVolumeOscillator(fastPeriod, slowPeriod, signalPeriod int, volume []float64) ([]float64, []float64, []float64) {
fastEma := Ema(fastPeriod, volume)
slowEma := Ema(slowPeriod, volume)
pvo := multiplyBy(divide(subtract(fastEma, slowEma), slowEma), 100)
signal := Ema(signalPeriod, pvo)
histogram := subtract(pvo, signal)
Expand All @@ -116,7 +115,7 @@ func PercentageVolumeOscillator(fastPeriod, slowPeriod, signalPeriod int, volume
// Default Percentage Volume Oscillator calculates it with the default periods of 12, 26, 9.
//
// Returns pvo, signal, histogram
func DefaultPercentageVolumeOscillator(volume []int64) ([]float64, []float64, []float64) {
func DefaultPercentageVolumeOscillator(volume []float64) ([]float64, []float64, []float64) {
return PercentageVolumeOscillator(12, 26, 9, volume)
}

Expand Down
4 changes: 2 additions & 2 deletions momentum_indicators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestChaikinOscillator(t *testing.T) {
high := []float64{10, 11, 12, 13, 14, 15, 16, 17}
low := []float64{1, 2, 3, 4, 5, 6, 7, 8}
closing := []float64{5, 6, 7, 8, 9, 10, 11, 12}
volume := []int64{100, 200, 300, 400, 500, 600, 700, 800}
volume := []float64{100, 200, 300, 400, 500, 600, 700, 800}
expected := []float64{0, -7.41, -18.52, -31.69, -46.09, -61.27, -76.95, -92.97}

actual, _ := ChaikinOscillator(2, 5, low, high, closing, volume)
Expand Down Expand Up @@ -76,7 +76,7 @@ func TestPercentagePriceOscillator(t *testing.T) {
}

func TestPercentageVolumeOscillator(t *testing.T) {
volume := []int64{
volume := []float64{
6954, 4511, 4474, 4126, 4572, 3936, 3192, 3090, 3476, 3852, 3107, 3604,
4145, 5192, 3560, 3961, 4322, 3901, 3392, 4278, 4212, 4428, 3846, 3824,
4142, 4964, 4683, 4630, 4746, 4254, 4197, 4236, 3877, 4474, 3943, 3969,
Expand Down
2 changes: 1 addition & 1 deletion strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Asset struct {
Closing []float64
High []float64
Low []float64
Volume []int64
Volume []float64
}

// Strategy function. It takes an Asset and returns
Expand Down
2 changes: 1 addition & 1 deletion strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Asset struct {
Closing []float64
High []float64
Low []float64
Volume []int64
Volume []float64
}
```

Expand Down
27 changes: 15 additions & 12 deletions trend_indicators.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,12 @@ func Min(period int, values []float64) []float64 {
// PSAR = PSAR[i - 1] - ((PSAR[i - 1] - EP) * AF)
//
// If the trend is Falling:
// - PSAR is the maximum of PSAR or the previous two high values.
// - If the current high is greather than or equals to PSAR, use EP.
// - PSAR is the maximum of PSAR or the previous two high values.
// - If the current high is greather than or equals to PSAR, use EP.
//
// If the trend is Rising:
// - PSAR is the minimum of PSAR or the previous two low values.
// - If the current low is less than or equals to PSAR, use EP.
// - PSAR is the minimum of PSAR or the previous two low values.
// - If the current low is less than or equals to PSAR, use EP.
//
// If PSAR is greater than the closing, trend is falling, and the EP
// is set to the minimum of EP or the low.
Expand Down Expand Up @@ -361,9 +361,10 @@ func Qstick(period int, opening, closing []float64) []float64 {
// crosses above 80%, and oversold when they crosses below
// 20%. The J line represents the divergence.
//
//
// RSV = ((Closing - Min(Low, rPeriod))
// / (Max(High, rPeriod) - Min(Low, rPeriod))) * 100
//
// / (Max(High, rPeriod) - Min(Low, rPeriod))) * 100
//
// K = Sma(RSV, kPeriod)
// D = Sma(K, dPeriod)
// J = (3 * K) - (2 * D)
Expand Down Expand Up @@ -498,9 +499,12 @@ func Tema(period int, values []float64) []float64 {
// Trima function calculates the Triangular Moving Average (TRIMA).
//
// If period is even:
// TRIMA = SMA(period / 2, SMA((period / 2) + 1, values))
//
// TRIMA = SMA(period / 2, SMA((period / 2) + 1, values))
//
// If period is odd:
// TRIMA = SMA((period + 1) / 2, SMA((period + 1) / 2, values))
//
// TRIMA = SMA((period + 1) / 2, SMA((period + 1) / 2, values))
//
// Returns trima.
func Trima(period int, values []float64) []float64 {
Expand Down Expand Up @@ -627,14 +631,13 @@ func Vortex(high, low, closing []float64) ([]float64, []float64) {
// VWMA = Sum(Price * Volume) / Sum(Volume) for a given Period.
//
// Returns vwma
func Vwma(period int, closing []float64, volume []int64) []float64 {
floatVolume := asFloat64(volume)
vwma := divide(Sum(period, multiply(closing, floatVolume)), Sum(period, floatVolume))
func Vwma(period int, closing, volume []float64) []float64 {
vwma := divide(Sum(period, multiply(closing, volume)), Sum(period, volume))

return vwma
}

// The DefaultVwma function calculates VWMA with a period of 20.
func DefaultVwma(closing []float64, volume []int64) []float64 {
func DefaultVwma(closing, volume []float64) []float64 {
return Vwma(20, closing, volume)
}
4 changes: 2 additions & 2 deletions trend_indicators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ func TestVortex(t *testing.T) {

func TestVwma(t *testing.T) {
closing := []float64{20, 21, 21, 19, 16}
volume := []int64{100, 50, 40, 50, 100}
volume := []float64{100, 50, 40, 50, 100}
expected := []float64{20, 20.33, 20.47, 20.29, 17.84}
period := 3

Expand All @@ -305,7 +305,7 @@ func TestVwma(t *testing.T) {

func TestDefaultVwma(t *testing.T) {
closing := []float64{20, 21, 21, 19, 16}
volume := []int64{100, 50, 40, 50, 100}
volume := []float64{100, 50, 40, 50, 100}
expected := []float64{20, 20.33, 20.47, 20.17, 18.94}

actual := DefaultVwma(closing, volume)
Expand Down
6 changes: 3 additions & 3 deletions trend_strategies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestTrendStrategy(t *testing.T) {
Low: []float64{
0, 0, 0, 0, 0,
},
Volume: []int64{
Volume: []float64{
0, 0, 0, 0, 0,
},
}
Expand Down Expand Up @@ -57,7 +57,7 @@ func TestVwmaStrategy(t *testing.T) {
Low: []float64{
0, 0, 0, 0, 0,
},
Volume: []int64{
Volume: []float64{
100, 50, 40, 50, 100,
},
}
Expand Down Expand Up @@ -90,7 +90,7 @@ func TestDefaultVwmaStrategy(t *testing.T) {
Low: []float64{
0, 0, 0, 0, 0,
},
Volume: []int64{
Volume: []float64{
100, 50, 40, 50, 100,
},
}
Expand Down
54 changes: 27 additions & 27 deletions volume_indicators.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const CMF_DEFAULT_PERIOD = 20
// AD = Previous AD + CMFV
//
// Returns ad.
func AccumulationDistribution(high, low, closing []float64, volume []int64) []float64 {
func AccumulationDistribution(high, low, closing, volume []float64) []float64 {
checkSameSize(high, low, closing)

ad := make([]float64, len(closing))
Expand All @@ -39,17 +39,19 @@ func AccumulationDistribution(high, low, closing []float64, volume []int64) []fl
// On-Balance Volume (OBV). It is a technical trading momentum indicator that
// uses volume flow to predict changes in stock price.
//
// volume, if Closing > Closing-Prev
// volume, if Closing > Closing-Prev
//
// OBV = OBV-Prev + 0, if Closing = Closing-Prev
// -volume, if Closing < Closing-Prev
//
// -volume, if Closing < Closing-Prev
//
// Returns obv
func Obv(closing []float64, volume []int64) []int64 {
func Obv(closing, volume []float64) []float64 {
if len(closing) != len(volume) {
panic("not all same size")
}

obv := make([]int64, len(volume))
obv := make([]float64, len(volume))

for i := 1; i < len(obv); i++ {
obv[i] = obv[i-1]
Expand All @@ -73,9 +75,9 @@ func Obv(closing []float64, volume []int64) []int64 {
// Money Flow Index = 100 - (100 / (1 + Money Ratio))
//
// Retruns money flow index values.
func MoneyFlowIndex(period int, high, low, closing []float64, volume []int64) []float64 {
func MoneyFlowIndex(period int, high, low, closing, volume []float64) []float64 {
typicalPrice, _ := TypicalPrice(low, high, closing)
rawMoneyFlow := multiply(typicalPrice, asFloat64(volume))
rawMoneyFlow := multiply(typicalPrice, volume)

signs := extractSign(diff(rawMoneyFlow, 1))
moneyFlow := multiply(signs, rawMoneyFlow)
Expand All @@ -93,7 +95,7 @@ func MoneyFlowIndex(period int, high, low, closing []float64, volume []int64) []
}

// Default money flow index with period 14.
func DefaultMoneyFlowIndex(high, low, closing []float64, volume []int64) []float64 {
func DefaultMoneyFlowIndex(high, low, closing, volume []float64) []float64 {
return MoneyFlowIndex(14, high, low, closing, volume)
}

Expand All @@ -103,12 +105,12 @@ func DefaultMoneyFlowIndex(high, low, closing []float64, volume []int64) []float
// Force Index = EMA(period, (Current - Previous) * Volume)
//
// Returns force index.
func ForceIndex(period int, closing []float64, volume []int64) []float64 {
return Ema(period, multiply(diff(closing, 1), asFloat64(volume)))
func ForceIndex(period int, closing, volume []float64) []float64 {
return Ema(period, multiply(diff(closing, 1), volume))
}

// The default Force Index (FI) with window size of 13.
func DefaultForceIndex(closing []float64, volume []int64) []float64 {
func DefaultForceIndex(closing, volume []float64) []float64 {
return ForceIndex(13, closing, volume)
}

Expand All @@ -121,15 +123,15 @@ func DefaultForceIndex(closing []float64, volume []int64) []float64 {
// EMV(14) = SMA(14, EMV(1))
//
// Returns ease of movement values.
func EaseOfMovement(period int, high, low []float64, volume []int64) []float64 {
func EaseOfMovement(period int, high, low, volume []float64) []float64 {
distanceMoved := diff(divideBy(add(high, low), 2), 1)
boxRatio := divide(divideBy(asFloat64(volume), float64(100000000)), subtract(high, low))
boxRatio := divide(divideBy(volume, float64(100000000)), subtract(high, low))
emv := Sma(period, divide(distanceMoved, boxRatio))
return emv
}

// The default Ease of Movement with the default period of 14.
func DefaultEaseOfMovement(high, low []float64, volume []int64) []float64 {
func DefaultEaseOfMovement(high, low, volume []float64) []float64 {
return EaseOfMovement(14, high, low, volume)
}

Expand All @@ -139,9 +141,9 @@ func DefaultEaseOfMovement(high, low []float64, volume []int64) []float64 {
// VPT = Previous VPT + (Volume * (Current Closing - Previous Closing) / Previous Closing)
//
// Returns volume price trend values.
func VolumePriceTrend(closing []float64, volume []int64) []float64 {
func VolumePriceTrend(closing, volume []float64) []float64 {
previousClosing := shiftRightAndFillBy(1, closing[0], closing)
vpt := multiply(asFloat64(volume), divide(subtract(closing, previousClosing), previousClosing))
vpt := multiply(volume, divide(subtract(closing, previousClosing), previousClosing))
return Sum(len(vpt), vpt)
}

Expand All @@ -151,13 +153,12 @@ func VolumePriceTrend(closing []float64, volume []int64) []float64 {
// VWAP = Sum(Closing * Volume) / Sum(Volume)
//
// Returns vwap values.
func VolumeWeightedAveragePrice(period int, closing []float64, volume []int64) []float64 {
v := asFloat64(volume)
return divide(Sum(period, multiply(closing, v)), Sum(period, v))
func VolumeWeightedAveragePrice(period int, closing, volume []float64) []float64 {
return divide(Sum(period, multiply(closing, volume)), Sum(period, volume))
}

// Default volume weighted average price with period of 14.
func DefaultVolumeWeightedAveragePrice(closing []float64, volume []int64) []float64 {
func DefaultVolumeWeightedAveragePrice(closing, volume []float64) []float64 {
return VolumeWeightedAveragePrice(14, closing, volume)
}

Expand All @@ -166,14 +167,14 @@ func DefaultVolumeWeightedAveragePrice(closing []float64, volume []int64) []floa
//
// If Volume is greather than Previous Volume:
//
// NVI = Previous NVI
// NVI = Previous NVI
//
// Otherwise:
//
// NVI = Previous NVI + (((Closing - Previous Closing) / Previous Closing) * Previous NVI)
// NVI = Previous NVI + (((Closing - Previous Closing) / Previous Closing) * Previous NVI)
//
// Returns nvi values.
func NegativeVolumeIndex(closing []float64, volume []int64) []float64 {
func NegativeVolumeIndex(closing, volume []float64) []float64 {
if len(closing) != len(volume) {
panic("not all same size")
}
Expand All @@ -199,17 +200,16 @@ func NegativeVolumeIndex(closing []float64, volume []int64) []float64 {
// Money Flow Multiplier = ((Closing - Low) - (High - Closing)) / (High - Low)
// Money Flow Volume = Money Flow Multiplier * Volume
// Chaikin Money Flow = Sum(20, Money Flow Volume) / Sum(20, Volume)
//
func ChaikinMoneyFlow(high, low, closing []float64, volume []int64) []float64 {
func ChaikinMoneyFlow(high, low, closing, volume []float64) []float64 {
moneyFlowMultiplier := divide(
subtract(subtract(closing, low), subtract(high, closing)),
subtract(high, low))

moneyFlowVolume := multiply(moneyFlowMultiplier, asFloat64(volume))
moneyFlowVolume := multiply(moneyFlowMultiplier, volume)

cmf := divide(
Sum(CMF_DEFAULT_PERIOD, moneyFlowVolume),
Sum(CMF_DEFAULT_PERIOD, asFloat64(volume)))
Sum(CMF_DEFAULT_PERIOD, volume))

return cmf
}
Loading