@metaflux/fluxaction 0.1.3

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/src/index.ts ADDED
@@ -0,0 +1,138 @@
1
+ import type { ExchangeAdapter } from './core/exchange'
2
+ import { RiskManager } from './core/RiskManager'
3
+ import {
4
+ type TakeProfitOrder,
5
+ type StopLossOrder,
6
+ type TrailingStopOrder,
7
+ } from './core/logicalOrders'
8
+ import { GateSpotAdapter } from './exchanges/GateSpotAdapter'
9
+
10
+ export interface FluxActionConfig {
11
+ okx?: {
12
+ apiKey: string
13
+ secret: string
14
+ passphrase: string
15
+ isDemo?: boolean
16
+ }
17
+ gate?: {
18
+ apiKey: string
19
+ secret: string
20
+ }
21
+ risk?: {
22
+ pollIntervalMs?: number
23
+ }
24
+ }
25
+
26
+ export class FluxAction {
27
+ private adapters: Record<string, ExchangeAdapter> = {}
28
+ private risk: RiskManager
29
+
30
+ constructor(cfg: FluxActionConfig) {
31
+ if (cfg.gate) {
32
+ const gate = new GateSpotAdapter({
33
+ id: 'gate-spot',
34
+ apiKey: cfg.gate.apiKey,
35
+ secret: cfg.gate.secret,
36
+ })
37
+ this.adapters[gate.id] = gate
38
+ }
39
+
40
+ this.risk = new RiskManager({
41
+ exchanges: this.adapters,
42
+ pollIntervalMs: cfg.risk?.pollIntervalMs,
43
+ })
44
+ }
45
+
46
+ async init(): Promise<void> {
47
+ await Promise.all(Object.values(this.adapters).map((a) => a.loadMarkets()))
48
+ }
49
+
50
+ getExchange(id: string): ExchangeAdapter | undefined {
51
+ return this.adapters[id]
52
+ }
53
+
54
+ async openSpotPosition(params: {
55
+ exchangeId: string
56
+ symbol: string
57
+ quoteCost: number
58
+ }): Promise<{ orderId: string; filledBase: number; avgPrice: number }> {
59
+ const ex = this.requireExchange(params.exchangeId)
60
+ const order = await ex.marketBuySpot(params.symbol, params.quoteCost)
61
+
62
+ return {
63
+ orderId: order.id,
64
+ filledBase: order.amount,
65
+ avgPrice: order.price ?? 0,
66
+ }
67
+ }
68
+
69
+ async closeSpotMarket(params: {
70
+ exchangeId: string
71
+ symbol: string
72
+ baseQty: number
73
+ }): Promise<{ orderId: string }> {
74
+ const ex = this.requireExchange(params.exchangeId)
75
+ const order = await ex.marketSellSpot(params.symbol, params.baseQty)
76
+ return { orderId: order.id }
77
+ }
78
+
79
+ async placeSpotLimit(params: {
80
+ exchangeId: string
81
+ symbol: string
82
+ side: 'buy' | 'sell'
83
+ baseQty: number
84
+ price: number
85
+ }): Promise<{ orderId: string }> {
86
+ const ex = this.requireExchange(params.exchangeId)
87
+ const order = await ex.limitOrderSpot(
88
+ params.symbol,
89
+ params.side,
90
+ params.baseQty,
91
+ params.price,
92
+ )
93
+ return { orderId: order.id }
94
+ }
95
+
96
+ async placeTakeProfit(o: TakeProfitOrder): Promise<{ id: string }> {
97
+ await this.risk.placeTakeProfit(o)
98
+ return { id: o.id }
99
+ }
100
+
101
+ async placeStopLoss(o: StopLossOrder): Promise<{ id: string }> {
102
+ await this.risk.placeStopLoss(o)
103
+ return { id: o.id }
104
+ }
105
+
106
+ async placeTrailingStop(o: TrailingStopOrder): Promise<{ id: string }> {
107
+ await this.risk.placeTrailingStop(o)
108
+ return { id: o.id }
109
+ }
110
+
111
+ async cancelLogical(id: string): Promise<void> {
112
+ await this.risk.cancel(id)
113
+ }
114
+
115
+ getActiveLogicalOrders() {
116
+ return this.risk.getActiveOrders()
117
+ }
118
+
119
+ private requireExchange(id: string): ExchangeAdapter {
120
+ const ex = this.adapters[id]
121
+ if (!ex) throw new Error(`Exchange ${id} is not configured`)
122
+ return ex
123
+ }
124
+ }
125
+
126
+ export { RiskManager, type RiskManagerConfig } from './core/RiskManager'
127
+ export type {
128
+ ExchangeAdapter,
129
+ ExchangeCapabilities,
130
+ MarketInfo,
131
+ OrderInfo,
132
+ PositionInfo,
133
+ } from './core/exchange'
134
+
135
+ export {
136
+ GateSpotAdapter,
137
+ type GateSpotAdapterConfig,
138
+ } from './exchanges/GateSpotAdapter'
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ES2020",
5
+ "moduleResolution": "Node",
6
+ "declaration": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "resolveJsonModule": true,
12
+ "skipLibCheck": true
13
+ },
14
+ "include": ["src"]
15
+ }