예제 #1
0
        // Try min profit squareoff first between 3 - 3.10 time.
        // From 3.10 to 3.15 time if squareoff of all positions is set to true and the ltp diff meets threshold for max loss pct, then do a market order squareoff
        public void TrySquareOffNearEOD(AlgoType algoType)
        {
            // if after 3 pm, then try to square off in at least no profit no loss if possible. either buy or sell is outstanding
            if (MarketUtils.IsTimeAfter3())
            {
                var ordPriceType   = OrderPriceType.LIMIT;
                var doUpdateOrders = false;

                // 3.10 - 3.15 pm time. market order type for forced square off given pct loss is within acceptable range
                // do it before 3.15, otherwise broker will try to squareoff on its own anytime between 3.15 - 3.30
                if (MarketUtils.IsTimeAfter310() && !MarketUtils.IsTimeAfter315() && squareOffAllPositionsAtEOD && !isEODMinLossSquareOffMarketOrderUpdated)
                {
                    var ltp = GetLTP();
                    ordPriceType = OrderPriceType.MARKET;

                    var diff = Math.Abs((ltp - todayOutstandingPrice) / ltp);
                    if (diff < pctMaxLossSquareOffPositions && todayOutstandingPrice > goodPrice)
                    {
                        Trace(string.Format("TrySquareOffNearEOD: max loss % {0} is within acceptable range of {1} and avg outstanding price {2} is greater than good price of {3}. Update squareoff at MARKET price type.", diff, pctMaxLossSquareOffPositions, todayOutstandingPrice, goodPrice));
                        doUpdateOrders = true;
                        isEODMinLossSquareOffMarketOrderUpdated = true;
                    }
                }

                // 3 - 3.10 pm time. try simple limit order with min profit price
                else if (!isEODMinProfitSquareOffLimitOrderUpdated)
                {
                    Trace(string.Format("TrySquareOffNearEOD: Update squareoff LIMIT order with min profit % price or cancel outstanding orders"));
                    ordPriceType = OrderPriceType.LIMIT;
                    isEODMinProfitSquareOffLimitOrderUpdated = true;
                    doUpdateOrders = true;
                }

                if (doUpdateOrders)
                {
                    if (algoType == AlgoType.AverageTheBuyThenSell)
                    {
                        // just cancel the outstanding buy order
                        if (!string.IsNullOrEmpty(todayOutstandingBuyOrderRef))
                        {
                            // cancel existing buy order
                            errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingBuyOrderRef, OrderDirection.BUY);
                        }

                        // bought qty needs square off. there is outstanding sell order, revise the price to try square off
                        if (!string.IsNullOrEmpty(todayOutstandingSellOrderRef))
                        {
                            // cancel existing sell order
                            errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingSellOrderRef, OrderDirection.SELL);

                            if (errCode == BrokerErrorCode.Success)
                            {
                                todayOutstandingSellOrderRef = "";
                                // place new sell order, update sell order ref
                                Trace("Placing EOD squareoff updated order");
                                var sellPrice = GetSellPrice(todayOutstandingPrice, false, true);
                                errCode = PlaceEquityOrder(stockCode, todayOutstandingQty, sellPrice.ToString(), ordPriceType, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, out todayOutstandingSellOrderRef);
                            }
                        }
                    }
                    else if (algoType == AlgoType.SimultaneousBuySell)
                    {
                        // if there is an outstanding order pair, just cancel both
                        if (!string.IsNullOrEmpty(todayOutstandingBuyOrderRef) && !string.IsNullOrEmpty(todayOutstandingSellOrderRef))
                        {
                            // cancel existing sell order
                            errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingSellOrderRef, OrderDirection.SELL);

                            // cancel existing buy order
                            errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingBuyOrderRef, OrderDirection.BUY);
                        }

                        // bought qty needs square off.  there is outstanding sell order, revise the price to try square off
                        else if (string.IsNullOrEmpty(todayOutstandingBuyOrderRef) && !string.IsNullOrEmpty(todayOutstandingSellOrderRef))
                        {
                            // cancel existing sell order
                            errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingSellOrderRef, OrderDirection.SELL);

                            if (errCode == BrokerErrorCode.Success)
                            {
                                todayOutstandingSellOrderRef = "";
                                // place new sell order, update sell order ref
                                Trace("Placing EOD squareoff updated order");
                                var sellPrice = GetSellPrice(todayOutstandingPrice, false, true);
                                errCode = PlaceEquityOrder(stockCode, ordQty, sellPrice.ToString(), ordPriceType, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, out todayOutstandingSellOrderRef);
                            }
                        }

                        // sold qty needs square off. there is outstanding buy order, revise the price to try square off
                        else if (string.IsNullOrEmpty(todayOutstandingSellOrderRef) && !string.IsNullOrEmpty(todayOutstandingBuyOrderRef))
                        {
                            // cancel existing buy order
                            errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingBuyOrderRef, OrderDirection.BUY);

                            if (errCode == BrokerErrorCode.Success)
                            {
                                todayOutstandingBuyOrderRef = "";
                                // place new buy order, update buy order ref
                                Trace("Placing EOD squareoff updated order");
                                var buyPrice = GetBuySquareOffPrice(todayOutstandingPrice);
                                errCode = PlaceEquityOrder(stockCode, ordQty, buyPrice.ToString(), ordPriceType, OrderDirection.BUY, EquityOrderType.MARGIN, exchange, out todayOutstandingBuyOrderRef);
                            }
                        }
                    }
                }
            }
        }
        public void TradeUpdated(object sender, TradeUpdateEventArgs args)
        {
            lock (lockRunEitherPlaceBuyOrTradeUpdated)
            {
                try
                {
                    var trade = ConvertTradeUpdateArgsToTradeRecord(args);

                    if (stockCode != trade.StockCode)
                    {
                        return;
                    }

                    var isSellExecutedFully = false;

                    Trace(string.Format(tradeTraceFormat, stockCode, trade.Direction == OrderDirection.BUY ? "bought" : "sold", args.TradedQty, args.TradedPrice,
                                        holdingSellOrder.OrderId == trade.OrderId ? "DELIVERY" : "MARGIN", trade.OrderId, trade.TradeId, trade.DateTime, args.ExchTime, args.TimeStamp));

                    // if any holding sell executed
                    if (trade.OrderId == holdingSellOrder.OrderId)
                    {
                        ProcessHoldingSellOrderExecution(trade.NewQuantity);
                    }

                    // if SELL executed, then update today outstanding with executed qty (handle part executions using NewQuantity)
                    // If it is after 3.15 and broker did auto sq off, then broker's order ref is not with us and wont match with our sq off order. Our sqoff order will be cancelled by the broker
                    if (trade.OrderId == outstandingSellOrder.OrderId || ((MarketUtils.IsTimeAfter315() && trade.EquityOrderType == EquityOrderType.MARGIN && trade.Direction == OrderDirection.SELL)))
                    {
                        if (!string.IsNullOrEmpty(outstandingSellOrder.OrderId) && trade.OrderId != outstandingSellOrder.OrderId)
                        {
                            // If broker initiated market squareoff then Cancel the known sell order to avoid extra execution
                            errCode = CancelEquityOrder("[Broker SquareOff Executed]", ref outstandingSellOrder.OrderId, orderType, OrderDirection.SELL);
                        }

                        todayOutstandingQty -= trade.NewQuantity;

                        if (todayOutstandingQty == 0)
                        {
                            todayOutstandingPrice        = 0;
                            outstandingSellOrder.OrderId = "";
                            todayOutstandingTradeCount   = 0;
                            isSellExecutedFully          = true;
                        }
                    }

                    // if BUY executed, then place a corresponding updated sell order.
                    if (trade.OrderId == outstandingBuyOrder.OrderId)
                    {
                        currentBuyOrdExecutedQty += trade.NewQuantity;

                        if (currentBuyOrdExecutedQty == currentBuyOrdQty)
                        {
                            Trace(string.Format("[Trade Execution] Fully executed NewQty={0} TotalQty={1}", trade.NewQuantity, currentBuyOrdQty));
                            outstandingBuyOrder.OrderId = "";
                            todayOutstandingTradeCount++;
                        }
                        else
                        {
                            Trace(string.Format("[Trade Execution] Partially executed NewQty={0} TotalQty={1}", trade.NewQuantity, currentBuyOrdQty));
                        }

                        // update outstanding qty and outstanding price to place updated sell order
                        todayOutstandingPrice = (todayOutstandingPrice * todayOutstandingQty) + (trade.NewQuantity * trade.Price);
                        todayOutstandingQty  += trade.NewQuantity;
                        todayOutstandingPrice = todayOutstandingQty == 0 ? 0 : todayOutstandingPrice / todayOutstandingQty;

                        UpdatePnLStats();

                        if (todayOutstandingQty >= maxTodayOutstandingQtyAllowed)
                        {
                            Trace(string.Format("[Trading Limits Hit] TodayOutstandingQty reached the max. todayOutstandingQty: {0} maxTodayPositionValueMultiple: {1}", todayOutstandingQty, maxTodayOutstandingQtyAllowed));
                        }

                        if ((todayOutstandingQty + holdingOutstandingQty) >= maxTotalOutstandingQtyAllowed)
                        {
                            Trace(string.Format("[Trading Limits Hit] TotalOutstandingQty reached the max. todayOutstandingQty: {0} holdingOutstandingQty: {1} maxTotalPositionValueMultiple: {2}", todayOutstandingQty, holdingOutstandingQty, maxTotalOutstandingQtyAllowed));
                        }

                        lastBuyPrice = trade.Price;

                        var sellPrice = GetSellPrice(todayOutstandingPrice, false, false);

                        if (!string.IsNullOrEmpty(outstandingSellOrder.OrderId))
                        {
                            // modify existing sell order if it exists
                            errCode = ModifyEquityOrder("NewBuy modify squareoff", stockCode, outstandingSellOrder.OrderId, OrderPriceType.LIMIT, todayOutstandingQty, sellPrice, out upstoxOrderStatus);

                            // cancel existing sell order if it exists
                            //errCode = CancelEquityOrder("[Buy Executed]", ref outstandingSellOrder.OrderId, orderType, OrderDirection.SELL);
                        }
                        if (string.IsNullOrEmpty(outstandingSellOrder.OrderId))
                        {
                            // place new sell order if previous cancelled or it was first one, update sell order ref
                            errCode = PlaceEquityOrder(exchStr, stockCode, OrderDirection.SELL, OrderPriceType.LIMIT, todayOutstandingQty, orderType, sellPrice, out outstandingSellOrder.OrderId, out upstoxOrderStatus);
                        }
                    }

                    if (isSellExecutedFully)
                    {
                        // Cancel existing Buy order which might be an average seeking order, as the pricecalc might have changed
                        if (!string.IsNullOrEmpty(outstandingBuyOrder.OrderId))
                        {
                            // cancel existing buy order
                            errCode = CancelEquityOrder("[Sell Executed Fully]", ref outstandingBuyOrder.OrderId, orderType, OrderDirection.BUY);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Trace("Error:" + ex.Message + "\nStacktrace:" + ex.StackTrace);
                }
            }
        }