public override void onTick(Tick <int> currTick) { lock (sObject) { try { base.InitComment(); if (!this.TestingMode) { spreadAnalyzer.EvaluateSpread(currTick); } if (currTime.Ticks / (TickHistory.tickInOneMinute) == currTick.DateTime.Ticks / (TickHistory.tickInOneMinute)) { return; } currTime = currTick.DateTime; foreach (BuyLimitAndWaitParam cparam in customParams) { if (cparam.InitHistoryMinutes > 0) { cparam.historySimulator = new HistorySimulator(cparam, base.TestingMode, new BuyLimitAndWaitStrategy(), this.param, cparam.Symbol, this.Meta); if (TestingMode) { cparam.StartDate = currTick.DateTime.AddMinutes(-cparam.InitHistoryMinutes); } List <string> logString; base.AddComment(cparam.ID, string.Format("Start simulate from {0} to {1}\n", cparam.StartDate.ToShortDateString(), currTick.DateTime.ToShortDateString())); IEnumerable <Order> newOrders = cparam.historySimulator.Init(currTick.DateTime, cparam.StartDate, out logString); if (cparam.historySimulator.IsSuccessful) { base.AddComment(cparam.ID, "Simulation was successful"); if (TestingMode) { Tick <int> currSymbolTick = new Tick <int>(); currSymbolTick.Ask = Meta.MarketInfo(cparam.Symbol, MarketInfoType.MODE_ASK); currSymbolTick.Bid = Meta.MarketInfo(cparam.Symbol, MarketInfoType.MODE_BID); currSymbolTick.DateTime = currTick.DateTime; currSymbolTick.volume = 1; AddOrders(currSymbolTick, newOrders.Where(p => p.Comment.StartsWith(cparam.IdentityComment))); } } else { base.AddComment(cparam.ID, "History Simulator return error. Init state is not valid.\n"); } cparam.InitHistoryMinutes = 0; } } IEnumerable <Order> allBuyOrders = OrderOperation.GetBuyMarketOrders(); IEnumerable <Order> allSellOrders = OrderOperation.GetSellMarketOrders(); IEnumerable <Order> allBuyLimitOrders; IEnumerable <Order> allSellLimitOrders; if (!TestingMode) { PositionAggregator pa = new PositionAggregator(); foreach (BuyLimitAndWaitParam cparam in customParams) { Tick <int> currSymbolTick = new Tick <int>(); currSymbolTick.Ask = Meta.MarketInfo(cparam.Symbol, MarketInfoType.MODE_ASK); currSymbolTick.Bid = Meta.MarketInfo(cparam.Symbol, MarketInfoType.MODE_BID); currSymbolTick.DateTime = currTick.DateTime; currSymbolTick.volume = 1; IEnumerable <Order> requiredOrders = cparam.historySimulator.AddTick(currSymbolTick); //IEnumerable<Order> openedOrders = allBuyOrders.Where(p => p.Comment.StartsWith(cparam.IdentityComment)) // .Union(allSellOrders.Where(p => p.Comment.StartsWith(cparam.IdentityComment))); pa.AddRequrementPosition(requiredOrders); base.AddCommentLine(cparam.Symbol, string.Format("{0} - openPrices={1}, tpPrices={2}", currSymbolTick.DateTime.ToShortTimeString(), String.Join(", ", cparam.historySimulator.LimitOrders.Select(p => p.OpenPrice)), String.Join(", ", cparam.historySimulator.MarketOrders.Select(p => p.TP)) )); } foreach (BuyLimitAndWaitParam cparam in customParams) { pa.CheckMinTradeVolumeSize(cparam.Symbol, cparam.MinTradeVolume); } pa.AddCurrentPositions(allBuyOrders); pa.AddCurrentPositions(allSellOrders); foreach (KeyValuePair <string, int> kv in pa.ResultDiff.Where(p => p.Value != 0)) { Tick <int> currSymbolTick = new Tick <int>(); currSymbolTick.Ask = Meta.MarketInfo(kv.Key, MarketInfoType.MODE_ASK); currSymbolTick.Bid = Meta.MarketInfo(kv.Key, MarketInfoType.MODE_BID); currSymbolTick.DateTime = currTick.DateTime; currSymbolTick.volume = 1; AddComment(string.Format("Adding new order for symbol {0} with volume {1}", kv.Key, kv.Value)); Meta.OrderSend(kv.Key, OrderType.Market, kv.Value > 0 ? OrderSide.Buy : OrderSide.Sell, Math.Abs(kv.Value), kv.Value > 0 ? currSymbolTick.Ask : currSymbolTick.Bid, 0, 0, ""); } allBuyOrders = OrderOperation.GetBuyMarketOrders(); allSellOrders = OrderOperation.GetSellMarketOrders(); var elem = allBuyOrders.Join(allSellOrders, bO => bO.Symbol, sO => sO.Symbol, (bO, sO) => new { t1 = bO.ID, t2 = sO.ID }).FirstOrDefault(); if (elem != null) { AddComment(string.Format("Trying to close by two orders: {0} and {1}.", elem.t1, elem.t2)); Meta.OrderCloseBy(elem.t1, elem.t2, 0); AddComment(string.Format("Successfull close by two orders: {0} and {1}.", elem.t1, elem.t2)); } return; } BuyLimitAndWaitParam firstParam = customParams[0]; RemoveAllLimitWithoutPair(OrderOperation.GetBuyLimitOrders(), OrderOperation.GetSellLimitOrders(), firstParam, currTick); allBuyLimitOrders = OrderOperation.GetBuyLimitOrders(); allSellLimitOrders = OrderOperation.GetSellLimitOrders(); Order minBuyOrder = null; Order maxSellOrder = null; if (allBuyOrders != null) { minBuyOrder = allBuyOrders .Where(p => p.Comment.StartsWith(firstParam.IdentityComment)) //.MinElement(p => p.OpenPrice); .MinElement(p => p.TP); } if (allSellOrders != null) { maxSellOrder = allSellOrders .Where(p => p.Comment.StartsWith(firstParam.IdentityComment)) //.MaxElement(p => p.OpenPrice); .MaxElement(p => p.TP); } bool isLimitExist = allSellLimitOrders.Where(p => p.Comment.StartsWith(firstParam.IdentityComment)).Count() != 0 || allBuyLimitOrders.Where(p => p.Comment.StartsWith(firstParam.IdentityComment)).Count() != 0; if (this.TestingMode && minBuyOrder != null && !isLimitExist) { RegisterTickToHandle.RegisterBuyLimit((minBuyOrder.TP - 2 * firstParam.TP) - firstParam.OpenOrderShift); } if (this.TestingMode && maxSellOrder != null && !isLimitExist) { RegisterTickToHandle.RegisterSellLimit(firstParam.OpenOrderShift + (maxSellOrder.TP + 2 * firstParam.TP)); } if (!isLimitExist && //(minBuyOrder != null && minBuyOrder.OpenPrice - currSymbolTick.Ask > firstParam.OpenOrderShift //|| maxSellOrder != null && currSymbolTick.Bid - maxSellOrder.OpenPrice > firstParam.OpenOrderShift (minBuyOrder != null && (minBuyOrder.TP - 2 * firstParam.TP) - currTick.Ask >= firstParam.OpenOrderShift || maxSellOrder != null && currTick.Bid - (maxSellOrder.TP + 2 * firstParam.TP) >= firstParam.OpenOrderShift || minBuyOrder == null && maxSellOrder == null) ) { string comment = firstParam.NewUniqueComment(); int openPrice = currTick.Ask - firstParam.TP; if (firstParam.OpenMode != OpenMode.OnlySell && (minBuyOrder == null || (minBuyOrder.TP - 2 * firstParam.TP) - openPrice >= firstParam.OpenOrderShift)) { int buyOrderID = Meta.OrderSend(firstParam.Symbol, OrderType.Limit, OrderSide.Buy, firstParam.BasicVolume, openPrice, 0, openPrice + 2 * firstParam.TP, comment); if (buyOrderID <= 0) { Meta.Print(string.Format("Error of adding buy order. Price = {0} Symbol = {1}", openPrice, firstParam.Symbol)); Meta.Comment(string.Format("Error of adding buy order. Price = {0} Symbol = {1}", openPrice, firstParam.Symbol)); return; } this.RegisterTickToHandle.RegisterBuyStop(openPrice + 2 * firstParam.TP); } openPrice = currTick.Bid + firstParam.TP; if (firstParam.OpenMode != OpenMode.OnlyBuy && (maxSellOrder == null || openPrice - (maxSellOrder.TP + 2 * firstParam.TP) >= firstParam.OpenOrderShift)) { int sellOrderID = Meta.OrderSend(firstParam.Symbol, OrderType.Limit, OrderSide.Sell, firstParam.BasicVolume, openPrice, 0, openPrice - 2 * firstParam.TP, comment); if (sellOrderID <= 0) { Meta.Print(string.Format("Error of adding sell order. Price = {0} Symbol = {1}", openPrice, firstParam.Symbol)); Meta.Comment(string.Format("Error of adding sell order. Price = {0} Symbol = {1}", openPrice, firstParam.Symbol)); } this.RegisterTickToHandle.RegisterSellStop(openPrice - 2 * firstParam.TP); } } } catch (HistoryNotAvailableExceptions exc) { logger.AddMessage("tick = {0}\r\n {1}", currTick.DateTime.ToLongTimeString(), exc); throw; } finally { ShowComment(); } } }