Exemplo n.º 1
0
        // reads position file: qty avgprice holdingssellorderref
        // gets order and trade book
        // if holdings sell order is executed, then holding qty is updated to 0, and position file is updated with only today outstanding and empty sellorderref
        // holdings data is seperate and today outstanding data is seperate
        // single buy or sell outsanding order at any time is assumed
        // if there is no sell order for holdings then create a sell order and update position file with holdings and sellorderref
        // position file contains only the holding data along with the holding sell order ref. it does not have today's outstanding. Only at EOD if conversion to delivery is done then that is assumed to be holding and written to postion file
        // holding sell order if reqd is placed only once at start in Init, not in loop run. that time iffordeliveryflag is set so that sell price is calculated as per deliverymarkup parameter
        // in normal run , sell orders are placed as per normal marginmarkup parameter
        // today's outstanding is derived from the tradebook and outstanding orders derived from order book. no state is saved outside. day before holdings are present in positions file
        public void Init(AlgoType algoType)
        {
            if (!File.Exists(positionFile))
            {
                File.WriteAllText(positionFile, "");
            }

            // just place squareoff orders for previous days open positions pending for delivery - develop it later

            // Position file always contains the holding qty, holding price and different type of holdings' details (demat/btst, qty, sell order ref) etc
            ReadPositionFile();

            var orders = new Dictionary <string, EquityOrderBookRecord>();
            var trades = new Dictionary <string, EquityTradeBookRecord>();

            // latest (wrt time) trades or orders appear at start of the output
            errCode = broker.GetEquityTradeBookToday(false, stockCode, out trades);
            errCode = broker.GetEquityOrderBookToday(false, true, stockCode, out orders);

            // get all holding qty trades
            var holdingTradesRef = holdingsOrders.Select(h => h.OrderRef);

            // any outstanding qty (buy minus sell trades) today except from holding qty trade
            todayOutstandingQty = trades.Where(t => !holdingTradesRef.Contains(t.Key)).Sum(t => t.Value.Direction == OrderDirection.SELL ? -t.Value.Quantity : t.Value.Quantity);

            var buyTrades = trades.Where(t => t.Value.Direction == OrderDirection.BUY);

            lastBuyPrice     = buyTrades.Any() ? buyTrades.First().Value.Price : holdingOutstandingPrice;
            settlementNumber = buyTrades.Any() ? buyTrades.First().Value.SettlementNumber : "";

            var numOutstandingBuyTrades = todayOutstandingQty > 0 ? todayOutstandingQty / ordQty : 0;

            // these are latest trades taken. each buy trade is for single lot and thus for each lot there is a trade
            todayOutstandingPrice = numOutstandingBuyTrades == 0 ? 0 : buyTrades.Take(numOutstandingBuyTrades).Average(t => t.Value.Price);

            ProcessHoldingSellOrderExecution(trades);

            var buyOrders  = orders.Values.Where(o => o.Direction == OrderDirection.BUY && o.Status == OrderStatus.ORDERED);
            var sellOrders = orders.Values.Where(o => o.Direction == OrderDirection.SELL && o.Status == OrderStatus.ORDERED && !holdingTradesRef.Contains(o.OrderRefenceNumber)); // pick only today's outstanding related sell orders

            // assumed that there is always at max only single outstanding buy order and a at max single outstanding sell order
            todayOutstandingBuyOrderRef  = buyOrders.Any() ? buyOrders.First().OrderRefenceNumber : "";
            todayOutstandingSellOrderRef = sellOrders.Any() ? sellOrders.First().OrderRefenceNumber : "";

            var sellOrder = sellOrders.Any() ? sellOrders.First() : null;

            isFirstBuyOrder = string.IsNullOrEmpty(todayOutstandingBuyOrderRef) && !trades.Where(t => t.Value.Direction == OrderDirection.BUY).Any();

            // if sqoff sell order for holdings is needed then place it
            //assumption is: if there is a holding pending from day before then it would have been converted to delivery
            if (holdingOutstandingQty > 0)
            {
                // get demat and btst listings
                List <EquityDematHoldingRecord> dematHoldings;
                errCode = broker.GetDematAllocation(stockCode, out dematHoldings);
                List <EquityBTSTTradeBookRecord> btstHoldings;
                errCode = broker.GetBTSTListings(stockCode, out btstHoldings);
                List <EquityPendingPositionForDelivery> pendingPositions;
                errCode = broker.GetOpenPositionsPendingForDelivery(stockCode, out pendingPositions);

                // place sq off sell order, update sell order ref
                var    sellPrice    = GetSellPrice(holdingOutstandingPrice, true, false);
                string sellOrderRef = "";
                if (dematHoldings.Any())
                {
                    var dematHolding = dematHoldings.First();
                    if (dematHolding.AvailableQuantity > 0)
                    {
                        errCode = PlaceEquityOrder(stockCode, OrderPositionTypeEnum.Demat, dematHolding.AvailableQuantity, dematHolding.AvailableQuantity, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.DELIVERY, exchange, "", out sellOrderRef);
                        if (errCode == BrokerErrorCode.Success)
                        {
                            holdingsOrders.Add(new HoldingOrder {
                                Type = OrderPositionTypeEnum.Demat, OrderRef = sellOrderRef, Qty = dematHolding.AvailableQuantity, SettlementNumber = ""
                            });
                        }
                    }
                }
                if (btstHoldings.Any())
                {
                    foreach (var btstHolding in btstHoldings)
                    {
                        if (btstHolding.AvailableQuantity > 0)
                        {
                            errCode = PlaceEquityOrder(stockCode, OrderPositionTypeEnum.Btst, btstHolding.AvailableQuantity, btstHolding.AvailableQuantity, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.DELIVERY, exchange, btstHolding.SettlementNumber, out sellOrderRef);
                            if (errCode == BrokerErrorCode.Success)
                            {
                                holdingsOrders.Add(new HoldingOrder {
                                    Type = OrderPositionTypeEnum.Btst, OrderRef = sellOrderRef, Qty = btstHolding.AvailableQuantity, SettlementNumber = btstHolding.SettlementNumber
                                });
                            }
                        }
                    }
                }
                if (pendingPositions.Any())
                {
                    foreach (var pendingPosition in pendingPositions)
                    {
                        if (pendingPosition.AvailableQuantity > 0)
                        {
                            errCode = PlaceEquityOrder(stockCode, OrderPositionTypeEnum.OpenPendingDelivery, pendingPosition.AvailableQuantity, pendingPosition.AvailableQuantity, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.DELIVERY, exchange, pendingPosition.SettlementNumber, out sellOrderRef);
                            if (errCode == BrokerErrorCode.Success)
                            {
                                holdingsOrders.Add(new HoldingOrder {
                                    Type = OrderPositionTypeEnum.OpenPendingDelivery, OrderRef = sellOrderRef, Qty = pendingPosition.AvailableQuantity, SettlementNumber = pendingPosition.SettlementNumber
                                });
                            }
                        }
                    }
                }
                UpdatePositionFile();
            }

            // For AverageTheBuyThenSell algo - place sell order for outstanding qty if not already present
            if (algoType == AlgoType.AverageTheBuyThenSell)
            {
                // check if the outstanding sell order has matching qty or not
                if (sellOrder != null && !string.IsNullOrEmpty(todayOutstandingSellOrderRef) && sellOrder.Quantity < todayOutstandingQty)
                {
                    // Cancel existing sell order
                    errCode = CancelEquityOrder("[Init Update Sell Qty]", ref todayOutstandingSellOrderRef, EquityOrderType.MARGIN, OrderDirection.SELL);
                }

                if (string.IsNullOrEmpty(todayOutstandingSellOrderRef) && todayOutstandingQty > 0)
                {
                    var sellPrice = GetSellPrice(todayOutstandingPrice, false, false);
                    errCode = PlaceEquityOrder(stockCode, OrderPositionTypeEnum.Margin, todayOutstandingQty, todayOutstandingQty, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, "", out todayOutstandingSellOrderRef);
                }
            }

            todayBuyOrderCount = buyOrders.Count();
        }
