Skip to content

Commit 5dadec0

Browse files
BusinessDuckDmitriy Yurov
andauthored
Mfi (#58)
* Update FUNDING.yml * MFI indicator implementation and unit tests for #46 * export MFI from package * add documentation about MFI * add moment value for MFI --------- Co-authored-by: Dmitriy Yurov <dyurov@tradingview.com>
1 parent a106b1e commit 5dadec0

36 files changed

+24549
-24213
lines changed

.github/FUNDING.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# These are supported funding model platforms
22

33
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4-
patreon: businessduck # Replace with a single Patreon username
4+
patreon: #businessduck # Replace with a single Patreon username
55
open_collective: debut-js # Replace with a single Open Collective username
66
ko_fi: # Replace with a single Ko-fi username
77
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ The main feature of these indicators is their continuous operation, which means
2828
- [Exponential Weighted Moving Average (EWMA)](./docs/ExponentialWeightedMovingAverage.md).
2929
- [Linearly Weighted Moving Average (LWMA)](./docs/LinearlyWeightedMovingAverage.md).
3030
- [Moving Average Convergence Divergence (MACD)](./docs/MovingAverageConvergenceDivergence.md).
31+
- [Money Flow Index (MFI)](./docs/MoneyFlowIndex.md).
3132
- [Pivot Point Levels (classic / woodie /camarilla / fibonacci)](./docs/PivotPointLevels.md).
3233
- [Rate of Change (ROC)](./docs/RateofChange.md).
3334
- [Relative Strength Index (RSI)](./docs/RelativeStrengthIndex.md).

docs/MoneyFlowIndex.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Money Flow Index (MFI)
2+
Money Flow Index (MFI) is a movement indicator used in technical analysis that looks at time and price to measure the trading pressure — buying or selling. It is also called volume-weighted Relative Strength Index (RSI), as it includes volume, unlike RSI, which only incorporates price.
3+
4+
## Key features
5+
6+
- The Money Flow Index (MFI) is a technical indicator that generates overbought or oversold signals using both prices and volume data.
7+
8+
- An MFI reading above 80 is considered overbought and an MFI reading below 20 is considered oversold, although levels of 90 and 10 are also used as thresholds.
9+
10+
- A divergence between the indicator and price is noteworthy. For example, if the indicator is rising while the price is falling or flat, the price could start rising.
11+
12+
## How to calculate Money Flow Index (MFI) in excel spreadsheet?
13+
14+
[Download excel sample](../tests/mfi/MoneyFlowIndex.xlsm)

index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export { SMMA } from './src/smma';
1313
export { RMA } from './src/rma';
1414
export { AO } from './src/ao';
1515
export { AC } from './src/ac';
16+
export { MFI } from './src/mfi';
1617
export { Move } from './src/move';
1718
export { Wave } from './src/wave';
1819
export { Stochastic } from './src/stochastic';
@@ -37,4 +38,4 @@ export { CircularBuffer } from './src/providers/circular-buffer';
3738
export { Sampler } from './src/providers/sampler';
3839
export { VolumeProfile } from './src/volume-profile'; /** BETA UNSTABLE */
3940
export { ChaikinOscillator } from './src/chaikin';
40-
// export { OrderBlock } from './src/order-block';
41+
// export { OrderBlock } from './src/order-block';

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"test": "jest",
4848
"version": "npm run build",
4949
"postversion": "git push && git push --tags",
50-
"prettier": "prettier --config './.prettierrc' --write 'src/**/*.ts'"
50+
"prettier": "prettier --config './.prettierrc' --write './**/*.ts'"
5151
},
5252
"bugs": {
5353
"url": "https://github.com/debut-js/Indicators/issues"

src/mfi.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { CircularBuffer } from './providers/circular-buffer';
2+
3+
/**
4+
* Money Flow Index (MFI) is a movement indicator used in technical analysis that looks at time and price
5+
* to measure the trading pressure — buying or selling. It is also called volume-weighted
6+
* Relative Strength Index (RSI), as it includes volume, unlike RSI, which only incorporates price.
7+
*/
8+
export class MFI {
9+
private positiveMoneyFlowSum = 0;
10+
private negativeMoneyFlowSum = 0;
11+
private pevTypicalPrice = 0;
12+
private posCircular: CircularBuffer;
13+
private negCircular: CircularBuffer;
14+
15+
constructor(period = 14) {
16+
this.posCircular = new CircularBuffer(period);
17+
this.negCircular = new CircularBuffer(period);
18+
}
19+
20+
nextValue(high: number, low: number, close: number, volume: number) {
21+
const typicalPrice = (high + low + close) / 3;
22+
const moneyFlow = typicalPrice * volume;
23+
24+
if (!this.pevTypicalPrice) {
25+
this.pevTypicalPrice = typicalPrice;
26+
return;
27+
}
28+
29+
const positiveMoneyFlow = typicalPrice > this.pevTypicalPrice ? moneyFlow : 0;
30+
const negativeMoneyFlow = typicalPrice < this.pevTypicalPrice ? moneyFlow : 0;
31+
32+
this.pevTypicalPrice = typicalPrice;
33+
this.negativeMoneyFlowSum += negativeMoneyFlow;
34+
this.positiveMoneyFlowSum += positiveMoneyFlow;
35+
36+
const posRedunant = this.posCircular.push(positiveMoneyFlow);
37+
const negRedunant = this.negCircular.push(negativeMoneyFlow);
38+
39+
if (!this.posCircular.filled) {
40+
return;
41+
}
42+
43+
this.negativeMoneyFlowSum -= negRedunant || 0;
44+
this.positiveMoneyFlowSum -= posRedunant || 0;
45+
46+
const moneyFlowRatio = this.positiveMoneyFlowSum / this.negativeMoneyFlowSum;
47+
48+
return 100 - 100 / (1 + moneyFlowRatio);
49+
}
50+
51+
momentValue(high: number, low: number, close: number, volume: number) {
52+
const typicalPrice = (high + low + close) / 3;
53+
const moneyFlow = typicalPrice * volume;
54+
55+
if (!this.pevTypicalPrice) {
56+
return;
57+
}
58+
59+
const positiveMoneyFlow = typicalPrice > this.pevTypicalPrice ? moneyFlow : 0;
60+
const negativeMoneyFlow = typicalPrice < this.pevTypicalPrice ? moneyFlow : 0;
61+
62+
if (!this.posCircular.filled) {
63+
return;
64+
}
65+
66+
const posRedunant = this.posCircular.peek();
67+
const negRedunant = this.negCircular.peek();
68+
const negativeMoneyFlowSum = this.negativeMoneyFlowSum + negativeMoneyFlow - negRedunant;
69+
const positiveMoneyFlowSum = this.positiveMoneyFlowSum + positiveMoneyFlow - posRedunant;
70+
const moneyFlowRatio = positiveMoneyFlowSum / negativeMoneyFlowSum;
71+
72+
return 100 - 100 / (1 + moneyFlowRatio);
73+
}
74+
}

src/providers/max-value.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ export class MaxProvider {
2323

2424
const rmMax = this.highest.push(high);
2525

26-
// Most perf degrade case
27-
if (rmMax === this.max && high !== this.max) {
26+
// Most perf degrade case
27+
if (rmMax === this.max && high !== this.max) {
2828
// console.count('degrade_max');
2929

3030
this.max = getMax(this.highest.toArray());
@@ -37,4 +37,3 @@ export class MaxProvider {
3737
return this.max > high ? this.max : high;
3838
}
3939
}
40-

src/stochastic-rsi.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { MinProvider } from './providers/min-value';
44
import { RSI } from './rsi';
55

66
/**
7-
* Developed by Tushar Chande and Stanley Kroll, StochRSI is an oscillator that measures the level of RSI relative
8-
* to its high-low range over a set time period. StochRSI applies the Stochastics formula to RSI values, rather
9-
* than price values, making it an indicator of an indicator. The result is an oscillator that
10-
* fluctuates between 0 and 1.
7+
* Developed by Tushar Chande and Stanley Kroll, StochRSI is an oscillator that measures the level of RSI relative
8+
* to its high-low range over a set time period. StochRSI applies the Stochastics formula to RSI values, rather
9+
* than price values, making it an indicator of an indicator. The result is an oscillator that
10+
* fluctuates between 0 and 1.
1111
*/
1212
export class StochasticRSI {
1313
private max: MaxProvider;
@@ -28,7 +28,7 @@ export class StochasticRSI {
2828
* Get next value for closed candle
2929
* affect all next calculations
3030
*/
31-
nextValue(close: number): { k: number, d: number, stochRsi: number } {
31+
nextValue(close: number): { k: number; d: number; stochRsi: number } {
3232
const rsi = this.rsi.nextValue(close);
3333

3434
if (rsi === undefined) {
@@ -37,7 +37,7 @@ export class StochasticRSI {
3737

3838
const max = this.max.nextValue(rsi);
3939
const min = this.min.nextValue(rsi);
40-
40+
4141
if (!this.max.filled()) {
4242
return;
4343
}
@@ -58,7 +58,7 @@ export class StochasticRSI {
5858
* Get next value for non closed (tick) candle hlc
5959
* does not affect any next calculations
6060
*/
61-
momentValue(close: number): { k: number, d: number, stochRsi: number} {
61+
momentValue(close: number): { k: number; d: number; stochRsi: number } {
6262
if (!this.max.filled()) {
6363
return;
6464
}

src/stochastic.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ export class Stochastic {
5151
const max = this.max.momentValue(high);
5252
const min = this.min.momentValue(low);
5353

54-
5554
const k: number = ((close - min) / (max - min)) * 100;
5655
const d: number = this.sma.momentValue(k);
5756

tests/ac/excel-data.ts

Lines changed: 10 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,16 @@
11
export const highs = [
2-
7150,
3-
7169,
4-
7278.2,
5-
7410,
6-
7500,
7-
7520,
8-
7535,
9-
7588,
10-
7584.6,
11-
7598,
12-
7647,
13-
7592,
14-
7598,
15-
7660.5,
16-
7668.4,
17-
7773.4,
18-
7791.55,
19-
7809.95,
20-
7796.7,
21-
7751.95,
22-
7822,
23-
7848.95,
24-
7800,
25-
7839.9,
26-
7790.15,
27-
7687.3,
28-
7670.7,
29-
7629.9,
30-
7743.5,
31-
7769,
32-
7926.8,
33-
7962,
34-
7996.5,
35-
8021.9,
36-
7980,
37-
7952,
38-
8029,
39-
8035.15,
40-
8037,
41-
7950,
42-
7874.45,
43-
7949.95,
44-
7789,
45-
7817.5,
46-
7770.6,
47-
7912.2,
48-
7933.55,
49-
7909.9,
50-
7939.4,
51-
7891.8,
52-
7898.1,
53-
7957.8,
2+
7150, 7169, 7278.2, 7410, 7500, 7520, 7535, 7588, 7584.6, 7598, 7647, 7592, 7598, 7660.5, 7668.4, 7773.4, 7791.55,
3+
7809.95, 7796.7, 7751.95, 7822, 7848.95, 7800, 7839.9, 7790.15, 7687.3, 7670.7, 7629.9, 7743.5, 7769, 7926.8, 7962,
4+
7996.5, 8021.9, 7980, 7952, 8029, 8035.15, 8037, 7950, 7874.45, 7949.95, 7789, 7817.5, 7770.6, 7912.2, 7933.55,
5+
7909.9, 7939.4, 7891.8, 7898.1, 7957.8,
546
];
557

568
export const lows = [
57-
7060,
58-
6884.85,
59-
7092.25,
60-
7344.15,
61-
7407,
62-
7443,
63-
7457.3,
64-
7451.75,
65-
7491.6,
66-
7508,
67-
7584.65,
68-
7532.15,
69-
7492,
70-
7545.1,
71-
7587.8,
72-
7672.15,
73-
7714,
74-
7738.8,
75-
7686.4,
76-
7676.65,
77-
7726.8,
78-
7783.3,
79-
7733.7,
80-
7767.15,
81-
7645,
82-
7639,
83-
7590.1,
84-
7584.8,
85-
7566,
86-
7717.15,
87-
7818.7,
88-
7885.3,
89-
7930.15,
90-
7924,
91-
7922,
92-
7867.6,
93-
7871.1,
94-
7991,
95-
7884,
96-
7831.1,
97-
7805.1,
98-
7770.1,
99-
7725,
100-
7733,
101-
7700.95,
102-
7775,
103-
7867.15,
104-
7798.2,
105-
7860.4,
106-
7787.3,
107-
7780.1,
108-
7896,
109-
]
9+
7060, 6884.85, 7092.25, 7344.15, 7407, 7443, 7457.3, 7451.75, 7491.6, 7508, 7584.65, 7532.15, 7492, 7545.1, 7587.8,
10+
7672.15, 7714, 7738.8, 7686.4, 7676.65, 7726.8, 7783.3, 7733.7, 7767.15, 7645, 7639, 7590.1, 7584.8, 7566, 7717.15,
11+
7818.7, 7885.3, 7930.15, 7924, 7922, 7867.6, 7871.1, 7991, 7884, 7831.1, 7805.1, 7770.1, 7725, 7733, 7700.95, 7775,
12+
7867.15, 7798.2, 7860.4, 7787.3, 7780.1, 7896,
13+
];
11014

11115
export const aoValues = [
11216
undefined,
@@ -161,4 +65,4 @@ export const aoValues = [
16165
28.34868,
16266
16.81946,
16367
8.91114,
164-
]
68+
];

0 commit comments

Comments
 (0)