void _provider_PositionsUpdateEvent(IOrderSink provider, AccountInfo accountInfo, PositionInfo[] positionsInfos) { foreach (PositionInfo info in positionsInfos) { if (info.Symbol.IsEmpty) { SystemMonitor.Warning("Empty symboled position."); continue; } Position position = ObtainPositionBySymbol(info.Symbol); if (position != null) { position.UpdateInfo(info); } } }
/// <summary> /// Update position parameters. /// </summary> /// <param name="symbol"></param> /// <param name="volumeChange">*Directional* volume change, 0 for no change.</param> /// <param name="operationResultMessage"></param> /// <returns></returns> bool UpdatePosition(Symbol symbol, int volumeChange, out string operationResultMessage) { if (_manager == null || _dataDelivery == null || _dataDelivery.SourceId.IsEmpty) { operationResultMessage = "Not initialized properly for operation."; return(false); } // Update the position corresponding to this order. Position position = _tradeEntities.GetPositionBySymbol(symbol, true); if (position == null) { operationResultMessage = "Failed to find corresponding position."; return(false); } IQuoteProvider quotes = position.QuoteProvider; if (quotes == null) { operationResultMessage = "Failed to find corresponding quotation provider."; return(false); } PositionInfo updatedPositionInfo = position.Info; if (updatedPositionInfo.Volume.HasValue == false) { updatedPositionInfo.Volume = 0; } updatedPositionInfo.PendingBuyVolume = 0; updatedPositionInfo.PendingSellVolume = 0; if (volumeChange != 0) { //decimal initialPositionResult = updatedPositionInfo.Result.Value; decimal?operationBasis = quotes.GetOrderOpenQuote(volumeChange > 0); if (operationBasis.HasValue == false) { operationResultMessage = "Failed to establish order operation basis price."; return(false); } else { //SystemMonitor.CheckError(updatedPositionInfo.Basis.HasValue, "Position has no properly assigned basis price."); } if (RecalculatePositionBasis(ref updatedPositionInfo, volumeChange, operationBasis.Value) == false) { operationResultMessage = "Failed to recalculate position parameters."; return(false); } } decimal?pendingPrice = quotes.GetOrderCloseQuote(updatedPositionInfo.Volume > 0); if (updatedPositionInfo.Volume.HasValue && updatedPositionInfo.Volume != 0 && pendingPrice.HasValue && updatedPositionInfo.Basis.HasValue) { updatedPositionInfo.Result = (pendingPrice.Value - updatedPositionInfo.Basis.Value) * updatedPositionInfo.Volume.Value; } else { updatedPositionInfo.Result = 0; } bool positionClosing = (position.Volume > 0 && volumeChange < 0) || (position.Volume < 0 && volumeChange > 0); if (volumeChange != 0 && positionClosing && position.Info.Result.HasValue && updatedPositionInfo.Result.HasValue) {// Update the account upon closing some (or all) of the position volume. _runningAccountBalance += position.Info.Result.Value - updatedPositionInfo.Result.Value; } position.UpdateInfo(updatedPositionInfo); operationResultMessage = string.Empty; return(true); }