@gera2ld/lib-trading 0.0.1

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.
@@ -0,0 +1,19 @@
1
+ import type { IBalance, IBaseOrder, ICalcOptions, IFeeMode } from './types.ts';
2
+ export declare function getOrderCost(price: number, quantity: number, options?: ICalcOptions): number;
3
+ export declare function calcOrderDelta(order: IBaseOrder, options?: ICalcOptions): {
4
+ deltaA: number;
5
+ deltaB: number;
6
+ };
7
+ export declare function calcBalance(balance: IBalance, options?: ICalcOptions): {
8
+ balanceA: number;
9
+ balanceB: number;
10
+ totalAsA: number;
11
+ totalAsB: number;
12
+ };
13
+ export declare function normalizeFeeOptions(options?: {
14
+ feeMode?: IFeeMode;
15
+ feeRate?: number;
16
+ }): {
17
+ feeMode: IFeeMode;
18
+ feeRate: number;
19
+ };
package/dist/grid.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ import type { IBaseOrder, ICalcOptions } from './types.ts';
2
+ export interface IGrid {
3
+ index: number;
4
+ price: number;
5
+ sellPrice: number;
6
+ }
7
+ export declare function createGrids(config: {
8
+ startPrice: number;
9
+ stopPrice: number;
10
+ minDifference: number;
11
+ minRatio: number;
12
+ maxCount: number;
13
+ precision: number;
14
+ }): IGrid[];
15
+ export declare function getGridRange(grids: IGrid[], options: {
16
+ enabledStartPrice?: number;
17
+ enabledStopPrice?: number;
18
+ placesPerSide?: number;
19
+ firstSellIndex?: number;
20
+ }): {
21
+ startIndex: number;
22
+ stopIndex: number;
23
+ actualStartIndex: number;
24
+ actualStopIndex: number;
25
+ };
26
+ export declare function getFirstSellIndex(grids: IGrid[], price: number): number;
27
+ export declare function getProfitRate(price: number, sellPrice: number, feeRate: number): number;
28
+ export declare function getGridProfit(buy: IBaseOrder | undefined, sell: IBaseOrder | undefined, options?: ICalcOptions): {
29
+ profitA: number;
30
+ profitB: number;
31
+ };
32
+ export declare function getBuyQuantity(quantity: number, options: ICalcOptions & {
33
+ precisionA?: number;
34
+ }): number;
35
+ export declare function getSellQuantity(quantity: number, options: ICalcOptions & {
36
+ precisionA?: number;
37
+ }): number;
38
+ export declare function matchOrders<T extends {
39
+ price: number;
40
+ }>(grids: IGrid[], firstSellIndex: number, buyOrders: T[], sellOrders: T[]): T[];
@@ -0,0 +1,3 @@
1
+ export * from './common';
2
+ export * from './grid';
3
+ export * from './types';
package/dist/index.js ADDED
@@ -0,0 +1,180 @@
1
+ import a from "bignumber.js";
2
+ function S(e, t, r) {
3
+ const o = r?.unitSize ?? 1;
4
+ let l = new a(o * t).abs();
5
+ return l = l[r?.marketType === "future-c" ? "div" : "times"](e), l.toNumber();
6
+ }
7
+ function w(e, t) {
8
+ let r = Math.sign(e.quantity);
9
+ t?.marketType === "future-c" && t?.positionSide === "short" && (r = -r);
10
+ const o = new a(e.quantity).abs().times(r), l = new a(
11
+ -r * S(e.price, e.quantity, t)
12
+ );
13
+ let n, c;
14
+ t?.marketType === "future-c" ? (n = l, c = o) : (n = o, c = l);
15
+ const { feeMode: i, feeRate: u } = P({
16
+ ...t,
17
+ ...e
18
+ });
19
+ return i === "A" || i === "buy" && r > 0 ? n = n.minus(n.abs().times(u)) : (i === "B" || i === "buy" && r < 0) && (c = c.minus(c.abs().times(u))), {
20
+ deltaA: n.toNumber(),
21
+ deltaB: c.toNumber()
22
+ };
23
+ }
24
+ function B(e, t) {
25
+ const r = t?.unitSize ?? 1;
26
+ let o = 0, l = 0;
27
+ if (e.price) {
28
+ const n = t?.positionSide === "short" ? -1 : 1;
29
+ let c, i = new a(e.balanceB);
30
+ t?.marketType === "future-c" ? (i = i.plus(e.balanceA * e.price / r), c = i.times(r).div(e.price)) : (i = i.plus(n * S(e.price, e.balanceA, t)), c = i.div(r).div(e.price).times(n)), o = c.toNumber(), l = i.toNumber();
31
+ }
32
+ return {
33
+ balanceA: e.balanceA,
34
+ balanceB: e.balanceB,
35
+ totalAsA: o,
36
+ totalAsB: l
37
+ };
38
+ }
39
+ function P(e) {
40
+ return {
41
+ feeMode: e?.feeMode ?? "buy",
42
+ feeRate: e?.feeRate ?? 0
43
+ };
44
+ }
45
+ function C(e) {
46
+ const {
47
+ startPrice: t,
48
+ stopPrice: r,
49
+ minDifference: o,
50
+ minRatio: l,
51
+ maxCount: n,
52
+ precision: c
53
+ } = e;
54
+ if (!o && l === 1 && !n)
55
+ throw new Error("Invalid grid config");
56
+ const i = {
57
+ totalCount: 0,
58
+ arithmeticCount: 0,
59
+ geometricStartPrice: new a(t)
60
+ };
61
+ let u = new a(t), s = !o;
62
+ for (; n && i.totalCount < n; ) {
63
+ let m = u.times(l);
64
+ if (!s) {
65
+ const p = u.plus(o);
66
+ p.lte(m) ? (s = !0, i.geometricStartPrice = u) : m = p;
67
+ }
68
+ if (m.gt(r)) break;
69
+ s || (i.arithmeticCount += 1), i.totalCount += 1, u = m;
70
+ }
71
+ s ? u.isEqualTo(t) || (i.geometricStartPrice = i.geometricStartPrice.minus(t).div(u.minus(t)).times(r - t).plus(t)) : i.geometricStartPrice = new a(r);
72
+ const h = [], x = i.arithmeticCount ? i.geometricStartPrice.minus(t).div(i.arithmeticCount) : 0, A = i.totalCount > i.arithmeticCount ? Math.pow(
73
+ r / i.geometricStartPrice.toNumber(),
74
+ 1 / (i.totalCount - i.arithmeticCount)
75
+ ) : 0;
76
+ let d = 0, f = new a(t);
77
+ for (; d < i.arithmeticCount; ) {
78
+ const m = +f.toFixed(c);
79
+ f = f.plus(x);
80
+ const p = +f.toFixed(c), g = {
81
+ index: d,
82
+ price: m,
83
+ sellPrice: p
84
+ };
85
+ h.push(g), d += 1;
86
+ }
87
+ for (; d < i.totalCount; ) {
88
+ const m = +f.toFixed(c);
89
+ f = f.times(A);
90
+ const p = +f.toFixed(c), g = {
91
+ index: d,
92
+ price: m,
93
+ sellPrice: p
94
+ };
95
+ h.push(g), d += 1;
96
+ }
97
+ return h;
98
+ }
99
+ function N(e, t) {
100
+ const { enabledStartPrice: r, enabledStopPrice: o, placesPerSide: l, firstSellIndex: n } = {
101
+ enabledStartPrice: 0,
102
+ enabledStopPrice: e.length,
103
+ firstSellIndex: -1,
104
+ ...t
105
+ };
106
+ let c = 0, i = e.length;
107
+ for (; c < e.length && e[c].price < r; )
108
+ c += 1;
109
+ if (o)
110
+ for (; i >= 0 && e[i].sellPrice > o; )
111
+ i -= 1;
112
+ let u = c, s = i;
113
+ return n >= 0 && l && (u = Math.max(
114
+ u,
115
+ n - l
116
+ ), s = Math.min(s, n + l)), { startIndex: c, stopIndex: i, actualStartIndex: u, actualStopIndex: s };
117
+ }
118
+ function y(e, t) {
119
+ let r = e.findIndex((o) => o.sellPrice >= t);
120
+ return r < 0 && (r = e.length), r;
121
+ }
122
+ function R(e, t, r) {
123
+ return t / e * (1 - r) - 1 / (1 - r);
124
+ }
125
+ function F(e, t, r) {
126
+ const o = e ? w(e, r) : { deltaA: 0, deltaB: 0 }, l = t ? w(t, r) : { deltaA: 0, deltaB: 0 };
127
+ return {
128
+ profitA: new a(o.deltaA).plus(l.deltaA).toNumber(),
129
+ profitB: new a(o.deltaB).plus(l.deltaB).toNumber()
130
+ };
131
+ }
132
+ function M(e, t) {
133
+ const { feeMode: r, feeRate: o } = P(t);
134
+ return t.marketType !== "future-c" && ["buy", "A"].includes(r) && (e /= 1 - o), t.precisionA && (e = +new a(e).toFixed(
135
+ t.precisionA,
136
+ a.ROUND_UP
137
+ )), e;
138
+ }
139
+ function I(e, t) {
140
+ const { feeMode: r, feeRate: o } = P(t);
141
+ return t.marketType !== "future-c" && r === "A" && (e /= 1 + o), t.precisionA && (e = +new a(e).toFixed(
142
+ t.precisionA,
143
+ a.ROUND_DOWN
144
+ )), e;
145
+ }
146
+ function O(e, t, r, o) {
147
+ const l = [];
148
+ r.sort((c, i) => c.price - i.price), o.sort((c, i) => i.price - c.price);
149
+ let n = 0;
150
+ for (const c of r) {
151
+ for (; n < e.length && (e[n].price < c.price || l[n]); )
152
+ n += 1;
153
+ if (n >= e.length || n >= t)
154
+ throw new Error(`Unmatched order: ${JSON.stringify(c)}`);
155
+ l[n] = c;
156
+ }
157
+ n = e.length - 1;
158
+ for (const c of o) {
159
+ for (; n >= 0 && (e[n].sellPrice > c.price || l[n]); )
160
+ n -= 1;
161
+ if (n < 0 || n < t)
162
+ throw new Error(`Unmatched order: ${JSON.stringify(c)}`);
163
+ l[n] = c;
164
+ }
165
+ return l;
166
+ }
167
+ export {
168
+ B as calcBalance,
169
+ w as calcOrderDelta,
170
+ C as createGrids,
171
+ M as getBuyQuantity,
172
+ y as getFirstSellIndex,
173
+ F as getGridProfit,
174
+ N as getGridRange,
175
+ S as getOrderCost,
176
+ R as getProfitRate,
177
+ I as getSellQuantity,
178
+ O as matchOrders,
179
+ P as normalizeFeeOptions
180
+ };
@@ -0,0 +1,24 @@
1
+ export type IPositionSide = '' | 'long' | 'short';
2
+ export type IMarketType = 'spot' | 'future-u' | 'future-c';
3
+ export type IFeeMode = 'buy' | 'free' | 'A' | 'B';
4
+ export interface IBaseOrder {
5
+ price: number;
6
+ quantity: number;
7
+ }
8
+ export interface ICalcOptions {
9
+ unitSize?: number;
10
+ /** Default as 'spot' */
11
+ marketType?: IMarketType;
12
+ /** Default as '' for spot, 'long' for futures */
13
+ positionSide?: IPositionSide;
14
+ /** Default as 'buy' */
15
+ feeMode?: IFeeMode;
16
+ /** Default as 0 */
17
+ feeRate?: number;
18
+ }
19
+ export interface IBalance {
20
+ balanceA: number;
21
+ balanceB: number;
22
+ price: number;
23
+ usdValue: number;
24
+ }
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@gera2ld/lib-trading",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "import": "./dist/index.js",
8
+ "types": "./dist/index.d.ts"
9
+ }
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "registry": "https://registry.npmjs.org/"
17
+ },
18
+ "dependencies": {
19
+ "bignumber.js": "^9.3.1"
20
+ },
21
+ "scripts": {
22
+ "clean": "del-cli dist tsconfig.tsbuildinfo",
23
+ "build:types": "tsc",
24
+ "build:js": "vite build",
25
+ "build": "pnpm clean && pnpm /^build:/"
26
+ }
27
+ }