private void SetInitialPrices() { var ordList = new List <OrderInfo>(); var changedList = new List <OrderInfo>(); foreach (var tp in P2_BuyOrders.Where(o => o.StratState == StrategyState.TP_ENTERED)) { if (tp.InitialPrice == 0M || !grid_values.Any(x => x == tp.InitialPrice)) { changedList.Add(new OrderInfo(tp)); var initPrice = tp.Price * (1 - SETTINGS.TakeProfitMargin); tp.InitialPrice = grid_values.Aggregate((x, y) => Math.Abs(x - initPrice) < Math.Abs(y - initPrice) ? x : y); ordList.Add(tp); } } P2_BuyOrders = P2_BuyOrders.Except(changedList).ToList(); P2_BuyOrders.AddRange(ordList); ordList.Clear(); changedList.Clear(); foreach (var tp in P2_SellOrders.Where(o => o.StratState == StrategyState.TP_ENTERED)) { if (tp.InitialPrice == 0M || !grid_values.Any(x => x == tp.InitialPrice)) { changedList.Add(new OrderInfo(tp)); var initPrice = tp.Price * (1 + SETTINGS.TakeProfitMargin); tp.InitialPrice = grid_values.Aggregate((x, y) => Math.Abs(x - initPrice) < Math.Abs(y - initPrice) ? x : y); ordList.Add(tp); } } P2_SellOrders = P2_SellOrders.Except(changedList).ToList(); P2_SellOrders.AddRange(ordList); }
public async Task Deactivate() { if (!P2_Active) { return; } // Cancel all OPEN orders, leave TakeProfits open var canceledOrds = new List <OrderInfo>(); foreach (var ord in P2_BuyOrders.Where(o => o.StratState == StrategyState.OPEN)) { var cancelResp = await BinaREST.CancelOrder(ord.Symbol, ord.ClientID); if (cancelResp != null) { Log.Debug($">>> [P2_BUY] CANCELED - Price: {ord.Price}"); } canceledOrds.Add(ord); } P2_BuyOrders = P2_BuyOrders.Except(canceledOrds).ToList(); canceledOrds.Clear(); foreach (var ord in P2_SellOrders.Where(o => o.StratState == StrategyState.OPEN)) { var cancelResp = await BinaREST.CancelOrder(ord.Symbol, ord.ClientID); if (cancelResp != null) { Log.Debug($">>> [P2_BUY] CANCELED - Price: {ord.Price}"); } canceledOrds.Add(ord); } P2_SellOrders = P2_SellOrders.Except(canceledOrds).ToList(); P2_Active = false; }
public async Task Activate(decimal middle, decimal top, decimal bottom) { // populate grid values if necessary PopulateGridVals(bottom); // snap existing P2 TakeProfit orders to an initial grid price SetInitialPrices(); // narrow down grid_values to only possible order placements var middleRound = Math.Round(middle, PriceRoundDigits); var possibleBuyVals = grid_values.Where(x => x >= middle * (1 - (SETTINGS.grid_interval * SETTINGS.MaxOrdsPerSide)) && x <middleRound && // Within range, and not impeding the phase1 TP boundary x> bottom && x * (1 + SETTINGS.TakeProfitMargin) < top).ToList(); var possibleSellVals = grid_values.Where(x => x <= middle * (1 + (SETTINGS.grid_interval * SETTINGS.MaxOrdsPerSide)) && x > middleRound && x <top && x * (1 - SETTINGS.TakeProfitMargin)> bottom).ToList(); // further filter possibleVals and cancel any OPEN orders that fall outside: var canceledOrds = new List <OrderInfo>(); foreach (var order in P2_BuyOrders) { // remove already placed orders from possibleVals if (order.StratState == StrategyState.OPEN || order.StratState == StrategyState.OPEN_UNCONFIRMED || order.StratState == StrategyState.OPEN_FILLED || order.StratState == StrategyState.PARTIAL_FILL) { possibleBuyVals.Remove(order.Price); } // cancel any OPEN status orders outside the possibleVals else if (order.StratState == StrategyState.OPEN && !possibleBuyVals.Any(x => x == order.Price)) { var cancelResp = await BinaREST.CancelOrder(order.Symbol, order.ClientID); if (cancelResp != null) { Log.Debug($">>> [P2_BUY] CANCELED - Price: {order.Price}"); } canceledOrds.Add(order); } // and remove possibleVals that already have corresponding TakeProfit.InitPrice open else if (order.StratState == StrategyState.TP_ENTERED || order.StratState == StrategyState.TP_UNCONFIRMED || order.StratState == StrategyState.TP_FILLED) { possibleBuyVals.Remove(order.InitialPrice); } } P2_BuyOrders = P2_BuyOrders.Except(canceledOrds).ToList(); // Same as above for Sell side: canceledOrds.Clear(); foreach (var order in P2_SellOrders) { if (order.StratState == StrategyState.OPEN || order.StratState == StrategyState.OPEN_UNCONFIRMED || order.StratState == StrategyState.OPEN_FILLED || order.StratState == StrategyState.PARTIAL_FILL) { possibleSellVals.Remove(order.Price); } else if (order.StratState == StrategyState.OPEN && !possibleSellVals.Any(x => x == order.Price)) { var cancelResp = await BinaREST.CancelOrder(order.Symbol, order.ClientID); if (cancelResp != null) { Log.Debug($">>> [P2_SELL] CANCELED - Price: {order.Price}"); } canceledOrds.Add(order); } else if (order.StratState == StrategyState.TP_ENTERED || order.StratState == StrategyState.TP_UNCONFIRMED || order.StratState == StrategyState.TP_FILLED) { possibleSellVals.Remove(order.InitialPrice); } } P2_SellOrders = P2_SellOrders.Except(canceledOrds).ToList(); possibleBuyVals = possibleBuyVals.Distinct().ToList(); possibleSellVals = possibleSellVals.Distinct().ToList(); // place orders on remaining values, add to orderInfo Lists possibleBuyVals.OrderByDescending(v => v); foreach (var p in possibleBuyVals) { // FIRST REPLACE ANY 'TP_FILLED' WITH COMPOUNDED GAINS var filledTP = P2_BuyOrders.FirstOrDefault(o => o.StratState == StrategyState.TP_FILLED); if (filledTP != null) { var buyQty = Math.Round(Convert.ToDecimal(filledTP.BaseCurrReturn) / (p * (1 + SETTINGS.FeePercentage)), QtyRoundDigits); var order = new CreateOrderRequest() { Side = OrderSide.Buy, Symbol = MarketSymbol, Price = p, Quantity = buyQty, NewClientOrderId = filledTP.ClientID }; var response = await BinaREST.CreateLimitOrder(order); if (response != null) { Log.Debug($">>> [BUY] (RE)ORDER PLACED - Price: {p}"); } // update order info var newOrd = new OrderInfo(order, StrategyState.OPEN_UNCONFIRMED); newOrd.InitialPrice = p; P2_BuyOrders[P2_BuyOrders.IndexOf(P2_BuyOrders.First(o => o.ClientID == filledTP.ClientID))] = newOrd; } //Place remaining available OPEN order slots else if (P2_BuyOrders.Count() < SETTINGS.MaxOrdsPerSide) { var buyQty = Math.Round(SETTINGS.PrimaryWager / (p * (1 + SETTINGS.FeePercentage)), QtyRoundDigits); var order = new CreateOrderRequest() { Side = OrderSide.Buy, Symbol = MarketSymbol, Price = p, Quantity = buyQty, NewClientOrderId = "bin2_Buy_" + UniqueString() }; var response = await BinaREST.CreateLimitOrder(order); if (response != null) { Log.Debug($">>> [P2_BUY] ORDER PLACED - Price: {p}"); } // add order status to prevent repeat order var newOrd = new OrderInfo(order, StrategyState.OPEN_UNCONFIRMED); newOrd.InitialPrice = p; P2_BuyOrders.Add(newOrd); } // MOVE UP LOWER BUY ORDERS else if (P2_BuyOrders.Any(o => o.StratState == StrategyState.OPEN && o.Price < p)) { // Cancel lowest buy order var minPrice = P2_BuyOrders.Where(o => o.StratState == StrategyState.OPEN).Min(o => o.Price); var oldOrder = P2_BuyOrders.First(o => o.Price == minPrice); var baseReturn = 0M; if (oldOrder.BaseCurrReturn != null) { baseReturn = Convert.ToDecimal(oldOrder.BaseCurrReturn); } var cancelResp = await BinaREST.CancelOrder(oldOrder.Symbol, oldOrder.ClientID); if (cancelResp != null) { Log.Debug($">>> [P2_SELL] CANCELED - Price: {oldOrder.Price}"); } P2_BuyOrders.Remove(oldOrder); // Place order at correct price // If baseCurr != 0, use this to calc QTY, else primary wager var buyQty = Math.Round(SETTINGS.PrimaryWager / (p * (1 + SETTINGS.FeePercentage)), QtyRoundDigits); if (baseReturn != 0) { buyQty = Math.Round(Convert.ToDecimal(baseReturn) / (p * (1 + SETTINGS.FeePercentage)), QtyRoundDigits); } var order = new CreateOrderRequest() { Side = OrderSide.Buy, Symbol = MarketSymbol, Price = p, Quantity = buyQty, NewClientOrderId = "bin2_Buy_" + UniqueString() }; var response = await BinaREST.CreateLimitOrder(order); if (response != null) { Log.Debug($">>> [P2_BUY] ORDER PLACED - Price: {p}"); } // add order status to prevent repeat order var newOrd = new OrderInfo(order, StrategyState.OPEN_UNCONFIRMED); newOrd.InitialPrice = p; P2_BuyOrders.Add(newOrd); } } // Same as above for sell side: possibleSellVals.OrderBy(v => v); foreach (var p in possibleSellVals) { // FIRST REPLACE ANY 'TP_FILLED' WITH COMPOUNDED GAINS var filledTP = P2_SellOrders.FirstOrDefault(o => o.StratState == StrategyState.TP_FILLED); if (filledTP != null) { var sellQty = filledTP.Qty; var order = new CreateOrderRequest() { Side = OrderSide.Sell, Symbol = MarketSymbol, Price = p, Quantity = sellQty, NewClientOrderId = filledTP.ClientID }; var response = await BinaREST.CreateLimitOrder(order); if (response != null) { Log.Debug($">>> [SELL] ORDER (RE)PLACED - Price: {p}"); } // update order info var newOrd = new OrderInfo(order, StrategyState.OPEN_UNCONFIRMED); newOrd.InitialPrice = p; P2_SellOrders[P2_SellOrders.IndexOf(P2_SellOrders.First(o => o.ClientID == filledTP.ClientID))] = newOrd; } //Place remaining available OPEN order slots else if (P2_SellOrders.Count() < SETTINGS.MaxOrdsPerSide) { var sellQty = Math.Round(SETTINGS.PrimaryWager / (p * (1 - SETTINGS.FeePercentage)), QtyRoundDigits); var order = new CreateOrderRequest() { Side = OrderSide.Sell, Symbol = MarketSymbol, Price = p, Quantity = sellQty, NewClientOrderId = "bin2_Sell_" + UniqueString() }; var response = await BinaREST.CreateLimitOrder(order); if (response != null) { Log.Debug($">>> [P2_SELL] ORDER PLACED - Price: {p}"); } // add order status to prevent repeat order var newOrd = new OrderInfo(order, StrategyState.OPEN_UNCONFIRMED); newOrd.InitialPrice = p; P2_SellOrders.Add(newOrd); } // MOVE DOWN ANY HIGHER SELL ORDERS else if (P2_SellOrders.Any(o => o.StratState == StrategyState.OPEN && o.Price > p)) { // Cancel order var maxPrice = P2_SellOrders.Where(o => o.StratState == StrategyState.OPEN).Max(o => o.Price); var oldOrder = P2_SellOrders.First(o => o.Price == maxPrice); var baseCurr = (oldOrder.Price * (1 - SETTINGS.FeePercentage)) * oldOrder.Qty; var cancelResp = await BinaREST.CancelOrder(oldOrder.Symbol, oldOrder.ClientID); if (cancelResp != null) { Log.Debug($">>> [P2_SELL] CANCELED - Price: {oldOrder.Price}"); } P2_SellOrders.Remove(oldOrder); // Place order at correct price // use same BaseCurr wager amount var sellQty = Math.Round(baseCurr / (p * (1 - SETTINGS.FeePercentage)), QtyRoundDigits); var order = new CreateOrderRequest() { Side = OrderSide.Sell, Symbol = MarketSymbol, Price = p, Quantity = sellQty, NewClientOrderId = "bin2_Sell_" + UniqueString() }; var response = await BinaREST.CreateLimitOrder(order); if (response != null) { Log.Debug($">>> [P2_SELL] ORDER PLACED - Price: {p}"); } // add order status to prevent repeat order var newOrd = new OrderInfo(order, StrategyState.OPEN_UNCONFIRMED); newOrd.InitialPrice = p; P2_SellOrders.Add(newOrd); } } P2_Active = true; }