Skip to content

Commit

Permalink
Negative Volume Index (NVI) is added.
Browse files Browse the repository at this point in the history
  • Loading branch information
cinar committed Jan 16, 2022
1 parent d6af34c commit a5118dd
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ The following list of indicators are currently supported by this package:
- [Ease of Movement (EMV)](volume_indicators.md#ease-of-movement-emv)
- [Force Index (FI)](volume_indicators.md#force-index-fi)
- [Money Flow Index (MFI)](volume_indicators.md#money-flow-index-mfi)
- [Negative Volume Index (NVI)](volume_indicators.md#negative-volume-index-nvi)
- [On-Balance Volume (OBV)](volume_indicators.md#on-balance-volume-obv)
- [Volume Price Trend (VPT)](volume_indicators.md#volume-price-trend-vpt)
- [Volume Weighted Average Price (VWAP)](volume_indicators.md#volume-weighted-average-price-vwap)
Expand Down Expand Up @@ -97,6 +98,7 @@ The following list of strategies are currently supported by this package:
- [Ease of Movement Strategy](volume_strategies.md#ease-of-movement-strategy)
- [Force Index Strategy](volume_strategies.md#force-index-strategy)
- [Money Flow Index Strategy](volume_strategies.md#money-flow-index-strategy)
- [Negative Volume Index Strategy](volume_strategies.md#negative-volume-index-strategy)
- [Volume Weighted Average Price Strategy](volume_strategies.md#volume-weighted-average-price-strategy)

### Compound Strategies
Expand Down
32 changes: 32 additions & 0 deletions volume_indicators.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,35 @@ func VolumeWeightedAveragePrice(period int, closing []float64, volume []int64) [
func DefaultVolumeWeightedAveragePrice(closing []float64, volume []int64) []float64 {
return VolumeWeightedAveragePrice(14, closing, volume)
}

// The Negative Volume Index (NVI) is a cumulative indicator using
// the change in volume to decide when the smart money is active.
//
// If Volume is greather than Previous Volume:
//
// NVI = Previous NVI
//
// Otherwise:
//
// NVI = Previous NVI + (((Closing - Previous Closing) / Previous Closing) * Previous NVI)
//
// Returns nvi values.
func NegativeVolumeIndex(closing []float64, volume []int64) []float64 {
if len(closing) != len(volume) {
panic("not all same size")
}

nvi := make([]float64, len(closing))

for i := 0; i < len(nvi); i++ {
if i == 0 {
nvi[i] = 1000
} else if volume[i-1] < volume[i] {
nvi[i] = nvi[i-1]
} else {
nvi[i] = nvi[i-1] + (((closing[i] - closing[i-1]) / closing[i-1]) * nvi[i-1])
}
}

return nvi
}
19 changes: 19 additions & 0 deletions volume_indicators.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Volumne indicators measure the strength of a trend based the volume.
- [Ease of Movement (EMV)](#ease-of-movement-emv)
- [Force Index (FI)](#force-index-fi)
- [Money Flow Index (MFI)](#money-flow-index-mfi)
- [Negative Volume Index (NVI)](#negative-volume-index-nvi)
- [On-Balance Volume (OBV)](#on-balance-volume-obv)
- [Volume Price Trend (VPT)](#volume-price-trend-vpt)
- [Volume Weighted Average Price (VWAP)](#volume-weighted-average-price-vwap)
Expand Down Expand Up @@ -83,6 +84,24 @@ result := indicator.MoneyFlowIndex(period, high, low, closing, volume)

The [DefaultMoneyFlowIndex](https://pkg.go.dev/github.com/cinar/indicator#DefaultMoneyFlowIndex) function uses the default period of 14.

#### Negative Volume Index (NVI)

The [NegativeVolumeIndex](https://pkg.go.dev/github.com/cinar/indicator#NegativeVolumeIndex) function calculates a cumulative indicator using the change in volume to decide when the smart money is active.

```
If Volume is greather than Previous Volume:
NVI = Previous NVI
Otherwise:
NVI = Previous NVI + (((Closing - Previous Closing) / Previous Closing) * Previous NVI)
```

```Golang
result := indicator.NegativeVolumeIndex(closing, volume)
```

#### On-Balance Volume (OBV)

The [Obv](https://pkg.go.dev/github.com/cinar/indicator#Obv) function calculates a technical trading momentum indicator that uses volume flow to predict changes in stock price.
Expand Down
9 changes: 9 additions & 0 deletions volume_indicators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,12 @@ func TestDefaultVolumeWeightedAveragePrice(t *testing.T) {
actual := roundDigitsAll(DefaultVolumeWeightedAveragePrice(closing, volume), 2)
testEquals(t, actual, expected)
}

func TestNegativeVolumeIndex(t *testing.T) {
closing := []float64{9, 11, 7, 10, 8}
volume := []int64{100, 110, 80, 120, 90}
expected := []float64{1000, 1000, 636.36, 636.36, 509.09}

actual := roundDigitsAll(NegativeVolumeIndex(closing, volume), 2)
testEquals(t, actual, expected)
}
20 changes: 20 additions & 0 deletions volume_strategies.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,23 @@ func VolumeWeightedAveragePriceStrategy(asset Asset) []Action {

return actions
}

// Negative volume index strategy.
func NegativeVolumeIndexStrategy(asset Asset) []Action {
actions := make([]Action, len(asset.Date))

nvi := NegativeVolumeIndex(asset.Closing, asset.Volume)
nvi255 := Ema(255, nvi)

for i := 0; i < len(actions); i++ {
if nvi[i] < nvi255[i] {
actions[i] = BUY
} else if nvi[i] > nvi255[i] {
actions[i] = SELL
} else {
actions[i] = HOLD
}
}

return actions
}
9 changes: 9 additions & 0 deletions volume_strategies.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Volume strategies generate signals based on a volume indicator.
- [Ease of Movement Strategy](#ease-of-movement-strategy)
- [Force Index Strategy](#force-index-strategy)
- [Money Flow Index Strategy](#money-flow-index-strategy)
- [Negative Volume Index Strategy](#negative-volume-index-strategy)
- [Volume Weighted Average Price Strategy](#volume-weighted-average-price-strategy)

#### Ease of Movement Strategy
Expand All @@ -31,6 +32,14 @@ The [MoneyFlowIndexStrategy](https://pkg.go.dev/github.com/cinar/indicator#Money
actions := indicator.MoneyFlowIndexStrategy(asset)
```

#### Negative Volume Index Strategy

The [NegativeVolumeIndexStrategy](https://pkg.go.dev/github.com/cinar/indicator#NegativeVolumeIndexStrategy) uses the _nvi_ values that are generated by the [Negative Volume Index (NVI)](volume_indicators.md#negative-volume-index-nvi) indicator function to provide a _BUY_ action when _nvi_ is less than its 255-period EMA, and a _SELL_ action when it is greather than its 255-period EMA, otherwise a _HOLD_ action.

```Golang
actions := indicator.NegativeVolumeIndexStrategy(asset)
```

#### Volume Weighted Average Price Strategy

The [VolumeWeightedAveragePriceStrategy]([./volumeWeightedAveragePriceStrategy.ts](https://pkg.go.dev/github.com/cinar/indicator#VolumeWeightedAveragePriceStrategy)) uses the values that are generated by the [Volume Weighted Average Price (VWAP)](volume_indicators.md#volume-weighted-average-price-vwap) indicator function to provide a _BUY_ action when the _closing_ is below the _VWAP_, and a _SELL_ action when the _closing_ is below the _VWAP_, a _HOLD_ action otherwise.
Expand Down

0 comments on commit a5118dd

Please sign in to comment.