Exemplo n.º 2
0
        // reads position file: qty avgprice holdingssellorderref
        // gets order and trade book
        // if holdings sell order is executed, then holding qty is updated to 0, and position file is updated with only today outstanding and empty sellorderref
        // holdings data is seperate and today outstanding data is seperate
        // single buy or sell outsanding order at any time is assumed
        // if there is no sell order for holdings then create a sell order and update position file with holdings and sellorderref
        // position file contains only the holding data along with the holding sell order ref. it does not have today's outstanding. Only at EOD if conversion to delivery is done then that is assumed to be holding and written to postion file
        // holding sell order if reqd is placed only once at start in Init, not in loop run. that time iffordeliveryflag is set so that sell price is calculated as per deliverymarkup parameter
        // in normal run , sell orders are placed as per normal marginmarkup parameter
        // today's outstanding is derived from the tradebook and outstanding orders derived from order book. no state is saved outside. day before holdings are present in positions file
        public void Init(AlgoType algoType)
        {
            if (!File.Exists(positionFile))
            {
                File.WriteAllText(positionFile, "");
            }

            // Position file always contains the holding qty, holding price and holding sell order ref
            ReadPositionFile();

            var orders = new Dictionary <string, EquityOrderBookRecord>();
            var trades = new Dictionary <string, EquityTradeBookRecord>();

            // latest (wrt time) trades or orders appear at start of the output
            errCode = broker.GetEquityTradeBookToday(false, stockCode, out trades);
            errCode = broker.GetEquityOrderBookToday(false, true, stockCode, out orders);

            // any outstanding qty (buy minus sell trades) today except from holding qty trade
            todayOutstandingQty = trades.Where(t => t.Key != holdingSellOrderRef).Sum(t => t.Value.Direction == OrderDirection.SELL ? -t.Value.Quantity : t.Value.Quantity);

            var buyTrades = trades.Where(t => t.Value.Direction == OrderDirection.BUY);

            lastBuyPrice = buyTrades.Any() ? buyTrades.First().Value.Price : 0;

            var numOutstandingBuyTrades = todayOutstandingQty > 0 ? todayOutstandingQty / ordQty : 0;

            // these are latest trades taken. each buy trade is for single lot and thus for each lot there is a trade
            todayOutstandingPrice = numOutstandingBuyTrades == 0 ? 0 : buyTrades.Take(numOutstandingBuyTrades).Average(t => t.Value.Price);

            if (trades.ContainsKey(holdingSellOrderRef))
            {
                ProcessHoldingSellOrderExecution();
            }

            var buyOrders  = orders.Values.Where(o => o.Direction == OrderDirection.BUY && o.Status == OrderStatus.ORDERED);
            var sellOrders = orders.Values.Where(o => o.Direction == OrderDirection.SELL && o.Status == OrderStatus.ORDERED && o.OrderRefenceNumber != holdingSellOrderRef); // pick only today's outstanding related sell orders

            // assumed that there is always at max only single outstanding buy order and a at max single outstanding sell order
            todayOutstandingBuyOrderRef  = buyOrders.Any() ? buyOrders.First().OrderRefenceNumber : "";
            todayOutstandingSellOrderRef = sellOrders.Any() ? sellOrders.First().OrderRefenceNumber : "";

            isFirstBuyOrder = string.IsNullOrEmpty(todayOutstandingBuyOrderRef) && !trades.Where(t => t.Value.Direction == OrderDirection.BUY).Any();

            // if sqoff sell order for holdings is needed then place it
            //assumption is: if there is a holding pending from day before then it would have been converted to delivery
            if (holdingOutstandingQty > 0 && string.IsNullOrEmpty(holdingSellOrderRef))
            {
                // place sq off sell order, update sell order ref
                var sellPrice = GetSellPrice(holdingOutstandingPrice, true);
                errCode = PlaceEquityOrder(stockCode, holdingOutstandingQty, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.DELIVERY, exchange, out holdingSellOrderRef);
                if (errCode == BrokerErrorCode.Success)
                {
                    UpdatePositionFile(holdingOutstandingQty, holdingOutstandingPrice, holdingSellOrderRef);
                    Trace(string.Format(orderTraceFormat, stockCode, "cash holding squareoff sell", holdingOutstandingQty, sellPrice, "CASH", errCode, OrderPriceType.LIMIT));
                }
            }

            // For AverageTheBuyThenSell algo - place sell order for outstanding qty if not already present
            if (algoType == AlgoType.AverageTheBuyThenSell)
            {
                if (string.IsNullOrEmpty(todayOutstandingSellOrderRef) && todayOutstandingQty > 0)
                {
                    var sellPrice = GetSellPrice(todayOutstandingPrice, false);
                    errCode = PlaceEquityOrder(stockCode, todayOutstandingQty, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, out todayOutstandingSellOrderRef);
                }
            }

            buyOrderCount = buyOrders.Count();
        }