Skip to content

Commit 8f9e03b

Browse files
Hiksangclaude
andcommitted
fix: stop order arg order + Pacifica trade dedup
- trade stop: changed CLI arg order from <stopPrice> <size> to <size> <stopPrice> for consistency with market/limit commands (size before price) - pacifica: deduplicate recent trades (API returns duplicate entries) - Updated 3 stop order tests to match new arg order Verified: 941/941 tests pass, dry-run stop size/price correct Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 90e0b8d commit 8f9e03b

3 files changed

Lines changed: 15 additions & 7 deletions

File tree

src/__tests__/commands/trade-commands.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ describe("trade stop -- parameter correctness", () => {
267267
it("calls adapter.stopOrder with correct args and options", async () => {
268268
const adapter = mockAdapter();
269269
await run(adapter, [
270-
"trade", "stop", "btc", "sell", "60000", "0.1",
270+
"trade", "stop", "btc", "sell", "0.1", "60000",
271271
"--limit-price", "59500", "--reduce-only",
272272
]);
273273

@@ -283,7 +283,7 @@ describe("trade stop -- parameter correctness", () => {
283283

284284
it("without --limit-price and --reduce-only: options have undefined values", async () => {
285285
const adapter = mockAdapter();
286-
await run(adapter, ["trade", "stop", "btc", "sell", "60000", "0.1"]);
286+
await run(adapter, ["trade", "stop", "btc", "sell", "0.1", "60000"]);
287287

288288
expect(adapter.stopOrder).toHaveBeenCalledTimes(1);
289289
expect(adapter.stopOrder).toHaveBeenCalledWith(
@@ -297,7 +297,7 @@ describe("trade stop -- parameter correctness", () => {
297297

298298
it("uppercases symbol for stop orders", async () => {
299299
const adapter = mockAdapter();
300-
await run(adapter, ["trade", "stop", "eth", "buy", "3500", "1"]);
300+
await run(adapter, ["trade", "stop", "eth", "buy", "1", "3500"]);
301301

302302
expect(adapter.stopOrder).toHaveBeenCalledWith(
303303
"ETH",
@@ -963,7 +963,7 @@ describe("no unexpected extra adapter calls", () => {
963963

964964
it("stop order only calls stopOrder", async () => {
965965
const adapter = mockAdapter();
966-
await run(adapter, ["trade", "stop", "btc", "sell", "60000", "0.1"]);
966+
await run(adapter, ["trade", "stop", "btc", "sell", "0.1", "60000"]);
967967

968968
expect(adapter.stopOrder).toHaveBeenCalledTimes(1);
969969
expect(adapter.marketOrder).not.toHaveBeenCalled();

src/commands/trade.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,11 +489,11 @@ export function registerTradeCommands(
489489
// === Stop / Trigger orders — Pacifica + Hyperliquid ===
490490

491491
trade
492-
.command("stop <symbol> <side> <stopPrice> <size>")
492+
.command("stop <symbol> <side> <size> <stopPrice>")
493493
.description("Place a stop order")
494494
.option("--limit-price <price>", "Limit price (makes it stop-limit)")
495495
.option("--reduce-only", "Reduce only order")
496-
.action(async (symbol: string, side: string, stopPrice: string, size: string, opts: { limitPrice?: string; reduceOnly?: boolean }) => {
496+
.action(async (symbol: string, side: string, size: string, stopPrice: string, opts: { limitPrice?: string; reduceOnly?: boolean }) => {
497497
const s = side.toLowerCase();
498498
if (s !== "buy" && s !== "sell") errorAndExit("Side must be buy or sell");
499499

src/exchanges/pacifica.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,15 @@ export class PacificaAdapter implements ExchangeAdapter {
286286

287287
async getRecentTrades(symbol: string, _limit = 20): Promise<ExchangeTrade[]> {
288288
const trades = await this.client.getTrades(symbol);
289-
return trades.slice(0, _limit).map((t) => ({
289+
// Deduplicate by time+price+size+side (API sometimes returns duplicate entries)
290+
const seen = new Set<string>();
291+
const unique = trades.filter((t) => {
292+
const key = `${t.created_at}:${t.price}:${t.amount}:${t.side}`;
293+
if (seen.has(key)) return false;
294+
seen.add(key);
295+
return true;
296+
});
297+
return unique.slice(0, _limit).map((t) => ({
290298
time: Number(t.created_at ?? 0),
291299
symbol,
292300
side: t.side === "bid" ? "buy" as const : "sell" as const,

0 commit comments

Comments
 (0)