Skip to content

Commit

Permalink
Merge pull request #21 from cinar/issue-5
Browse files Browse the repository at this point in the history
Ulcer Index (UI) added. Fixed #5.
  • Loading branch information
cinar committed Jan 21, 2022
2 parents 839ca62 + 62e7b6f commit 404c5b4
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -52,6 +52,7 @@ The following list of indicators are currently supported by this package:
- [Chandelier Exit](src/indicator/volatility/index.md#chandelier-exit)
- [Moving Standard Deviation (Std)](src/indicator/volatility/index.md#moving-standard-deviation-std)
- [Projection Oscillator (PO)](src/indicator/volatility/index.md#projection-oscillator-po)
- [Ulcer Index (UI)](src/indicator/volatility/index.md#ulcer-index-ui)

### Volume Indicators

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions src/indicator/volatility/index.md
Expand Up @@ -9,6 +9,7 @@ Volatility indicators measure the rate of movement regardless of its direction.
- [Chandelier Exit](#chandelier-exit)
- [Moving Standard Deviation (Std)](#moving-standard-deviation-std)
- [Projection Oscillator (PO)](#projection-oscillator-po)
- [Ulcer Index (UI)](#ulcer-index-ui)

#### Acceleration Bands

Expand Down Expand Up @@ -117,6 +118,31 @@ import {projectionOscillator} from 'indicatorts';
const result = projectionOscillator(period, smooth, highs, lows, closings);
```

#### Ulcer Index (UI)

The [ulcerIndex](./ulcerIndex.ts) measures downside risk. The index increases in value as the price moves farther away from a recent high and falls as the price rises to new highs.

```
High Closings = Max(period, Closings)
Percentage Drawdown = 100 * ((Closings - High Closings) / High Closings)
Squared Average = Sma(period, Percent Drawdown * Percent Drawdown)
Ulcer Index = Sqrt(Squared Average)
```

```TypeScript
import {ulcerIndex} from 'indicatorts';

const result = ulcerIndex(period, closings);
```

The [defaultUlcerIndex](./ulcerIndex.ts) measures the ulcer index with the default period of 14.

```TypeScript
import {defaultUlcerIndex} from 'indicatorts';

const result = defaultUlcerIndex(closings);
```

## Disclaimer

The information provided on this project is strictly for informational purposes and is not to be construed as advice or solicitation to buy or sell any security.
Expand Down
16 changes: 16 additions & 0 deletions src/indicator/volatility/ulcerIndex.test.ts
@@ -0,0 +1,16 @@
// Copyright (c) 2022 Onur Cinar. All Rights Reserved.
// https://github.com/cinar/indicatorts

import {roundDigitsAll} from '../../index';
import {defaultUlcerIndex} from './ulcerIndex';

describe('Ulcer Index', () => {
it('should be able to compute UI', () => {
const closings = [9, 11, 7, 10, 8, 7, 7, 8, 10, 9, 5, 4, 6, 7];
const expected = [0, 0, 20.99, 18.74, 20.73, 24.05, 26.17, 26.31,
24.99, 24.39, 28.49, 32.88, 34.02, 34.19];

const actual = defaultUlcerIndex(closings);
expect(roundDigitsAll(2, actual)).toStrictEqual(expected);
});
});
45 changes: 45 additions & 0 deletions src/indicator/volatility/ulcerIndex.ts
@@ -0,0 +1,45 @@
// Copyright (c) 2022 Onur Cinar. All Rights Reserved.
// https://github.com/cinar/indicatorts

import {divide, multiply, multiplyBy, sqrt, substract} from '../../helper/numArray';
import {mmax} from '../trend/mmax';
import {sma} from '../trend/sma';

/**
* Default period for UI.
*/
export const UI_DEFAULT_PERIOD = 14;

/**
* The Ulcer Index (UI) measures downside risk. The index increases in value
* as the price moves farther away from a recent high and falls as the price
* rises to new highs.
*
* High Closings = Max(period, Closings)
* Percentage Drawdown = 100 * ((Closings - High Closings) / High Closings)
* Squared Average = Sma(period, Percent Drawdown * Percent Drawdown)
* Ulcer Index = Sqrt(Squared Average)
*
* @param period window period.
* @param closings closing values.
* @returns ui values.
*/
export function ulcerIndex(period: number, closings: number[]): number[] {
const highClosings = mmax(period, closings);
const percentageDrawdown = multiplyBy(100, divide(substract(closings, highClosings), highClosings));
const squaredAverage = sma(period, multiply(percentageDrawdown, percentageDrawdown));
const ui = sqrt(squaredAverage);

return ui;
}

/**
* The default ulcer index with the default period of 14.
*
* @param closings closing values.
* @returns ui values.
*/
export function defaultUlcerIndex(closings: number[]): number[] {
return ulcerIndex(UI_DEFAULT_PERIOD, closings);
}

0 comments on commit 404c5b4

Please sign in to comment.