UNPKG

@thoshpathi/utils-smartapi-order

Version:

Utility functions for placing live and dummy orders using Angel One's SmartAPI, with helper methods for streamlined trading workflows.

206 lines (203 loc) 6.74 kB
import { OrderHelper } from "./chunk-O6PJTRR5.mjs"; import { delay, toggleTrend } from "./chunk-RQBWMBFA.mjs"; // src/helpers/live_order_helper.ts import { groupByLatestMap } from "@thoshpathi/utils-core"; var LiveOrderHelper = class extends OrderHelper { async handleScripsTrendReversal(scripTrendMapData) { this.logger.d("run close open orders"); await this.closeTrendOpenOrders(scripTrendMapData); this.logger.d("run place new orders"); await this.placeNewTrendOrders(scripTrendMapData); } async handleDaySquareoff() { const openOrders = await this.getOpenOrders({}); if (openOrders == null) return; return await this.processOrdersSquareoff(openOrders, "squareoff"); } async processOrdersSquareoff(openOrders, status) { const squareoffOrders = await this.generateCloseOrderParams( openOrders, status ); if (squareoffOrders == null) return false; await this.updateOrdersClose(squareoffOrders); return true; } async handleOpenOrdersTracking() { const orderCloseTracks = await this.getOrderCloseTrackDatas(); if (orderCloseTracks == null) return; const completedOrderMap = await this.getCompletedOrderMap({ orders: orderCloseTracks.map((v) => v.order), isOrderClosing: true }); if (completedOrderMap == null) return; const closeOrders = []; for (const { order, status, ltp } of orderCloseTracks) { const { id, symbol, candleInterval } = order; const orderData = completedOrderMap.get(symbol); if (orderData == null) continue; closeOrders.push({ id, symbol, candleInterval, exitOrderid: orderData.orderid, exitPrice: orderData.price ?? orderData.averageprice ?? ltp, status }); } if (closeOrders.length == 0) { this.logger.w("closeOrders empty. no close track orders"); return; } await this.updateOrdersClose(closeOrders); } async closeTrendOpenOrders({ scripTrendMap }) { const names = Array.from(scripTrendMap.values()).map( (v) => v.indexScrip.name ); const openOrders = await this.getOpenOrders({ names }); if (openOrders == null) return; const closeOrders = await this.generateCloseOrderParams( openOrders, "closed" ); if (closeOrders == null) return false; await this.updateOrdersClose(closeOrders); return true; } async placeNewTrendOrders(scripTrendMapData) { const newOrders = await this.getTrendNewOrders(scripTrendMapData); if (newOrders == null) return; const createNewOrders = await this.generateCreateNewOrders(newOrders); if (createNewOrders == null) return; await this.createOrders(createNewOrders, scripTrendMapData.candleInterval); } async generateCloseOrderParams(openOrders, status) { const completedOrderMap = await this.getCompletedOrderMap({ orders: openOrders, isOrderClosing: true }); if (completedOrderMap == null) return; const closeOrders = []; for (const { id, symbol, candleInterval } of openOrders) { const orderData = completedOrderMap.get(symbol); if (orderData == null) continue; const exitPrice = orderData.price ?? orderData.averageprice; if (!exitPrice) { this.logger.w( symbol, `[${orderData.orderid}]: price / avg.price empty` ); continue; } closeOrders.push({ id, symbol, candleInterval, exitOrderid: orderData.orderid, exitPrice, status }); } if (closeOrders.length == 0) { this.logger.w(`closeOrders empty. no ${status} orders`); return; } return closeOrders; } async generateCreateNewOrders(newOrders) { const completedOrderMap = await this.getCompletedOrderMap({ orders: newOrders, isOrderClosing: false }); if (completedOrderMap == null) return; const createNewOrders = []; for (const order of newOrders) { const completedOrder = completedOrderMap.get(order.symbol); if (completedOrder == null) continue; const { orderid, price, averageprice } = completedOrder; order.entryOrderId = orderid; order.entryPrice = price ?? averageprice ?? order.entryPrice; createNewOrders.push(order); } if (createNewOrders.length == 0) { this.logger.w("createNewOrders empty. no create orders"); return; } return createNewOrders; } /** * Returns data of Map(symbol, OrderDetails) | undefined */ async getCompletedOrderMap(params) { const { orders, isOrderClosing = false } = params; const orderParams = orders.map((order) => { const transactionType = isOrderClosing ? toggleTrend(order.transaction) : order.transaction; return this.liveOrderParams({ symbol: order.symbol, symbolToken: order.symbolToken, exchange: order.exchange, qty: order.qty, transactionType }); }); const completedOrders = await this.placeLiveOrders(orderParams); if (completedOrders == null) return; return groupByLatestMap(completedOrders, "tradingsymbol"); } async placeLiveOrders(orderParams) { try { const buyPromises = orderParams.filter((v) => v.transactiontype === "BUY").map((params) => { return this.smartapi.placeOrder_e(params); }); const sellPromises = orderParams.filter((v) => v.transactiontype === "SELL").map((params) => { return this.smartapi.placeOrder_e(params); }); const responses = []; if (buyPromises.length > 0) { const buyResponses = await Promise.all(buyPromises); responses.push(...buyResponses); await delay(200); } if (sellPromises.length > 0) { const sellResponses = await Promise.all(sellPromises); responses.push(...sellResponses); } await delay(this.orderVerfiyWaitMs); const completedOrders = await this.smartapi.fetchCompletedOrders( responses ); if (completedOrders == null || completedOrders.length == 0) { this.logger.e("completedOrders empty. place order failed"); return; } return completedOrders; } catch (error) { this.logger.c("place live orders error", error); } return; } liveOrderParams(params) { return { tradingsymbol: params.symbol, symboltoken: params.symbolToken, exchange: params.exchange, transactiontype: params.transactionType, quantity: params.qty, producttype: params.productType ?? "INTRADAY", duration: params.duration ?? "DAY", variety: "NORMAL", ordertype: "MARKET" }; } }; export { LiveOrderHelper };