finmagic 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/jest.config.cjs +0 -9
- package/rollup.config.ts +0 -29
- package/src/financial.ts +0 -29
- package/src/index.ts +0 -7
- package/src/moving.ts +0 -10
- package/src/price.ts +0 -11
- package/src/ratios.ts +0 -25
- package/src/risk.ts +0 -16
- package/src/statistics.ts +0 -12
- package/src/volume.ts +0 -12
- package/tests/financial.test.ts +0 -20
- package/tests/moving.test.ts +0 -11
- package/tests/price.test.ts +0 -17
- package/tests/ratios.test.ts +0 -28
- package/tests/risk.test.ts +0 -20
- package/tests/statistics.test.ts +0 -11
- package/tests/volume.test.ts +0 -16
- package/tsconfig.json +0 -13
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "finmagic",
|
|
3
3
|
"author": "Mohammad Esmaeilzadeh",
|
|
4
4
|
"description": "A TypeScript library for essential financial, technical, and statistical calculations.",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.2",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
"main": "dist/index.cjs.js",
|
|
30
30
|
"module": "dist/index.esm.js",
|
|
31
31
|
"types": "dist/index.d.ts",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
32
35
|
"scripts": {
|
|
33
36
|
"build": "rollup -c",
|
|
34
37
|
"test": "jest"
|
package/jest.config.cjs
DELETED
package/rollup.config.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import typescript from '@rollup/plugin-typescript';
|
|
2
|
-
import resolve from '@rollup/plugin-node-resolve';
|
|
3
|
-
|
|
4
|
-
export default [
|
|
5
|
-
{
|
|
6
|
-
input: 'src/index.ts',
|
|
7
|
-
output: {
|
|
8
|
-
file: 'dist/index.esm.js',
|
|
9
|
-
format: 'esm',
|
|
10
|
-
sourcemap: true
|
|
11
|
-
},
|
|
12
|
-
plugins: [
|
|
13
|
-
resolve(),
|
|
14
|
-
typescript({ tsconfig: './tsconfig.json' })
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
input: 'src/index.ts',
|
|
19
|
-
output: {
|
|
20
|
-
file: 'dist/index.cjs.js',
|
|
21
|
-
format: 'cjs',
|
|
22
|
-
sourcemap: true
|
|
23
|
-
},
|
|
24
|
-
plugins: [
|
|
25
|
-
resolve(),
|
|
26
|
-
typescript({ tsconfig: './tsconfig.json' })
|
|
27
|
-
]
|
|
28
|
-
}
|
|
29
|
-
];
|
package/src/financial.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export const PV = (futureValue: number, rate: number, periods: number): number => {
|
|
2
|
-
return futureValue / Math.pow(1 + rate, periods);
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export const FV = (presentValue: number, rate: number, periods: number): number => {
|
|
6
|
-
return presentValue * Math.pow(1 + rate, periods);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const NPV = (rate: number, cashFlows: number[]): number => {
|
|
10
|
-
return cashFlows.reduce((acc, cf, i) => acc + cf / Math.pow(1 + rate, i + 1), 0);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const IRR = (cashFlows: number[], guess = 0.1): number => {
|
|
14
|
-
let rate = guess;
|
|
15
|
-
let iteration = 0;
|
|
16
|
-
const maxIter = 1000;
|
|
17
|
-
const tol = 1e-6;
|
|
18
|
-
|
|
19
|
-
while (iteration < maxIter) {
|
|
20
|
-
const npv = cashFlows.reduce((acc, cf, i) => acc + cf / Math.pow(1 + rate, i), 0);
|
|
21
|
-
const derivative = cashFlows.reduce((acc, cf, i) => acc - (i * cf) / Math.pow(1 + rate, i + 1), 0);
|
|
22
|
-
const newRate = rate - npv / derivative;
|
|
23
|
-
if (Math.abs(newRate - rate) < tol) break;
|
|
24
|
-
rate = newRate;
|
|
25
|
-
iteration++;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return rate;
|
|
29
|
-
}
|
package/src/index.ts
DELETED
package/src/moving.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export const SMA = (data: number[], period: number): number => {
|
|
2
|
-
const slice = data.slice(-period);
|
|
3
|
-
const sum = slice.reduce((a, b) => a + b, 0);
|
|
4
|
-
return sum / slice.length;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export const EMA = (data: number[], period: number): number => {
|
|
8
|
-
const k = 2 / (period + 1);
|
|
9
|
-
return data.reduce((prev, curr) => curr * k + prev * (1 - k));
|
|
10
|
-
}
|
package/src/price.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const percentChange = (current: number, previous: number): number => {
|
|
2
|
-
return ((current - previous) / previous) * 100;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export const dailyReturn = (current: number, previous: number): number => {
|
|
6
|
-
return percentChange(current, previous);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const cumulativeReturn = (returns: number[]): number => {
|
|
10
|
-
return returns.reduce((acc, r) => acc * (1 + r / 100), 1) - 1;
|
|
11
|
-
}
|
package/src/ratios.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export const PE = (price: number, eps: number): number => {
|
|
2
|
-
return price / eps;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export const PB = (price: number, bookValue: number): number => {
|
|
6
|
-
return price / bookValue;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const DividendYield = (dividend: number, price: number): number => {
|
|
10
|
-
return (dividend / price) * 100;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const Beta = (covariance: number, marketVariance: number): number => {
|
|
14
|
-
return covariance / marketVariance;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const Alpha = (actualReturn: number, expectedReturn: number): number => {
|
|
18
|
-
return actualReturn - expectedReturn;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const Sharpe = (returns: number[], riskFreeRate = 0): number => {
|
|
22
|
-
const avg = returns.reduce((a, b) => a + b, 0) / returns.length;
|
|
23
|
-
const std = Math.sqrt(returns.reduce((a, b) => a + Math.pow(b - avg, 2), 0) / returns.length);
|
|
24
|
-
return (avg - riskFreeRate) / std;
|
|
25
|
-
}
|
package/src/risk.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export const volatility = (returns: number[]): number => {
|
|
2
|
-
const mean = returns.reduce((a, b) => a + b, 0) / returns.length;
|
|
3
|
-
return Math.sqrt(returns.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / returns.length);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export const positionSizing = (accountBalance: number, riskPercent: number, stopLossDistance: number): number => {
|
|
7
|
-
return (accountBalance * riskPercent) / stopLossDistance;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const stopLoss = (entryPrice: number, riskDistance: number): number => {
|
|
11
|
-
return entryPrice - riskDistance;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const takeProfit = (entryPrice: number, profitDistance: number): number => {
|
|
15
|
-
return entryPrice + profitDistance;
|
|
16
|
-
}
|
package/src/statistics.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export const covariance = (a: number[], b: number[]): number => {
|
|
2
|
-
const meanA = a.reduce((x, y) => x + y, 0) / a.length;
|
|
3
|
-
const meanB = b.reduce((x, y) => x + y, 0) / b.length;
|
|
4
|
-
return a.reduce((acc, val, i) => acc + (val - meanA) * (b[i] - meanB), 0) / a.length;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export const correlation = (a: number[], b: number[]): number => {
|
|
8
|
-
const cov = covariance(a, b);
|
|
9
|
-
const stdA = Math.sqrt(a.reduce((acc, val) => acc + Math.pow(val - a.reduce((x,y)=>x+y,0)/a.length,2),0)/a.length);
|
|
10
|
-
const stdB = Math.sqrt(b.reduce((acc, val) => acc + Math.pow(val - b.reduce((x,y)=>x+y,0)/b.length,2),0)/b.length);
|
|
11
|
-
return cov / (stdA * stdB);
|
|
12
|
-
}
|
package/src/volume.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export const VWAP = (prices: number[], volumes: number[]): number => {
|
|
2
|
-
const totalVolume = volumes.reduce((a, b) => a + b, 0);
|
|
3
|
-
const weightedSum = prices.reduce((sum, price, i) => sum + price * volumes[i], 0);
|
|
4
|
-
return weightedSum / totalVolume;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export const accumulationDistribution = (priceClose: number[], priceOpen: number[], volume: number[]): number => {
|
|
8
|
-
return priceClose.reduce((acc, close, i) => {
|
|
9
|
-
const mfm = ((close - priceOpen[i]) / (priceClose[i] - priceOpen[i])) || 0;
|
|
10
|
-
return acc + mfm * volume[i];
|
|
11
|
-
}, 0);
|
|
12
|
-
}
|
package/tests/financial.test.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { PV, FV, NPV, IRR } from '../src/financial';
|
|
2
|
-
|
|
3
|
-
describe('Financial calculations', () => {
|
|
4
|
-
test('PV calculates present value', () => {
|
|
5
|
-
expect(PV(1000, 0.1, 5)).toBeCloseTo(620.921, 2);
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
test('FV calculates future value', () => {
|
|
9
|
-
expect(FV(1000, 0.1, 5)).toBeCloseTo(1610.51, 2);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test('NPV calculates net present value', () => {
|
|
13
|
-
expect(NPV(0.1, [-1000, 200, 300, 500])).toBeCloseTo(-176.9, 1);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('IRR calculates internal rate of return', () => {
|
|
17
|
-
const rate = IRR([-1000, 200, 300, 500]);
|
|
18
|
-
expect(rate).toBeCloseTo(-0.000000668, 6);
|
|
19
|
-
});
|
|
20
|
-
});
|
package/tests/moving.test.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { SMA, EMA } from '../src/moving';
|
|
2
|
-
|
|
3
|
-
describe('Moving averages', () => {
|
|
4
|
-
test('SMA calculates simple moving average', () => {
|
|
5
|
-
expect(SMA([1,2,3,4,5], 5)).toBe(3);
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
test('EMA calculates exponential moving average', () => {
|
|
9
|
-
expect(EMA([1,2,3,4,5], 3)).toBeCloseTo(4.0625, 4);
|
|
10
|
-
});
|
|
11
|
-
});
|
package/tests/price.test.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { percentChange, dailyReturn, cumulativeReturn } from '../src/price';
|
|
2
|
-
|
|
3
|
-
describe('Price calculations', () => {
|
|
4
|
-
test('percentChange calculates correct percentage', () => {
|
|
5
|
-
expect(percentChange(110, 100)).toBe(10);
|
|
6
|
-
expect(percentChange(90, 100)).toBe(-10);
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
test('dailyReturn uses percentChange', () => {
|
|
10
|
-
expect(dailyReturn(105, 100)).toBe(5);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('cumulativeReturn calculates cumulative growth', () => {
|
|
14
|
-
const returns = [5, 3, 2];
|
|
15
|
-
expect(cumulativeReturn(returns)).toBeCloseTo(0.107);
|
|
16
|
-
});
|
|
17
|
-
});
|
package/tests/ratios.test.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { PE, PB, DividendYield, Beta, Alpha, Sharpe } from '../src/ratios';
|
|
2
|
-
|
|
3
|
-
describe('Financial ratios', () => {
|
|
4
|
-
test('PE ratio', () => {
|
|
5
|
-
expect(PE(50,5)).toBe(10);
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
test('PB ratio', () => {
|
|
9
|
-
expect(PB(50,20)).toBe(2.5);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test('DividendYield', () => {
|
|
13
|
-
expect(DividendYield(2,50)).toBe(4);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('Beta calculation', () => {
|
|
17
|
-
expect(Beta(0.2,0.1)).toBe(2);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test('Alpha calculation', () => {
|
|
21
|
-
expect(Alpha(0.15,0.1)).toBeCloseTo(0.049999, 5);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('Sharpe ratio', () => {
|
|
25
|
-
const returns = [0.01,0.02,0.03];
|
|
26
|
-
expect(Sharpe(returns)).toBeCloseTo(2.4495, 4);
|
|
27
|
-
});
|
|
28
|
-
});
|
package/tests/risk.test.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { volatility, positionSizing, stopLoss, takeProfit } from '../src/risk';
|
|
2
|
-
|
|
3
|
-
describe('Risk management', () => {
|
|
4
|
-
test('volatility calculation', () => {
|
|
5
|
-
const returns = [0.01, -0.02, 0.03];
|
|
6
|
-
expect(volatility(returns)).toBeCloseTo(0.025, 2);
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
test('positionSizing', () => {
|
|
10
|
-
expect(positionSizing(10000,0.02,5)).toBe(40);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('stopLoss', () => {
|
|
14
|
-
expect(stopLoss(100,5)).toBe(95);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test('takeProfit', () => {
|
|
18
|
-
expect(takeProfit(100,10)).toBe(110);
|
|
19
|
-
});
|
|
20
|
-
});
|
package/tests/statistics.test.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { covariance, correlation } from '../src/statistics';
|
|
2
|
-
|
|
3
|
-
describe('Statistics', () => {
|
|
4
|
-
test('covariance', () => {
|
|
5
|
-
expect(covariance([1,2,3],[4,5,6])).toBe(0.6666666666666666);
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
test('correlation', () => {
|
|
9
|
-
expect(correlation([1,2,3],[4,5,6])).toBeCloseTo(1,2);
|
|
10
|
-
});
|
|
11
|
-
});
|
package/tests/volume.test.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { VWAP, accumulationDistribution } from '../src/volume';
|
|
2
|
-
|
|
3
|
-
describe('Volume calculations', () => {
|
|
4
|
-
test('VWAP calculation', () => {
|
|
5
|
-
const prices = [100,102,101];
|
|
6
|
-
const volumes = [50,60,40];
|
|
7
|
-
expect(VWAP(prices, volumes)).toBeCloseTo(101.0666666667, 4);
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
test('AccumulationDistribution', () => {
|
|
11
|
-
const close = [10,12];
|
|
12
|
-
const open = [9,11];
|
|
13
|
-
const volume = [100,200];
|
|
14
|
-
expect(accumulationDistribution(close, open, volume)).toBe(300);
|
|
15
|
-
});
|
|
16
|
-
});
|
package/tsconfig.json
DELETED