Skip to content

Commit

Permalink
fix(PaperExchange): handle network errors
Browse files Browse the repository at this point in the history
  • Loading branch information
bludnic committed Aug 14, 2024
1 parent f29aeb7 commit d597d88
Showing 1 changed file with 56 additions and 34 deletions.
90 changes: 56 additions & 34 deletions packages/exchanges/src/exchanges/ccxt/paper-exchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*
* Repository URL: https://github.com/bludnic/opentrader
*/
import { ExchangeClosedByUser, NetworkError, RequestTimeout } from "ccxt";
import {
IAccountAsset,
ICancelLimitOrderRequest,
Expand Down Expand Up @@ -74,41 +75,62 @@ export class PaperExchange extends CCXTExchange {
this.matchingEnabled = true;

while (this.enabled && this.symbols.length > 0) {
const tickers = await this.ccxt.watchTickers(this.symbols);

for (const order of this.openOrders) {
const ticker = tickers[order.symbol];

if (order.side === "buy" && order.price! >= ticker.ask!) {
const filledOrder = await xprisma.paperOrder.update({
where: { id: order.id },
data: {
status: "filled" satisfies OrderStatus,
filledPrice: ticker.ask,
lastTradeTimestamp: new Date(),
},
});
this.openOrders = this.openOrders.filter((openOrder) => openOrder.id !== order.id); // remove from open orders
console.log(
`[${this.exchangeCode} Paper] BUY order ID:${order.id} filled at price ${ticker.ask} ${order.symbol}`,
);

this.emitOrder(filledOrder);
} else if (order.side === "sell" && order.price! <= ticker.bid!) {
const filledOrder = await xprisma.paperOrder.update({
where: { id: order.id },
data: {
status: "filled" satisfies OrderStatus,
filledPrice: ticker.bid,
lastTradeTimestamp: new Date(),
},
});
this.openOrders = this.openOrders.filter((openOrder) => openOrder.id !== order.id); // remove from open orders
console.log(
`[${this.exchangeCode} Paper] SELL order ID:${order.id} filled at price ${ticker.bid} ${order.symbol}`,
try {
const tickers = await this.ccxt.watchTickers(this.symbols);

for (const order of this.openOrders) {
const ticker = tickers[order.symbol];

if (order.side === "buy" && order.price! >= ticker.ask!) {
const filledOrder = await xprisma.paperOrder.update({
where: { id: order.id },
data: {
status: "filled" satisfies OrderStatus,
filledPrice: ticker.ask,
lastTradeTimestamp: new Date(),
},
});
this.openOrders = this.openOrders.filter((openOrder) => openOrder.id !== order.id); // remove from open orders
console.log(
`[${this.exchangeCode} Paper] BUY order ID:${order.id} filled at price ${ticker.ask} ${order.symbol}`,
);

this.emitOrder(filledOrder);
} else if (order.side === "sell" && order.price! <= ticker.bid!) {
const filledOrder = await xprisma.paperOrder.update({
where: { id: order.id },
data: {
status: "filled" satisfies OrderStatus,
filledPrice: ticker.bid,
lastTradeTimestamp: new Date(),
},
});
this.openOrders = this.openOrders.filter((openOrder) => openOrder.id !== order.id); // remove from open orders
console.log(
`[${this.exchangeCode} Paper] SELL order ID:${order.id} filled at price ${ticker.bid} ${order.symbol}`,
);

this.emitOrder(filledOrder);
}
}
} catch (err) {
if (err instanceof NetworkError) {
console.warn(`[PaperExchange ${this.exchangeCode}] NetworkError occurred: ${err.message}. Timeout: 3s`);
await new Promise((resolve) => setTimeout(resolve, 3000)); // prevents flooding microtasks
} else if (err instanceof RequestTimeout) {
console.warn(`[PaperExchange ${this.exchangeCode}] RequestTimeout occurred: ${err.message}`);
} else if (err instanceof ExchangeClosedByUser) {
// This is an expected error when destroying ccxt instance via ccxt.close()
console.info(`[PaperExchange ${this.exchangeCode}] ExchangeClosedByUser`);
break;
} else {
console.error(
`[PaperExchange ${this.exchangeCode}] ‼️ Unhandled error occurred. Disabling WS connection.`,
err,
);

this.emitOrder(filledOrder);
await this.destroy();
process.exit(1);
break;
}
}
}
Expand Down

0 comments on commit d597d88

Please sign in to comment.