private void CheckDistanceToOrder() { // минимально допустимая цена для открытия лонг позиции decimal downPriceLong = _tab.PriceBestBid - MaxOrderDistance * _tab.Securiti.PriceStep; // максимально допустимая цена для открытия шорт позиции decimal upPriceShort = _tab.PriceBestAsk + MaxOrderDistance * _tab.Securiti.PriceStep; // получаем все открытые позиции List <Position> positions = _tab.PositionsOpenAll; for (int i = 0; i < positions.Count; i++) { // если у позиции есть ордер на открытие и исполненный объем ордера равен нулю // и цена ордера вышла за предельную цену, то отзываем ордер if (positions[i].OpenActiv && positions[i].OpenOrders[positions[i].OpenOrders.Count - 1].VolumeExecute == 0) { if (positions[i].Direction == Side.Buy && positions[i].OpenOrders[positions[i].OpenOrders.Count - 1].Price < downPriceLong) { _tab.CloseAllOrderToPosition(positions[i]); continue; } else if (positions[i].Direction == Side.Sell && positions[i].OpenOrders[positions[i].OpenOrders.Count - 1].Price > upPriceShort) { _tab.CloseAllOrderToPosition(positions[i]); continue; } } // если у позициии есть ордер на закрытие и исполненный объем ордера равен нулю // и цена ордера вышла за предельную цену, то отзываем ордер if (positions[i].CloseActiv && positions[i].CloseOrders[positions[i].CloseOrders.Count - 1].VolumeExecute == 0) { if (positions[i].Direction == Side.Buy && positions[i].CloseOrders[positions[i].CloseOrders.Count - 1].Price > upPriceShort) { _tab.CloseAllOrderToPosition(positions[i]); continue; } else if (positions[i].Direction == Side.Sell && positions[i].CloseOrders[positions[i].CloseOrders.Count - 1].Price < downPriceLong) { _tab.CloseAllOrderToPosition(positions[i]); continue; } } } }
private void CanselAllOrders() { List <Position> openPositions = _tab.PositionsOpenAll; Position[] poses = openPositions.ToArray(); for (int i = 0; poses != null && i < poses.Length; i++) { if (poses[i].State != PositionStateType.Open) { _tab.CloseAllOrderToPosition(poses[i]); } Thread.Sleep(200); } Thread.Sleep(1000); if (openPositions.Count != 0) { Thread.Sleep(1000); } if (openPositions.Count != 0) { Thread.Sleep(1000); } }
/// <summary> /// Обработка события не удачного закрытия позиции /// </summary> /// <param name="position">позиция, которая не закрылась</param> private void Tab_PositionClosingFailEvent(Position position) { // если позиция еще не полностью закрылась и у неё остались ордера на закрытие, то закрываем их if (position.CloseActiv) { _tab.CloseAllOrderToPosition(position); _tab.SetNewLogMessage($"Tab_PositionClosingFailEvent: у позиции остались активные ордера. Закрываем их.", Logging.LogMessageType.User); System.Threading.Thread.Sleep(4000); } // не закрытую со второго раза позицию закрываем по маркету if (position.SignalTypeClose == "reclosing") { _tab.CloseAtMarket(position, position.OpenVolume); _tab.SetNewLogMessage($"Tab_PositionClosingFailEvent: закрытие позиции {position.Number}" + " по маркету: объем - {position.OpenVolume}.", Logging.LogMessageType.User); return; } // повторно пытаемся закрыть позицию по лимиту else { if (OnDebug.ValueBool) { _tab.SetNewLogMessage($"Отладка. Tab_PositionClosingFailEvent: повторная попытка закрыть позицию {position.Number}" + " по лимиту.", Logging.LogMessageType.User); } position.SignalTypeClose = "reclosing"; if (position.Direction == Side.Buy) { CloseLong(position); } else if (position.Direction == Side.Sell) { CloseShort(position); } } return; }
/// <summary> /// попробовать закрыть позицию /// </summary> private void TryClosePosition(Position position, List <Candle> candles) { if (EmulatorIsOn) { int currentEmuPos = GetCurrentPosition(); if (currentEmuPos == 0 || currentEmuPos == 1 && position.Direction == Side.Sell || currentEmuPos == -1 && position.Direction == Side.Buy) { _tab.SetNewLogMessage("Кроем позицию по эмулятору. Номер позиции: " + position.Number, LogMessageType.System); // Выход по эмулятору! позиции нет. Нужно закрывать полюбой цене _tab.CloseAllOrderToPosition(position); _timeToClose = DateTime.Now.AddSeconds(3); _positionToClose = position; return; } } // первый выход по проколу if (Shoulderette(candles.Count - 1, candles)) { // если произошёл прокол и мы заработали больше 20% if (position.EntryPrice * 1.2m <= candles[candles.Count - 1].Close) { _tab.CloseAtLimit(position, candles[candles.Count - 1].Close - SlipageCloseFirst * _tab.Securiti.PriceStep, position.OpenVolume); //Sell(_settings.Position, _myCandles[_myCandles.Length - 1].ClosePrice); return; } } // второй выход по стопам if (position.Direction == Side.Buy) { decimal priceEtalon = Math.Round(((Line)_chandelier).Values[((Line)_chandelier).Values.Count - 1], _tab.Securiti.Decimals); if (_tab.Securiti.Decimals == 0) { priceEtalon = Math.Truncate(((Line)_chandelier).Values[((Line)_chandelier).Values.Count - 1]); } decimal priceOrder = priceEtalon - _tab.Securiti.PriceStep * SlipageCloseFirst; // ЗДЕСЬ!!!!!!!!!!!!!! decimal priceRedLine = priceEtalon + _tab.Securiti.PriceStep * SlipageReversClose; if (priceRedLine - _tab.Securiti.PriceStep * 10 > _tab.PriceBestAsk) { _tab.CloseAtLimit(position, _tab.PriceBestAsk, position.OpenVolume); return; } _tab.CloseAtStop(position, priceRedLine, priceOrder); if (StartProgram != StartProgram.IsTester && AlertIsOn) { _alert.PriceActivation = priceRedLine + SlipageToAlert * _tab.Securiti.PriceStep; _alert.TypeActivation = PriceAlertTypeActivation.PriceLowerOrEqual; _alert.MessageIsOn = true; _alert.MusicType = AlertMusic.Duck; _alert.Message = "Приближаемся к точке выхода"; _alert.IsOn = true; } } }
/// <summary> /// new marketDepth event /// новый входящий стакан /// </summary> void _tab_MarketDepthUpdateEvent(MarketDepth marketDepth) { if (Regime.ValueString == "Off") { return; } if (marketDepth.Asks == null || marketDepth.Asks.Count == 0 || marketDepth.Bids == null || marketDepth.Bids.Count == 0) { return; } if (_tab.PositionsOpenAll.Find(pos => pos.State == PositionStateType.Open || pos.State == PositionStateType.Closing ) != null) { return; } if (StartProgram == StartProgram.IsOsTrader && _lastCheckTime.AddSeconds(1) > DateTime.Now) { // in real trade, check marketDepth once at second // в реальной торговле, проверяем стакан раз в секунду return; } _lastCheckTime = DateTime.Now; Position positionBuy = _tab.PositionsOpenAll.Find(pos => pos.Direction == Side.Buy); Position positionSell = _tab.PositionsOpenAll.Find(pos => pos.Direction == Side.Sell); // buy / покупка decimal buyPrice = 0; int lastVolume = 0; for (int i = 0; i < marketDepth.Bids.Count && i < MaxLevelsInMarketDepth.ValueInt; i++) { if (marketDepth.Bids[i].Bid > lastVolume) { buyPrice = marketDepth.Bids[i].Price + _tab.Securiti.PriceStep; lastVolume = Convert.ToInt32(marketDepth.Bids[i].Bid); } } if (positionBuy != null && positionBuy.OpenOrders[0].Price != buyPrice && positionBuy.State != PositionStateType.Open && positionBuy.State != PositionStateType.Closing) { if (StartProgram == StartProgram.IsOsTrader) { _positionsToClose.Add(positionBuy); } else { _tab.CloseAllOrderToPosition(positionBuy); } _tab.BuyAtLimit(Volume.ValueDecimal, buyPrice); } if (positionBuy == null) { _tab.BuyAtLimit(Volume.ValueDecimal, buyPrice); } // sell продажа decimal sellPrice = 0; int lastVolumeInAsk = 0; for (int i = 0; i < marketDepth.Asks.Count && i < MaxLevelsInMarketDepth.ValueInt; i++) { if (marketDepth.Asks[i].Ask > lastVolumeInAsk) { sellPrice = marketDepth.Asks[i].Price - _tab.Securiti.PriceStep; lastVolumeInAsk = Convert.ToInt32(marketDepth.Asks[i].Ask); } } if (positionSell != null && positionSell.OpenOrders[0].Price != sellPrice && positionSell.State != PositionStateType.Open && positionSell.State != PositionStateType.Closing) { if (StartProgram == StartProgram.IsOsTrader) { _positionsToClose.Add(positionSell); } else { _tab.CloseAllOrderToPosition(positionSell); } _tab.SellAtLimit(Volume.ValueDecimal, sellPrice); } if (positionSell == null) { _tab.SellAtLimit(Volume.ValueDecimal, sellPrice); } }
/// <summary> /// выставить стоп приказ по открытой позиции /// </summary> private void TryClosePosition(Position position, List <Candle> candles) { if (EmulatorIsOn) { int currentEmuPos = GetCurrentPosition(); if (currentEmuPos == 0 || currentEmuPos == 1 && position.Direction == Side.Sell || currentEmuPos == -1 && position.Direction == Side.Buy) { _tab.SetNewLogMessage("Кроем позицию по эмулятору. Номер позиции: " + position.Number, LogMessageType.System); // Выход по эмулятору! позиции нет. Нужно закрывать полюбой цене _tab.CloseAllOrderToPosition(position); _timeToClose = DateTime.Now.AddSeconds(3); _positionToClose = position; return; } } if (position.Direction == Side.Buy) { decimal priceEtalon = GetPriseStop(Side.Buy, candles.Count - 1); decimal priceOrder = priceEtalon - _tab.Securiti.PriceStep * SlipageCloseFirst; // ЗДЕСЬ!!!!!!!!!!!!!! decimal priceRedLine = priceEtalon + SlipageReversClose * _tab.Securiti.PriceStep; if (priceRedLine - _tab.Securiti.PriceStep * 10 > _tab.PriceBestAsk) { _tab.CloseAtLimit(position, _tab.PriceBestAsk, position.OpenVolume); return; } _tab.CloseAtStop(position, priceRedLine, priceOrder); if (StartProgram != StartProgram.IsTester && AlertIsOn) { _alert.PriceActivation = priceRedLine + SlipageToAlert * _tab.Securiti.PriceStep; _alert.TypeActivation = PriceAlertTypeActivation.PriceLowerOrEqual; _alert.MessageIsOn = true; _alert.MusicType = AlertMusic.Duck; _alert.Message = "Приближаемся к точке выхода"; _alert.IsOn = true; } } if (position.Direction == Side.Sell) { decimal priceEtalon = GetPriseStop(Side.Sell, candles.Count - 1); decimal priceOrder = priceEtalon + _tab.Securiti.PriceStep * SlipageCloseFirst; // ЗДЕСЬ!!!!!!!!!!!!!! decimal priceRedLine = priceEtalon - SlipageReversClose * _tab.Securiti.PriceStep; if (priceRedLine + _tab.Securiti.PriceStep * 10 < _tab.PriceBestAsk) { _tab.CloseAtLimit(position, _tab.PriceBestAsk, position.OpenVolume); return; } _tab.CloseAtStop(position, priceRedLine, priceOrder); if (StartProgram != StartProgram.IsTester && AlertIsOn) { _alert.PriceActivation = priceRedLine - SlipageToAlert * _tab.Securiti.PriceStep; _alert.TypeActivation = PriceAlertTypeActivation.PriceHigherOrEqual; _alert.MessageIsOn = true; _alert.MusicType = AlertMusic.Duck; _alert.Message = "Приближаемся к точке выхода"; _alert.IsOn = true; } } }
/// <summary> /// проверить условия на закрытие позиции /// </summary> private void TryClosePosition(Position position) { if (EmulatorIsOn) { int currentEmuPos = GetCurrentPosition(); if (currentEmuPos == 0 || currentEmuPos == 1 && position.Direction == Side.Sell || currentEmuPos == -1 && position.Direction == Side.Buy) { // Выход по эмулятору! позиции нет. Нужно закрывать полюбой цене _tab.CloseAllOrderToPosition(position); _timeToClose = DateTime.Now.AddSeconds(3); _positionToClose = position; return; } } // БАЙ if (position.Direction == Side.Sell) { decimal lineBuy = GetPriceToClosePos(Side.Buy); if (lineBuy == 0) { return; } decimal priceOrder = lineBuy + _tab.Securiti.PriceStep * SlipageCloseFirst; // ЗДЕСЬ!!!!!!!!!!!!!! decimal priceRedLine = lineBuy - _tab.Securiti.PriceStep * SlipageReversClose; if (priceRedLine + _tab.Securiti.PriceStep * 10 < _tab.PriceBestAsk) { _tab.CloseAtLimit(position, _tab.PriceBestAsk, position.OpenVolume); return; } _tab.CloseAtStop(position, priceRedLine, priceOrder); } // СЕЛЛ if (position.Direction == Side.Buy) { decimal lineSell = GetPriceToClosePos(Side.Sell); if (lineSell == 0) { return; } decimal priceOrderSell = lineSell - _tab.Securiti.PriceStep * SlipageCloseFirst; // ЗДЕСЬ!!!!!!!!!!!!!! decimal priceRedLineSell = lineSell + _tab.Securiti.PriceStep * SlipageReversClose; if (priceRedLineSell - _tab.Securiti.PriceStep * 10 > _tab.PriceBestAsk) { _tab.CloseAtLimit(position, _tab.PriceBestAsk, position.OpenVolume); return; } _tab.CloseAtStop(position, priceRedLineSell, priceOrderSell); } }