@ael-protocol/sdk 0.1.0 → 0.2.0
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/dist/abi/market.d.ts +394 -0
- package/dist/abi/market.d.ts.map +1 -0
- package/dist/abi/market.js +264 -0
- package/dist/abi/market.js.map +1 -0
- package/dist/agent-wallet.d.ts +79 -0
- package/dist/agent-wallet.d.ts.map +1 -0
- package/dist/agent-wallet.js +483 -0
- package/dist/agent-wallet.js.map +1 -0
- package/dist/hub.d.ts +125 -0
- package/dist/hub.d.ts.map +1 -0
- package/dist/hub.js +237 -0
- package/dist/hub.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +39 -1
- package/dist/index.js.map +1 -1
- package/dist/market.d.ts +73 -0
- package/dist/market.d.ts.map +1 -0
- package/dist/market.js +388 -0
- package/dist/market.js.map +1 -0
- package/dist/marketplace.d.ts +137 -0
- package/dist/marketplace.d.ts.map +1 -0
- package/dist/marketplace.js +479 -0
- package/dist/marketplace.js.map +1 -0
- package/dist/networks.d.ts +66 -0
- package/dist/networks.d.ts.map +1 -0
- package/dist/networks.js +106 -0
- package/dist/networks.js.map +1 -0
- package/dist/parser.d.ts +39 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +134 -0
- package/dist/parser.js.map +1 -0
- package/dist/strategies/dca.d.ts +39 -0
- package/dist/strategies/dca.d.ts.map +1 -0
- package/dist/strategies/dca.js +124 -0
- package/dist/strategies/dca.js.map +1 -0
- package/dist/strategies/grid.d.ts +54 -0
- package/dist/strategies/grid.d.ts.map +1 -0
- package/dist/strategies/grid.js +161 -0
- package/dist/strategies/grid.js.map +1 -0
- package/dist/strategies/stop-loss.d.ts +55 -0
- package/dist/strategies/stop-loss.d.ts.map +1 -0
- package/dist/strategies/stop-loss.js +152 -0
- package/dist/strategies/stop-loss.js.map +1 -0
- package/dist/strategy.d.ts +72 -0
- package/dist/strategy.d.ts.map +1 -0
- package/dist/strategy.js +78 -0
- package/dist/strategy.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Grid Trading Strategy
|
|
4
|
+
* Places buy orders below current price and sell orders above
|
|
5
|
+
* Profits from price oscillation within a range
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.GridStrategy = void 0;
|
|
9
|
+
const strategy_1 = require("../strategy");
|
|
10
|
+
class GridStrategy extends strategy_1.Strategy {
|
|
11
|
+
wallet;
|
|
12
|
+
marketFeed;
|
|
13
|
+
levels = [];
|
|
14
|
+
buys = 0;
|
|
15
|
+
sells = 0;
|
|
16
|
+
profit = 0;
|
|
17
|
+
currentPrice;
|
|
18
|
+
lastPrice;
|
|
19
|
+
baseToken;
|
|
20
|
+
quoteToken;
|
|
21
|
+
amountPerGrid;
|
|
22
|
+
amountToken;
|
|
23
|
+
constructor(wallet, marketFeed, config) {
|
|
24
|
+
super(config);
|
|
25
|
+
this.wallet = wallet;
|
|
26
|
+
this.marketFeed = marketFeed;
|
|
27
|
+
// Parse pair
|
|
28
|
+
const [base, quote] = config.pair.split(/[\/\-]/).map(t => t.toUpperCase());
|
|
29
|
+
this.baseToken = base;
|
|
30
|
+
this.quoteToken = quote;
|
|
31
|
+
// Parse amount
|
|
32
|
+
const { amount, token } = this.parseAmount(config.amountPerGrid);
|
|
33
|
+
this.amountPerGrid = parseFloat(amount);
|
|
34
|
+
this.amountToken = token;
|
|
35
|
+
// Initialize grid levels
|
|
36
|
+
this.initializeLevels();
|
|
37
|
+
}
|
|
38
|
+
initializeLevels() {
|
|
39
|
+
const { upperPrice, lowerPrice, gridCount } = this.config;
|
|
40
|
+
const step = (upperPrice - lowerPrice) / gridCount;
|
|
41
|
+
this.levels = [];
|
|
42
|
+
for (let i = 0; i <= gridCount; i++) {
|
|
43
|
+
this.levels.push({
|
|
44
|
+
price: lowerPrice + (step * i),
|
|
45
|
+
status: 'open',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
start() {
|
|
50
|
+
if (this._running)
|
|
51
|
+
return;
|
|
52
|
+
this._running = true;
|
|
53
|
+
this._startedAt = Date.now();
|
|
54
|
+
// Start watching price
|
|
55
|
+
this.marketFeed.watch(this.config.pair, { interval: 10 }, (priceData) => this.onPriceUpdate(priceData));
|
|
56
|
+
}
|
|
57
|
+
stop() {
|
|
58
|
+
super.stop();
|
|
59
|
+
this.marketFeed.unwatch(this.config.pair);
|
|
60
|
+
}
|
|
61
|
+
status() {
|
|
62
|
+
return {
|
|
63
|
+
running: this._running,
|
|
64
|
+
startedAt: this._startedAt,
|
|
65
|
+
tradesCompleted: this._tradesCompleted,
|
|
66
|
+
buys: this.buys,
|
|
67
|
+
sells: this.sells,
|
|
68
|
+
profit: `${this.profit.toFixed(6)} ${this.quoteToken}`,
|
|
69
|
+
currentPrice: this.currentPrice,
|
|
70
|
+
levels: [...this.levels],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async onPriceUpdate(priceData) {
|
|
74
|
+
if (!this._running)
|
|
75
|
+
return;
|
|
76
|
+
const newPrice = priceData.price;
|
|
77
|
+
this.currentPrice = newPrice;
|
|
78
|
+
this.emit('priceUpdate', priceData);
|
|
79
|
+
// Skip if no previous price (first update)
|
|
80
|
+
if (this.lastPrice === undefined) {
|
|
81
|
+
this.lastPrice = newPrice;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// Check for level crossings
|
|
85
|
+
try {
|
|
86
|
+
await this.checkLevelCrossings(this.lastPrice, newPrice);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
90
|
+
}
|
|
91
|
+
this.lastPrice = newPrice;
|
|
92
|
+
}
|
|
93
|
+
async checkLevelCrossings(oldPrice, newPrice) {
|
|
94
|
+
for (const level of this.levels) {
|
|
95
|
+
// Price crossed down through level (buy signal)
|
|
96
|
+
if (oldPrice > level.price && newPrice <= level.price) {
|
|
97
|
+
if (level.status === 'open' || level.status === 'filled-sell') {
|
|
98
|
+
await this.executeBuy(level, newPrice);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Price crossed up through level (sell signal)
|
|
102
|
+
else if (oldPrice < level.price && newPrice >= level.price) {
|
|
103
|
+
if (level.status === 'filled-buy') {
|
|
104
|
+
await this.executeSell(level, newPrice);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async executeBuy(level, price) {
|
|
110
|
+
try {
|
|
111
|
+
// Calculate USDC amount needed to buy the grid amount of ETH
|
|
112
|
+
const usdcAmount = this.amountPerGrid * price;
|
|
113
|
+
const tradeStr = `${usdcAmount.toFixed(6)} ${this.quoteToken} -> ${this.baseToken}`;
|
|
114
|
+
const result = await this.wallet.trade(tradeStr);
|
|
115
|
+
level.status = 'filled-buy';
|
|
116
|
+
level.lastTradeAt = Date.now();
|
|
117
|
+
this.buys++;
|
|
118
|
+
this._tradesCompleted++;
|
|
119
|
+
// Track cost for profit calculation
|
|
120
|
+
level.buyPrice = price;
|
|
121
|
+
level.buyAmount = parseFloat(result.amountOut);
|
|
122
|
+
this.emit('trade', result);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async executeSell(level, price) {
|
|
129
|
+
try {
|
|
130
|
+
const buyAmount = level.buyAmount || this.amountPerGrid;
|
|
131
|
+
const tradeStr = `${buyAmount} ${this.baseToken} -> ${this.quoteToken}`;
|
|
132
|
+
const result = await this.wallet.trade(tradeStr);
|
|
133
|
+
// Calculate profit
|
|
134
|
+
const buyPrice = level.buyPrice || level.price;
|
|
135
|
+
const sellAmount = parseFloat(result.amountOut);
|
|
136
|
+
const buyAmount2 = level.buyAmount || this.amountPerGrid;
|
|
137
|
+
const buyCost = buyAmount2 * buyPrice;
|
|
138
|
+
this.profit += sellAmount - buyCost;
|
|
139
|
+
level.status = 'filled-sell';
|
|
140
|
+
level.lastTradeAt = Date.now();
|
|
141
|
+
this.sells++;
|
|
142
|
+
this._tradesCompleted++;
|
|
143
|
+
this.emit('trade', result);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Reset all levels to open state
|
|
151
|
+
*/
|
|
152
|
+
reset() {
|
|
153
|
+
this.initializeLevels();
|
|
154
|
+
this.buys = 0;
|
|
155
|
+
this.sells = 0;
|
|
156
|
+
this.profit = 0;
|
|
157
|
+
this._tradesCompleted = 0;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
exports.GridStrategy = GridStrategy;
|
|
161
|
+
//# sourceMappingURL=grid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.js","sourceRoot":"","sources":["../../src/strategies/grid.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stop-Loss / Take-Profit Strategy
|
|
3
|
+
* Protects positions with stop-loss, take-profit, and trailing stop
|
|
4
|
+
*/
|
|
5
|
+
import { Strategy, StrategyConfig, StrategyStatus } from '../strategy';
|
|
6
|
+
import type { AgentWallet } from '../agent-wallet';
|
|
7
|
+
import type { MarketFeed } from '../market';
|
|
8
|
+
export interface StopLossConfig extends StrategyConfig {
|
|
9
|
+
position: string;
|
|
10
|
+
stopLoss?: number;
|
|
11
|
+
takeProfit?: number;
|
|
12
|
+
trailingStop?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface StopLossStatus extends StrategyStatus {
|
|
15
|
+
position: string;
|
|
16
|
+
currentPrice?: number;
|
|
17
|
+
highestPrice?: number;
|
|
18
|
+
trailingStopPrice?: number;
|
|
19
|
+
triggered: boolean;
|
|
20
|
+
triggerType?: 'stop-loss' | 'take-profit' | 'trailing-stop';
|
|
21
|
+
triggerPrice?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare class StopLossStrategy extends Strategy<StopLossConfig, StopLossStatus> {
|
|
24
|
+
private wallet;
|
|
25
|
+
private marketFeed;
|
|
26
|
+
private positionAmount;
|
|
27
|
+
private positionToken;
|
|
28
|
+
private quoteToken;
|
|
29
|
+
private currentPrice?;
|
|
30
|
+
private highestPrice?;
|
|
31
|
+
private triggered;
|
|
32
|
+
private triggerType?;
|
|
33
|
+
private triggerPrice?;
|
|
34
|
+
private triggerResult?;
|
|
35
|
+
constructor(wallet: AgentWallet, marketFeed: MarketFeed, config: StopLossConfig);
|
|
36
|
+
start(): void;
|
|
37
|
+
stop(): void;
|
|
38
|
+
status(): StopLossStatus;
|
|
39
|
+
private calculateTrailingStopPrice;
|
|
40
|
+
private onPriceUpdate;
|
|
41
|
+
private trigger;
|
|
42
|
+
/**
|
|
43
|
+
* Update stop-loss price while running
|
|
44
|
+
*/
|
|
45
|
+
updateStopLoss(price: number): void;
|
|
46
|
+
/**
|
|
47
|
+
* Update take-profit price while running
|
|
48
|
+
*/
|
|
49
|
+
updateTakeProfit(price: number): void;
|
|
50
|
+
/**
|
|
51
|
+
* Update trailing stop percentage while running
|
|
52
|
+
*/
|
|
53
|
+
updateTrailingStop(percentage: number): void;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=stop-loss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop-loss.d.ts","sourceRoot":"","sources":["../../src/strategies/stop-loss.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,WAAW,CAAC;AAEvD,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,eAAe,CAAC;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,gBAAiB,SAAQ,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAC5E,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,UAAU,CAAa;IAE/B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,WAAW,CAAC,CAAgD;IACpE,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAC,CAAc;gBAExB,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc;IAwB/E,KAAK,IAAI,IAAI;IAgBJ,IAAI,IAAI,IAAI;IAKrB,MAAM,IAAI,cAAc;IAiBxB,OAAO,CAAC,0BAA0B;YAOpB,aAAa;YAsCb,OAAO;IA0BrB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAG7C"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stop-Loss / Take-Profit Strategy
|
|
4
|
+
* Protects positions with stop-loss, take-profit, and trailing stop
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.StopLossStrategy = void 0;
|
|
8
|
+
const strategy_1 = require("../strategy");
|
|
9
|
+
class StopLossStrategy extends strategy_1.Strategy {
|
|
10
|
+
wallet;
|
|
11
|
+
marketFeed;
|
|
12
|
+
positionAmount;
|
|
13
|
+
positionToken;
|
|
14
|
+
quoteToken;
|
|
15
|
+
currentPrice;
|
|
16
|
+
highestPrice;
|
|
17
|
+
triggered = false;
|
|
18
|
+
triggerType;
|
|
19
|
+
triggerPrice;
|
|
20
|
+
triggerResult;
|
|
21
|
+
constructor(wallet, marketFeed, config) {
|
|
22
|
+
super(config);
|
|
23
|
+
this.wallet = wallet;
|
|
24
|
+
this.marketFeed = marketFeed;
|
|
25
|
+
// Validate at least one trigger is set
|
|
26
|
+
if (!config.stopLoss && !config.takeProfit && !config.trailingStop) {
|
|
27
|
+
throw new Error('At least one of stopLoss, takeProfit, or trailingStop must be set');
|
|
28
|
+
}
|
|
29
|
+
// Parse position
|
|
30
|
+
const { amount, token } = this.parseAmount(config.position);
|
|
31
|
+
this.positionAmount = parseFloat(amount);
|
|
32
|
+
this.positionToken = token;
|
|
33
|
+
// Parse pair for quote token
|
|
34
|
+
const [base, quote] = config.pair.split(/[\/\-]/).map(t => t.toUpperCase());
|
|
35
|
+
this.quoteToken = quote;
|
|
36
|
+
if (this.positionToken !== base) {
|
|
37
|
+
throw new Error(`Position token ${this.positionToken} must match pair base token ${base}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
start() {
|
|
41
|
+
if (this._running)
|
|
42
|
+
return;
|
|
43
|
+
this._running = true;
|
|
44
|
+
this._startedAt = Date.now();
|
|
45
|
+
this.triggered = false;
|
|
46
|
+
this.highestPrice = undefined;
|
|
47
|
+
// Start watching price
|
|
48
|
+
this.marketFeed.watch(this.config.pair, { interval: 5 }, // Check every 5 seconds for stop-loss
|
|
49
|
+
(priceData) => this.onPriceUpdate(priceData));
|
|
50
|
+
}
|
|
51
|
+
stop() {
|
|
52
|
+
super.stop();
|
|
53
|
+
this.marketFeed.unwatch(this.config.pair);
|
|
54
|
+
}
|
|
55
|
+
status() {
|
|
56
|
+
const trailingStopPrice = this.calculateTrailingStopPrice();
|
|
57
|
+
return {
|
|
58
|
+
running: this._running,
|
|
59
|
+
startedAt: this._startedAt,
|
|
60
|
+
tradesCompleted: this._tradesCompleted,
|
|
61
|
+
position: `${this.positionAmount} ${this.positionToken}`,
|
|
62
|
+
currentPrice: this.currentPrice,
|
|
63
|
+
highestPrice: this.highestPrice,
|
|
64
|
+
trailingStopPrice,
|
|
65
|
+
triggered: this.triggered,
|
|
66
|
+
triggerType: this.triggerType,
|
|
67
|
+
triggerPrice: this.triggerPrice,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
calculateTrailingStopPrice() {
|
|
71
|
+
if (!this.config.trailingStop || !this.highestPrice) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
return this.highestPrice * (1 - this.config.trailingStop / 100);
|
|
75
|
+
}
|
|
76
|
+
async onPriceUpdate(priceData) {
|
|
77
|
+
if (!this._running || this.triggered)
|
|
78
|
+
return;
|
|
79
|
+
const price = priceData.price;
|
|
80
|
+
this.currentPrice = price;
|
|
81
|
+
this.emit('priceUpdate', priceData);
|
|
82
|
+
// Update highest price for trailing stop
|
|
83
|
+
if (this.highestPrice === undefined || price > this.highestPrice) {
|
|
84
|
+
this.highestPrice = price;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
// Check stop-loss
|
|
88
|
+
if (this.config.stopLoss && price <= this.config.stopLoss) {
|
|
89
|
+
await this.trigger('stop-loss', price);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Check take-profit
|
|
93
|
+
if (this.config.takeProfit && price >= this.config.takeProfit) {
|
|
94
|
+
await this.trigger('take-profit', price);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Check trailing stop
|
|
98
|
+
if (this.config.trailingStop && this.highestPrice) {
|
|
99
|
+
const trailingStopPrice = this.calculateTrailingStopPrice();
|
|
100
|
+
if (price <= trailingStopPrice) {
|
|
101
|
+
await this.trigger('trailing-stop', price);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async trigger(type, price) {
|
|
111
|
+
this.triggered = true;
|
|
112
|
+
this.triggerType = type;
|
|
113
|
+
this.triggerPrice = price;
|
|
114
|
+
try {
|
|
115
|
+
// Sell entire position
|
|
116
|
+
const tradeStr = `${this.positionAmount} ${this.positionToken} -> ${this.quoteToken}`;
|
|
117
|
+
const result = await this.wallet.trade(tradeStr);
|
|
118
|
+
this.triggerResult = result;
|
|
119
|
+
this._tradesCompleted++;
|
|
120
|
+
this.emit('triggered', { type, price, result });
|
|
121
|
+
this.emit('trade', result);
|
|
122
|
+
// Stop strategy after trigger
|
|
123
|
+
this.stop();
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
this.triggered = false;
|
|
127
|
+
this.triggerType = undefined;
|
|
128
|
+
this.triggerPrice = undefined;
|
|
129
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Update stop-loss price while running
|
|
134
|
+
*/
|
|
135
|
+
updateStopLoss(price) {
|
|
136
|
+
this.config.stopLoss = price;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Update take-profit price while running
|
|
140
|
+
*/
|
|
141
|
+
updateTakeProfit(price) {
|
|
142
|
+
this.config.takeProfit = price;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Update trailing stop percentage while running
|
|
146
|
+
*/
|
|
147
|
+
updateTrailingStop(percentage) {
|
|
148
|
+
this.config.trailingStop = percentage;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.StopLossStrategy = StopLossStrategy;
|
|
152
|
+
//# sourceMappingURL=stop-loss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop-loss.js","sourceRoot":"","sources":["../../src/strategies/stop-loss.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy Engine - Base class for trading strategies
|
|
3
|
+
*/
|
|
4
|
+
import { EventEmitter } from 'events';
|
|
5
|
+
import type { TradeResult } from './agent-wallet';
|
|
6
|
+
import type { PriceData } from './market';
|
|
7
|
+
export interface StrategyConfig {
|
|
8
|
+
pair: string;
|
|
9
|
+
maxSlippage?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface StrategyStatus {
|
|
12
|
+
running: boolean;
|
|
13
|
+
startedAt?: number;
|
|
14
|
+
tradesCompleted: number;
|
|
15
|
+
}
|
|
16
|
+
export type StrategyEventMap = {
|
|
17
|
+
trade: [TradeResult];
|
|
18
|
+
error: [Error];
|
|
19
|
+
complete: [StrategyStatus];
|
|
20
|
+
triggered: [{
|
|
21
|
+
type: string;
|
|
22
|
+
price: number;
|
|
23
|
+
result: TradeResult;
|
|
24
|
+
}];
|
|
25
|
+
priceUpdate: [PriceData];
|
|
26
|
+
};
|
|
27
|
+
export type StrategyEvent = keyof StrategyEventMap;
|
|
28
|
+
/**
|
|
29
|
+
* Abstract base class for all trading strategies
|
|
30
|
+
*/
|
|
31
|
+
export declare abstract class Strategy<TConfig extends StrategyConfig = StrategyConfig, TStatus extends StrategyStatus = StrategyStatus> extends EventEmitter {
|
|
32
|
+
protected config: TConfig;
|
|
33
|
+
protected _running: boolean;
|
|
34
|
+
protected _startedAt?: number;
|
|
35
|
+
protected _tradesCompleted: number;
|
|
36
|
+
protected _priceInterval?: NodeJS.Timeout;
|
|
37
|
+
constructor(config: TConfig);
|
|
38
|
+
/**
|
|
39
|
+
* Start the strategy
|
|
40
|
+
*/
|
|
41
|
+
abstract start(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Stop the strategy
|
|
44
|
+
*/
|
|
45
|
+
stop(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Get strategy status
|
|
48
|
+
*/
|
|
49
|
+
abstract status(): TStatus;
|
|
50
|
+
/**
|
|
51
|
+
* Type-safe event emitter
|
|
52
|
+
*/
|
|
53
|
+
on<K extends StrategyEvent>(event: K, listener: (...args: StrategyEventMap[K]) => void): this;
|
|
54
|
+
emit<K extends StrategyEvent>(event: K, ...args: StrategyEventMap[K]): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Check if strategy is running
|
|
57
|
+
*/
|
|
58
|
+
get running(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Parse period string to milliseconds
|
|
61
|
+
*/
|
|
62
|
+
protected parsePeriodMs(period: string | number): number;
|
|
63
|
+
/**
|
|
64
|
+
* Parse amount string (e.g., "50 USDC" -> { amount: "50", token: "USDC" })
|
|
65
|
+
*/
|
|
66
|
+
protected parseAmount(amountStr: string): {
|
|
67
|
+
amount: string;
|
|
68
|
+
token: string;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export type StrategyType = 'dca' | 'grid' | 'stop-loss';
|
|
72
|
+
//# sourceMappingURL=strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC;IACrB,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;IACf,QAAQ,EAAE,CAAC,cAAc,CAAC,CAAC;IAC3B,SAAS,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAClE,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC;AAEnD;;GAEG;AACH,8BAAsB,QAAQ,CAC5B,OAAO,SAAS,cAAc,GAAG,cAAc,EAC/C,OAAO,SAAS,cAAc,GAAG,cAAc,CAC/C,SAAQ,YAAY;IACpB,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAS;IACpC,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAK;IACvC,SAAS,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;gBAE9B,MAAM,EAAE,OAAO;IAK3B;;OAEG;IACH,QAAQ,CAAC,KAAK,IAAI,IAAI;IAEtB;;OAEG;IACH,IAAI,IAAI,IAAI;IAQZ;;OAEG;IACH,QAAQ,CAAC,MAAM,IAAI,OAAO;IAE1B;;OAEG;IACM,EAAE,CAAC,CAAC,SAAS,aAAa,EACjC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,IAAI,GAC/C,IAAI;IAIE,IAAI,CAAC,CAAC,SAAS,aAAa,EACnC,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,OAAO;IAIV;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACH,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAoBxD;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CAO5E;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC"}
|
package/dist/strategy.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Strategy Engine - Base class for trading strategies
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Strategy = void 0;
|
|
7
|
+
const events_1 = require("events");
|
|
8
|
+
/**
|
|
9
|
+
* Abstract base class for all trading strategies
|
|
10
|
+
*/
|
|
11
|
+
class Strategy extends events_1.EventEmitter {
|
|
12
|
+
config;
|
|
13
|
+
_running = false;
|
|
14
|
+
_startedAt;
|
|
15
|
+
_tradesCompleted = 0;
|
|
16
|
+
_priceInterval;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
super();
|
|
19
|
+
this.config = config;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Stop the strategy
|
|
23
|
+
*/
|
|
24
|
+
stop() {
|
|
25
|
+
this._running = false;
|
|
26
|
+
if (this._priceInterval) {
|
|
27
|
+
clearInterval(this._priceInterval);
|
|
28
|
+
this._priceInterval = undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Type-safe event emitter
|
|
33
|
+
*/
|
|
34
|
+
on(event, listener) {
|
|
35
|
+
return super.on(event, listener);
|
|
36
|
+
}
|
|
37
|
+
emit(event, ...args) {
|
|
38
|
+
return super.emit(event, ...args);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Check if strategy is running
|
|
42
|
+
*/
|
|
43
|
+
get running() {
|
|
44
|
+
return this._running;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Parse period string to milliseconds
|
|
48
|
+
*/
|
|
49
|
+
parsePeriodMs(period) {
|
|
50
|
+
if (typeof period === 'number')
|
|
51
|
+
return period * 1000;
|
|
52
|
+
const match = period.match(/^(\d+)\s*(s|m|h|d)?$/i);
|
|
53
|
+
if (!match) {
|
|
54
|
+
throw new Error(`Invalid period format: ${period}`);
|
|
55
|
+
}
|
|
56
|
+
const value = parseInt(match[1]);
|
|
57
|
+
const unit = (match[2] || 's').toLowerCase();
|
|
58
|
+
switch (unit) {
|
|
59
|
+
case 's': return value * 1000;
|
|
60
|
+
case 'm': return value * 60 * 1000;
|
|
61
|
+
case 'h': return value * 60 * 60 * 1000;
|
|
62
|
+
case 'd': return value * 24 * 60 * 60 * 1000;
|
|
63
|
+
default: return value * 1000;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parse amount string (e.g., "50 USDC" -> { amount: "50", token: "USDC" })
|
|
68
|
+
*/
|
|
69
|
+
parseAmount(amountStr) {
|
|
70
|
+
const match = amountStr.trim().match(/^([\d.]+)\s*(\w+)$/);
|
|
71
|
+
if (!match) {
|
|
72
|
+
throw new Error(`Invalid amount format: ${amountStr}`);
|
|
73
|
+
}
|
|
74
|
+
return { amount: match[1], token: match[2].toUpperCase() };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.Strategy = Strategy;
|
|
78
|
+
//# sourceMappingURL=strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy.js","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,mCAAsC;AAyBtC;;GAEG;AACH,MAAsB,QAGpB,SAAQ,qBAAY;IACV,MAAM,CAAU;IAChB,QAAQ,GAAY,KAAK,CAAC;IAC1B,UAAU,CAAU;IACpB,gBAAgB,GAAW,CAAC,CAAC;IAC7B,cAAc,CAAkB;IAE1C,YAAY,MAAe;QACzB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAOD;;OAEG;IACH,IAAI;QACF,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAClC,CAAC;IACH,CAAC;IAOD;;OAEG;IACM,EAAE,CACT,KAAQ,EACR,QAAgD;QAEhD,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAwC,CAAC,CAAC;IACnE,CAAC;IAEQ,IAAI,CACX,KAAQ,EACR,GAAG,IAAyB;QAE5B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;OAEG;IACO,aAAa,CAAC,MAAuB;QAC7C,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,MAAM,GAAG,IAAI,CAAC;QAErD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACpD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAE7C,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC;YAC9B,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC;YACnC,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;YACxC,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;YAC7C,OAAO,CAAC,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;OAEG;IACO,WAAW,CAAC,SAAiB;QACrC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,0BAA0B,SAAS,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;IAC7D,CAAC;CACF;AA7FD,4BA6FC"}
|