Skip to content

Commit 6909ab0

Browse files
committed
wizard: add profit-based stop-loss
1 parent 360aba8 commit 6909ab0

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

apps/arb-solana-bot/src/start.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@ export const start = async () => {
6767
autoReset?: {
6868
enabled: boolean;
6969
timeWindowMs: number;
70-
};
70+
},
71+
expectedProfitBasedStopLoss?: {
72+
enabled: boolean;
73+
percent: number;
74+
}
7175
};
7276
} = JSON.parse(fs.readFileSync("./config.json", "utf8"));
7377

@@ -96,6 +100,9 @@ export const start = async () => {
96100
enableAutoSlippage: config.strategy.slippage.enableAutoSlippage,
97101
enableCompounding: config.strategy.enableCompounding ?? false,
98102
autoReset: config.strategy.autoReset,
103+
expectedProfitBasedStopLoss: config.strategy.expectedProfitBasedStopLoss,
104+
onStopLossAction: "sell&reset"
105+
99106
});
100107

101108
const bot = extendBot(

packages/core/src/strategies/ping-pong.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ export type PingPongStrategyConfig = {
3131
executeAboveExpectedProfitPercent: number;
3232
priorityFeeMicroLamports?: number;
3333
lock?: boolean;
34-
enableExpectedProfitBasedStopLoss?: boolean;
35-
profitBasedStopLossPercent?: number;
34+
expectedProfitBasedStopLoss?: {
35+
enabled: boolean;
36+
percent: number;
37+
}
3638
onStopLossAction?: "sell&reset" | "shutdown" | "sell&shutdown";
3739
shouldReset?: boolean;
3840
autoReset?: {
@@ -53,7 +55,6 @@ export const PingPongStrategy: Strategy<PingPongStrategyConfig> = {
5355
lock: false,
5456
enableAutoSlippage: false,
5557
enableCompounding: false,
56-
enableExpectedProfitBasedStopLoss: false,
5758
},
5859
uiHook: {},
5960
// dependencies: {
@@ -373,16 +374,16 @@ export const PingPongStrategy: Strategy<PingPongStrategyConfig> = {
373374
* then execute stop loss action
374375
*/
375376
if (
376-
this.config.enableExpectedProfitBasedStopLoss &&
377-
this.config.profitBasedStopLossPercent &&
377+
this.config.expectedProfitBasedStopLoss?.enabled &&
378+
this.config.expectedProfitBasedStopLoss.percent &&
378379
expectedProfitPercent.toNumber() <
379-
this.config.profitBasedStopLossPercent * -1 &&
380+
Math.abs(this.config.expectedProfitBasedStopLoss.percent) * -1 &&
380381
isSellSide
381382
) {
382383
bot.setStatus("strategy:stopLossExceeded");
383384

384385
if (this.config.onStopLossAction === "shutdown") {
385-
const msg = `PingPongStrategy:run: profitBasedStopLossPercent ${this.config.profitBasedStopLossPercent} reached, shutting down bot`;
386+
const msg = `PingPongStrategy:run: profitBasedStopLossPercent ${this.config.expectedProfitBasedStopLoss?.percent} reached, shutting down bot`;
386387
bot.logger.info({ runtimeId }, msg);
387388
console.log("\n\n" + msg + "\n\n");
388389
bot.setStatus("!shutdown");

packages/wizard/src/run-wizard.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ export const runWizard = async () => {
219219
timeWindowMs: 60_000,
220220
};
221221

222+
let expectedProfitBasedStopLoss = {
223+
enabled: false,
224+
percent: 0,
225+
}
226+
222227
if (experienceLevel !== "beginner") {
223228
features = await multiselect({
224229
message: "What features do you want to setup? [spacebar] to select",
@@ -228,7 +233,8 @@ export const runWizard = async () => {
228233
{ value: "executionRateLimiter", label: "Execution rate limiter" },
229234
{ value: "iterationsRateLimiter", label: "Iterations rate" },
230235
{ value: "aggregatorErrorsRateLimiter", label: "Aggregator errors rate limiter" },
231-
{ value: "autoReset", label: "Auto reset" },
236+
{ value: "autoReset", label: "Auto reset", hint: "experimental" },
237+
{ value: "expectedProfitBasedStopLoss", label: "Stop Loss", hint: "experimental" },
232238
],
233239
required: false,
234240
});
@@ -451,6 +457,32 @@ export const runWizard = async () => {
451457
};
452458
}
453459
}
460+
461+
if (features.includes("expectedProfitBasedStopLoss")) {
462+
const expectedProfitBasedStopLossPercent = await text({
463+
message:
464+
"What is the expected profit based stop loss percent?\n· If expected profit reaches this percent then swap back to the initial token & reset.\n· The provided number will always be negative (e.g. 0.5 = -0.5)",
465+
initialValue: "0",
466+
validate: (value) => {
467+
if (value.length === 0) return "Please enter a expected profit based stop loss percent";
468+
const expectedProfitBasedStopLossPercent = Math.abs(parseFloat(value));
469+
if (isNaN(expectedProfitBasedStopLossPercent)) return "Please enter a valid number";
470+
if (expectedProfitBasedStopLossPercent === 0) return "Please enter a non-zero number";
471+
},
472+
});
473+
474+
if (isCancel(expectedProfitBasedStopLossPercent)) {
475+
cancel("Operation cancelled");
476+
return process.exit(0);
477+
}
478+
479+
if (typeof expectedProfitBasedStopLossPercent === "string") {
480+
expectedProfitBasedStopLoss = {
481+
enabled: true,
482+
percent: Math.abs(parseFloat(expectedProfitBasedStopLossPercent)),
483+
};
484+
}
485+
}
454486
}
455487

456488
// Arb Protocol BuyBack
@@ -517,6 +549,10 @@ export const runWizard = async () => {
517549
enabled: boolean;
518550
timeWindowMs: number;
519551
};
552+
expectedProfitBasedStopLoss?: {
553+
enabled: boolean;
554+
percent: number;
555+
}
520556
};
521557
};
522558

@@ -537,6 +573,7 @@ export const runWizard = async () => {
537573
? priorityFeeMicroLamports
538574
: undefined,
539575
autoReset,
576+
expectedProfitBasedStopLoss
540577
},
541578
maxConcurrent: 1,
542579
tui: {

0 commit comments

Comments
 (0)