/// <summary>
        /// 
        /// </summary>
        protected override string OnExecuteMarket(ISourceOrderExecution provider, OrderTypeEnum orderType, int volume, 
            decimal? price, decimal? slippage, decimal? takeProfit, decimal? stopLoss, TimeSpan timeOut,
            out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            SystemMonitor.CheckError(provider.SupportsActiveOrderManagement, "Wrong position type for this provider.");

            executionInfo = PositionExecutionInfo.Empty;

            IQuoteProvider quoteProvider = _manager.ObtainQuoteProvider(_dataDelivery.SourceId, Symbol);
            if (quoteProvider == null)
            {
                operationResultMessage = "Failed to establish quote provider for [" + _dataDelivery.SourceId.Name + ", " + Symbol.Name + "].";
                SystemMonitor.Error(operationResultMessage);
                return string.Empty;
            }

            price = ProcessPrice(quoteProvider, orderType, price);

            // New order shall be created.
            ActiveOrder order = new ActiveOrder(_manager, provider, quoteProvider, _dataDelivery.SourceId, Symbol, true);

            OrderInfo? infoReference;

            // Using the extended operationTimeOut to 40 seconds.
            bool result = provider.SynchronousExecute(provider.DefaultAccount.Info, order, _info.Symbol,
                orderType, volume, slippage, price, takeProfit, stopLoss, string.Empty, TimeSpan.FromSeconds(40), out infoReference, out operationResultMessage);

            if (result && infoReference.HasValue)
            {
                OrderInfo infoAssign = infoReference.Value;
                if (infoAssign.Type == OrderTypeEnum.UNKNOWN)
                {
                    infoAssign.Type = orderType;
                }

                if (infoAssign.Volume == int.MinValue
                    || infoAssign.Volume == int.MaxValue)
                {// Volume was not retrieved by integration.
                    infoAssign.Volume = volume;
                }

                if (infoAssign.OpenPrice.HasValue)
                {
                    executionInfo = new PositionExecutionInfo(infoReference.Value.Id, _dataDelivery.SourceId, provider.SourceId, Symbol,
                        infoAssign.Type, infoAssign.OpenPrice.Value, volume, volume,
                        infoAssign.OpenTime, PositionExecutionInfo.ExecutionResultEnum.Success);
                }
                else
                {
                    SystemMonitor.Error("Received execution result, but price not assigned.");
                }

                order.AdoptInfo(infoAssign);

                provider.TradeEntities.AddOrder(order);
                return infoReference.Value.Id;
            }

            return string.Empty;
        }
Example #2
0
        /// <summary>
        /// This may contain a few operations on active orders, in order to match the rule "no opposing active orders"
        /// </summary>
        public virtual string ExecuteMarketBalanced(int volumeModification, decimal?desiredPrice, decimal?slippage, TimeSpan timeOut,
                                                    out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            executionInfo = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _orderProvider;

            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not properly initialized.";
                return(string.Empty);
            }

            // Trace pre-execution info.
            string traceMessage = string.Format("Submit Volume Modification [{0}] Price [{1}] Slippage [{2}] TimeOut [{3}]",
                                                volumeModification.ToString(), GeneralHelper.ToString(desiredPrice), GeneralHelper.ToString(slippage), timeOut.ToString());

            traceMessage += GenerateConditionsInfo();

            TracerHelper.Trace(_tracer, traceMessage, TracerItem.PriorityEnum.High);

            if (OnExecuteMarketBalanced(provider, volumeModification, desiredPrice, slippage, timeOut, out executionInfo, out operationResultMessage))
            {
                return(Guid.NewGuid().ToString());
            }

            return(string.Empty);
        }
        /// <summary>
        ///
        /// </summary>
        protected override string OnExecuteMarket(ISourceOrderExecution provider, OrderTypeEnum orderType, int volume,
                                                  decimal?price, decimal?slippage, decimal?takeProfit, decimal?stopLoss, TimeSpan timeOut,
                                                  out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            SystemMonitor.CheckError(provider.SupportsActiveOrderManagement == false, "Wrong position type for this provider.");

            executionInfo = PositionExecutionInfo.Empty;
            PassiveOrder order;

            lock (this)
            {
                order = new PassiveOrder(_manager, _dataDelivery.SourceId, provider.SourceId);
            }

            OrderInfo?infoReference;

            bool result = provider.SynchronousExecute(provider.DefaultAccount.Info, order, _info.Symbol,
                                                      orderType, volume, slippage, price, takeProfit, stopLoss, string.Empty, out infoReference, out operationResultMessage);

            if (result && infoReference.HasValue)
            {
                OrderInfo infoAssign = infoReference.Value;
                if (infoAssign.Type == OrderTypeEnum.UNKNOWN)
                {
                    infoAssign.Type = orderType;
                }

                if (infoAssign.Volume == int.MinValue ||
                    infoAssign.Volume == int.MaxValue)
                {// Volume was not retrieved by integration.
                    infoAssign.Volume = volume;
                }

                if (infoAssign.OpenPrice.HasValue)
                {
                    executionInfo = new PositionExecutionInfo(infoReference.Value.Id, _dataDelivery.SourceId, provider.SourceId, Symbol,
                                                              infoAssign.Type, infoAssign.OpenPrice.Value, volume, volume,
                                                              infoAssign.OpenTime, PositionExecutionInfo.ExecutionResultEnum.Success);
                }
                else
                {
                    SystemMonitor.Error("Received execution result, but price not assigned.");
                }

                order.AdoptInfo(infoAssign);

                provider.TradeEntities.AddOrder(order);

                return(infoReference.Value.Id);
            }

            return(string.Empty);
        }
        /// <summary>
        /// 
        /// </summary>
        protected override string OnExecuteMarket(ISourceOrderExecution provider, OrderTypeEnum orderType, int volume, 
            decimal? price, decimal? slippage, decimal? takeProfit, decimal? stopLoss, TimeSpan timeOut, 
            out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            SystemMonitor.CheckError(provider.SupportsActiveOrderManagement == false, "Wrong position type for this provider.");

            executionInfo = PositionExecutionInfo.Empty;
            PassiveOrder order;
            lock (this)
            {
                order = new PassiveOrder(_manager, _dataDelivery.SourceId, provider.SourceId);
            }

            OrderInfo? infoReference;

            bool result = provider.SynchronousExecute(provider.DefaultAccount.Info, order, _info.Symbol,
                orderType, volume, slippage, price, takeProfit, stopLoss, string.Empty, out infoReference, out operationResultMessage);

            if (result && infoReference.HasValue)
            {
                OrderInfo infoAssign = infoReference.Value;
                if (infoAssign.Type == OrderTypeEnum.UNKNOWN)
                {
                    infoAssign.Type = orderType;
                }

                if (infoAssign.Volume == int.MinValue
                    || infoAssign.Volume == int.MaxValue)
                {// Volume was not retrieved by integration.
                    infoAssign.Volume = volume;
                }

                if (infoAssign.OpenPrice.HasValue)
                {
                    executionInfo = new PositionExecutionInfo(infoReference.Value.Id, _dataDelivery.SourceId, provider.SourceId, Symbol,
                        infoAssign.Type, infoAssign.OpenPrice.Value, volume, volume,
                        infoAssign.OpenTime, PositionExecutionInfo.ExecutionResultEnum.Success);
                }
                else
                {
                    SystemMonitor.Error("Received execution result, but price not assigned.");
                }

                order.AdoptInfo(infoAssign);

                provider.TradeEntities.AddOrder(order);

                return infoReference.Value.Id;
            }

            return string.Empty;
        }
Example #5
0
        /// <summary>
        /// This may contain a few operations on active orders, in order to match the rule "no opposing active orders"
        /// </summary>
        public virtual string ExecuteMarketBalanced(int volumeModification, decimal?desiredPrice, decimal?slippage, TimeSpan timeOut,
                                                    out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            executionInfo = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _provider;

            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not properly initialized.";
                return(string.Empty);
            }

            if (OnExecuteMarketBalanced(provider, volumeModification, desiredPrice, slippage, timeOut, out executionInfo, out operationResultMessage))
            {
                return(Guid.NewGuid().ToString());
            }

            return(string.Empty);
        }
Example #6
0
        /// <summary>
        ///
        /// </summary>
        public string ExecuteMarketBalancedClose(int?closeVolume, TimeSpan timeOut, out PositionExecutionInfo executionResult, out string operationResultMessage)
        {
            operationResultMessage = string.Empty;
            executionResult        = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _orderProvider;

            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not initialized.";
                return(string.Empty);
            }

            if (Volume == 0)
            {
                operationResultMessage = "Position has no open volume (amount).";
                return(string.Empty);
            }

            if (closeVolume.HasValue == false)
            {
                closeVolume = -(int)Volume;
            }
            else if (Volume > 0)
            {// Reverse of direction needed, since we make it directional.
                closeVolume = -closeVolume.Value;
            }

            if (Math.Abs(closeVolume.Value) > Math.Abs(Volume))
            {
                operationResultMessage = "Volume (amount) to close too big.";
                return(string.Empty);
            }

            return(ExecuteMarketBalanced(closeVolume.Value, null, null,
                                         timeOut, out executionResult, out operationResultMessage));
        }
        ///// <summary>
        ///// Will try to asynchronously reverse the given execution info position part.
        ///// Similar to the ExecuteMarketReverse baseMethod, only this is not synchronous.
        ///// </summary>
        //public virtual string SubmitReverse(PositionExecutionInfo orderInfo, decimal? slippage, bool manipulateExistingOrders, out string operationResultMessage)
        //{
        //    if (orderInfo.IsEmpty || orderInfo.Result != PositionExecutionInfo.ExecutionResultEnum.Success)
        //    {
        //        operationResultMessage = "Execution info not properly assigned for reversal.";
        //        return string.Empty;
        //    }
        //    OrderTypeEnum orderType = OrderTypeEnum.UNKNOWN;
        //    if (orderInfo.OrderType == OrderTypeEnum.BUY_MARKET)
        //    {
        //        orderType = OrderTypeEnum.SELL_MARKET;
        //    }
        //    else if (orderInfo.OrderType == OrderTypeEnum.SELL_MARKET)
        //    {
        //        orderType = OrderTypeEnum.BUY_MARKET;
        //    }
        //    else
        //    {
        //        operationResultMessage = "Only market position can be reversed.";
        //        SystemMonitor.OperationError(operationResultMessage);
        //        return string.Empty;
        //    }
        //    return Submit(orderType, (int)orderInfo.ExecutedVolume,
        //        null, slippage, null, null, manipulateExistingOrders, out operationResultMessage);
        //}
        ///// <summary>
        ///// Will try to synchronously execute a reverse of the given execution info.
        ///// This is a suitable replacement for a specific "order close", i.e. allowing
        ///// you to reverse a specific previous execution on this position.
        ///// </summary>
        ///// <param name="orderInfo"></param>
        ///// <param name="allowExistingActiveOrdersManipulation">Is the operation allowed to close a matching existing order, or should we always open a new one. This is suitable for Active orders brokers, that dissallow hedged orders at the same time.</param>
        ///// <returns></returns>
        //public virtual string ExecuteMarketReverse(PositionExecutionInfo orderInfo, decimal? slippage, TimeSpan timeOut, bool manipulateExistingOrders,
        //    out PositionExecutionInfo newExecutionInfo, out string operationResultMessage)
        //{
        //    newExecutionInfo = PositionExecutionInfo.Empty;
        //    if (orderInfo.IsEmpty == false && orderInfo.Result == PositionExecutionInfo.ExecutionResultEnum.Success)
        //    {
        //        OrderTypeEnum orderType = OrderTypeEnum.UNKNOWN;
        //        if (orderInfo.OrderType == OrderTypeEnum.BUY_MARKET)
        //        {
        //            orderType = OrderTypeEnum.SELL_MARKET;
        //        }
        //        else if (orderInfo.OrderType == OrderTypeEnum.SELL_MARKET)
        //        {
        //            orderType = OrderTypeEnum.BUY_MARKET;
        //        }
        //        else
        //        {
        //            operationResultMessage = "Only market position can be reversed.";
        //            SystemMonitor.OperationError(operationResultMessage);
        //            return string.Empty;
        //        }
        //        return ExecuteMarket(orderType, (int)orderInfo.ExecutedVolume, null, slippage, null, null, timeOut, out newExecutionInfo, out operationResultMessage);
        //    }
        //    else
        //    {
        //        operationResultMessage = "Can not reverse execution info with result [" + orderInfo.Result.ToString() + "], no action taken.";
        //        SystemMonitor.OperationError(operationResultMessage);
        //        return string.Empty;
        //    }
        //}
        /// <summary>
        /// 
        /// </summary>
        protected virtual bool OnExecuteMarketBalanced(ISourceOrderExecution provider, int volumeModification, decimal? desiredPrice,
            decimal? slippage, TimeSpan timeOut, out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            OrderTypeEnum orderType = OrderTypeEnum.BUY_MARKET;
            if (volumeModification < 0)
            {
                orderType = OrderTypeEnum.SELL_MARKET;
            }

            return string.IsNullOrEmpty(ExecuteMarket(orderType, Math.Abs(volumeModification), desiredPrice, slippage, null, null,
                timeOut, out executionInfo, out operationResultMessage)) == false;
        }
Example #8
0
 /// <summary>
 ///
 /// </summary>
 protected abstract string OnExecuteMarket(ISourceOrderExecution provider, OrderTypeEnum orderType, int volume,
                                           decimal?price, decimal?slippage, decimal?takeProfit, decimal?stopLoss, TimeSpan timeOut,
                                           out PositionExecutionInfo executionInfo, out string operationResultMessage);
Example #9
0
        /// <summary>
        /// Places and tries to execute a market order synchronously. Since it might be a modification of an
        /// existing active order, no specific order Id is returned - instead a bool indicating operation result.
        /// </summary>
        /// <param name="manipulateExistingOrders">[where applicable] Is the operation allowed to close a matching existing order, or should we always open a new one. This is suitable for Active orders brokers, that dissallow hedged orders at the same time.</param>
        public string ExecuteMarket(OrderTypeEnum orderType, int volume, decimal?price, decimal?slippage,
                                    decimal?takeProfit, decimal?stopLoss, TimeSpan timeOut, out PositionExecutionInfo executionInfo,
                                    out string operationResultMessage)
        {
            operationResultMessage = string.Empty;
            executionInfo          = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _orderProvider;

            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not properly initialized.";
                return(string.Empty);
            }

            // Trace pre-execution info.
            string traceMessage = string.Format("Submit Type[{0}] Volume [{1}] Price [{2}] Slippage [{3}] TP [{4}] SL [{5}] TimeOut [{6}]", orderType.ToString(),
                                                volume.ToString(), GeneralHelper.ToString(price), GeneralHelper.ToString(slippage), GeneralHelper.ToString(takeProfit),
                                                GeneralHelper.ToString(stopLoss), timeOut.ToString());

            traceMessage += GenerateConditionsInfo();

            TracerHelper.Trace(_tracer, traceMessage, TracerItem.PriorityEnum.High);

            _isProcessing = true;

            string result = OnExecuteMarket(provider, orderType, volume, price, slippage, takeProfit, stopLoss, timeOut,
                                            out executionInfo, out operationResultMessage);

            SystemMonitor.CheckError(result == executionInfo.ExecutionId, operationResultMessage);

            _isProcessing = false;

            return(result);
        }
Example #10
0
        ///// <summary>
        ///// Will try to asynchronously reverse the given execution info position part.
        ///// Similar to the ExecuteMarketReverse baseMethod, only this is not synchronous.
        ///// </summary>
        //public virtual string SubmitReverse(PositionExecutionInfo orderInfo, decimal? slippage, bool manipulateExistingOrders, out string operationResultMessage)
        //{
        //    if (orderInfo.IsEmpty || orderInfo.Result != PositionExecutionInfo.ExecutionResultEnum.Success)
        //    {
        //        operationResultMessage = "Execution info not properly assigned for reversal.";
        //        return string.Empty;
        //    }

        //    OrderTypeEnum orderType = OrderTypeEnum.UNKNOWN;
        //    if (orderInfo.OrderType == OrderTypeEnum.BUY_MARKET)
        //    {
        //        orderType = OrderTypeEnum.SELL_MARKET;
        //    }
        //    else if (orderInfo.OrderType == OrderTypeEnum.SELL_MARKET)
        //    {
        //        orderType = OrderTypeEnum.BUY_MARKET;
        //    }
        //    else
        //    {
        //        operationResultMessage = "Only market position can be reversed.";
        //        SystemMonitor.OperationError(operationResultMessage);
        //        return string.Empty;
        //    }

        //    return Submit(orderType, (int)orderInfo.ExecutedVolume,
        //        null, slippage, null, null, manipulateExistingOrders, out operationResultMessage);
        //}

        ///// <summary>
        ///// Will try to synchronously execute a reverse of the given execution info.
        ///// This is a suitable replacement for a specific "order close", i.e. allowing
        ///// you to reverse a specific previous execution on this position.
        ///// </summary>
        ///// <param name="orderInfo"></param>
        ///// <param name="allowExistingActiveOrdersManipulation">Is the operation allowed to close a matching existing order, or should we always open a new one. This is suitable for Active orders brokers, that dissallow hedged orders at the same time.</param>
        ///// <returns></returns>
        //public virtual string ExecuteMarketReverse(PositionExecutionInfo orderInfo, decimal? slippage, TimeSpan timeOut, bool manipulateExistingOrders,
        //    out PositionExecutionInfo newExecutionInfo, out string operationResultMessage)
        //{
        //    newExecutionInfo = PositionExecutionInfo.Empty;

        //    if (orderInfo.IsEmpty == false && orderInfo.Result == PositionExecutionInfo.ExecutionResultEnum.Success)
        //    {
        //        OrderTypeEnum orderType = OrderTypeEnum.UNKNOWN;
        //        if (orderInfo.OrderType == OrderTypeEnum.BUY_MARKET)
        //        {
        //            orderType = OrderTypeEnum.SELL_MARKET;
        //        }
        //        else if (orderInfo.OrderType == OrderTypeEnum.SELL_MARKET)
        //        {
        //            orderType = OrderTypeEnum.BUY_MARKET;
        //        }
        //        else
        //        {
        //            operationResultMessage = "Only market position can be reversed.";
        //            SystemMonitor.OperationError(operationResultMessage);
        //            return string.Empty;
        //        }

        //        return ExecuteMarket(orderType, (int)orderInfo.ExecutedVolume, null, slippage, null, null, timeOut, out newExecutionInfo, out operationResultMessage);
        //    }
        //    else
        //    {
        //        operationResultMessage = "Can not reverse execution info with result [" + orderInfo.Result.ToString() + "], no action taken.";
        //        SystemMonitor.OperationError(operationResultMessage);
        //        return string.Empty;
        //    }
        //}

        /// <summary>
        ///
        /// </summary>
        protected virtual bool OnExecuteMarketBalanced(ISourceOrderExecution provider, int volumeModification, decimal?desiredPrice,
                                                       decimal?slippage, TimeSpan timeOut, out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            OrderTypeEnum orderType = OrderTypeEnum.BUY_MARKET;

            if (volumeModification < 0)
            {
                orderType = OrderTypeEnum.SELL_MARKET;
            }

            return(string.IsNullOrEmpty(ExecuteMarket(orderType, Math.Abs(volumeModification), desiredPrice, slippage, null, null,
                                                      timeOut, out executionInfo, out operationResultMessage)) == false);
        }
        /// <summary>
        /// Places and tries to execute a market order synchronously. Since it might be a modification of an 
        /// existing active order, no specific order Id is returned - instead a bool indicating operation result.
        /// </summary>
        /// <param name="manipulateExistingOrders">[where applicable] Is the operation allowed to close a matching existing order, or should we always open a new one. This is suitable for Active orders brokers, that dissallow hedged orders at the same time.</param>
        public string ExecuteMarket(OrderTypeEnum orderType, int volume, decimal? price, decimal? slippage,
            decimal? takeProfit, decimal? stopLoss, TimeSpan timeOut, out PositionExecutionInfo executionInfo, 
            out string operationResultMessage)
        {
            operationResultMessage = string.Empty;
            executionInfo = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _orderProvider;
            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not properly initialized.";
                return string.Empty;
            }

            // Trace pre-execution info.
            string traceMessage = string.Format("Submit Type[{0}] Volume [{1}] Price [{2}] Slippage [{3}] TP [{4}] SL [{5}] TimeOut [{6}]", orderType.ToString(),
                volume.ToString(), GeneralHelper.ToString(price), GeneralHelper.ToString(slippage), GeneralHelper.ToString(takeProfit),
                GeneralHelper.ToString(stopLoss), timeOut.ToString());

            traceMessage += GenerateConditionsInfo();

            TracerHelper.Trace(_tracer, traceMessage, TracerItem.PriorityEnum.High);

            _isProcessing = true;

            string result = OnExecuteMarket(provider, orderType, volume, price, slippage, takeProfit, stopLoss, timeOut,
                out executionInfo, out operationResultMessage);

            SystemMonitor.CheckError(result == executionInfo.ExecutionId, operationResultMessage);

            _isProcessing = false;

            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        protected override bool OnExecuteMarketBalanced(ISourceOrderExecution provider, int volumeModification, decimal? desiredPrice, 
            decimal? slippage, TimeSpan timeOut, out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            if (_manipulateExistingOrders == false)
            {
                return base.OnExecuteMarketBalanced(provider, volumeModification, desiredPrice, slippage, timeOut, out executionInfo, out operationResultMessage);
            }

            OrderTypeEnum orderType = OrderTypeEnum.BUY_MARKET;
            if (volumeModification < 0)
            {
                orderType = OrderTypeEnum.SELL_MARKET;
                volumeModification = Math.Abs(volumeModification);
            }

            executionInfo = PositionExecutionInfo.Empty;
            int originalVolumeModification = volumeModification;

            List<KeyValuePair<double, decimal>> closePrices = new List<KeyValuePair<double, decimal>>();

            bool suitableOrdersAvailable;

            ActiveOrder orderSelected = ObtainManipulationOrder(provider, GetReverseOrderType(orderType), Math.Abs(originalVolumeModification),
                out suitableOrdersAvailable);

            if (orderSelected != null && volumeModification > 0)
            {
                if (volumeModification >= orderSelected.CurrentVolume)
                {
                    int orderVolume = orderSelected.CurrentVolume;
                    if (orderSelected.Close(slippage, null))
                    {
                        volumeModification -= orderVolume;
                        if (orderSelected.ClosePrice.HasValue)
                        {
                            closePrices.Add(new KeyValuePair<double, decimal>(orderVolume, orderSelected.ClosePrice.Value));
                        }
                        else
                        {
                            SystemMonitor.Error("Order [{" + orderSelected.Id + "}] closed but close price not assigned.");
                        }
                    }
                    else
                    {
                        ReleaseManipulationOrder(orderSelected);
                        operationResultMessage = "Failed to close corresponding reverse active order.";
                        return false;
                    }
                }
                else
                {
                    if (orderSelected.DecreaseVolume(volumeModification, slippage, null))
                    {
                        volumeModification = 0;
                    }
                }

                ReleaseManipulationOrder(orderSelected);
                orderSelected = null;
            }

            if (suitableOrdersAvailable && volumeModification > 0
                && originalVolumeModification == volumeModification)
            {// Complete failure to close anything, and there are some suitable.
                executionInfo = PositionExecutionInfo.Empty;
                operationResultMessage = "Suitable reverse market orders are available, but currently manipulated, so hedging rules forbid reverse orders placement at this moment.";
                return false;
            }

            if (volumeModification > 0)
            {// We need to execute one more in the reverse direction.
                PositionExecutionInfo marketExecutionInfo;
                string tmp;

                string executionResult = ExecuteMarket(orderType, volumeModification, null, slippage, null, null,
                    timeOut, out marketExecutionInfo, out tmp);

                if (string.IsNullOrEmpty(executionResult) == false)
                {// Success.
                    volumeModification -= (int)marketExecutionInfo.VolumeExecuted;
                    if (marketExecutionInfo.ExecutedPrice.HasValue)
                    {
                        closePrices.Add(new KeyValuePair<double, decimal>(marketExecutionInfo.VolumeExecuted, marketExecutionInfo.ExecutedPrice.Value));
                    }
                    else
                    {
                        SystemMonitor.Error("MarketExecutionInfo for a valid execution [{" + executionResult + "}] does not have ExecutedPrice assigned.");
                    }
                }
                else
                {
                    operationResultMessage = tmp;
                    return false;
                }
            }

            // Calculate the close price, combination from the operations.
            decimal closePrice = 0;
            double totalVolume = 0;

            if (FinancialHelper.CalculateAveragePrice(closePrices, out closePrice, out totalVolume) == false)
            {
                SystemMonitor.Error("Failed to calculate average price for market balanced execution.");
                closePrice = 0;
            }

            if (volumeModification > 0)
            {// Failure.
                if (originalVolumeModification == volumeModification)
                {// Complete failure.
                    executionInfo = PositionExecutionInfo.Empty;
                    operationResultMessage = "Failed to execute market operation.";
                    return false;
                }
                else
                {// Partial execution success.
                    executionInfo = new PositionExecutionInfo(Guid.NewGuid().ToString(), _dataDelivery.SourceId, provider.SourceId, Symbol, orderType,
                        closePrice, originalVolumeModification, originalVolumeModification - volumeModification, DateTime.Now, PositionExecutionInfo.ExecutionResultEnum.PartialSuccess);
                }
            }
            else
            {// Success.
                executionInfo = new PositionExecutionInfo(Guid.NewGuid().ToString(), _dataDelivery.SourceId, provider.SourceId, Symbol, orderType,
                    closePrice, originalVolumeModification, originalVolumeModification, DateTime.Now, PositionExecutionInfo.ExecutionResultEnum.Success);
            }

            operationResultMessage = string.Empty;
            return true;
        }
        /// <summary>
        /// This may contain a few operations on active orders, in order to match the rule "no opposing active orders"
        /// </summary>
        public virtual string ExecuteMarketBalanced(int volumeModification, decimal? desiredPrice, decimal? slippage, TimeSpan timeOut, 
            out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            executionInfo = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _orderProvider;
            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not properly initialized.";
                return string.Empty;
            }

            // Trace pre-execution info.
            string traceMessage = string.Format("Submit Volume Modification [{0}] Price [{1}] Slippage [{2}] TimeOut [{3}]",
                volumeModification.ToString(), GeneralHelper.ToString(desiredPrice), GeneralHelper.ToString(slippage), timeOut.ToString());

            traceMessage += GenerateConditionsInfo();

            TracerHelper.Trace(_tracer, traceMessage, TracerItem.PriorityEnum.High);

            if (OnExecuteMarketBalanced(provider, volumeModification, desiredPrice, slippage, timeOut, out executionInfo, out operationResultMessage))
            {
                return Guid.NewGuid().ToString();
            }

            return string.Empty;
        }
        /// <summary>
        ///
        /// </summary>
        protected override string OnExecuteMarket(ISourceOrderExecution provider, OrderTypeEnum orderType, int volume,
                                                  decimal?price, decimal?slippage, decimal?takeProfit, decimal?stopLoss, TimeSpan timeOut,
                                                  out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            SystemMonitor.CheckError(provider.SupportsActiveOrderManagement, "Wrong position type for this provider.");

            executionInfo = PositionExecutionInfo.Empty;

            IQuoteProvider quoteProvider = _manager.ObtainQuoteProvider(_dataDelivery.SourceId, Symbol);

            if (quoteProvider == null)
            {
                operationResultMessage = "Failed to establish quote provider for [" + _dataDelivery.SourceId.Name + ", " + Symbol.Name + "].";
                SystemMonitor.Error(operationResultMessage);
                return(string.Empty);
            }

            price = ProcessPrice(quoteProvider, orderType, price);

            // New order shall be created.
            ActiveOrder order = new ActiveOrder(_manager, provider, quoteProvider, _dataDelivery.SourceId, Symbol, true);

            OrderInfo?infoReference;

            // Using the extended operationTimeOut to 40 seconds.
            bool result = provider.SynchronousExecute(provider.DefaultAccount.Info, order, _info.Symbol,
                                                      orderType, volume, slippage, price, takeProfit, stopLoss, string.Empty, TimeSpan.FromSeconds(40), out infoReference, out operationResultMessage);

            if (result && infoReference.HasValue)
            {
                OrderInfo infoAssign = infoReference.Value;
                if (infoAssign.Type == OrderTypeEnum.UNKNOWN)
                {
                    infoAssign.Type = orderType;
                }

                if (infoAssign.Volume == int.MinValue ||
                    infoAssign.Volume == int.MaxValue)
                {// Volume was not retrieved by integration.
                    infoAssign.Volume = volume;
                }

                if (infoAssign.OpenPrice.HasValue)
                {
                    executionInfo = new PositionExecutionInfo(infoReference.Value.Id, _dataDelivery.SourceId, provider.SourceId, Symbol,
                                                              infoAssign.Type, infoAssign.OpenPrice.Value, volume, volume,
                                                              infoAssign.OpenTime, PositionExecutionInfo.ExecutionResultEnum.Success);
                }
                else
                {
                    SystemMonitor.Error("Received execution result, but price not assigned.");
                }

                order.AdoptInfo(infoAssign);

                provider.TradeEntities.AddOrder(order);
                return(infoReference.Value.Id);
            }

            return(string.Empty);
        }
        /// <summary>
        ///
        /// </summary>
        protected override bool OnExecuteMarketBalanced(ISourceOrderExecution provider, int volumeModification, decimal?desiredPrice,
                                                        decimal?slippage, TimeSpan timeOut, out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            if (_manipulateExistingOrders == false)
            {
                return(base.OnExecuteMarketBalanced(provider, volumeModification, desiredPrice, slippage, timeOut, out executionInfo, out operationResultMessage));
            }

            OrderTypeEnum orderType = OrderTypeEnum.BUY_MARKET;

            if (volumeModification < 0)
            {
                orderType          = OrderTypeEnum.SELL_MARKET;
                volumeModification = Math.Abs(volumeModification);
            }

            executionInfo = PositionExecutionInfo.Empty;
            int originalVolumeModification = volumeModification;

            List <KeyValuePair <double, decimal> > closePrices = new List <KeyValuePair <double, decimal> >();

            bool suitableOrdersAvailable;

            ActiveOrder orderSelected = ObtainManipulationOrder(provider, GetReverseOrderType(orderType), Math.Abs(originalVolumeModification),
                                                                out suitableOrdersAvailable);

            if (orderSelected != null && volumeModification > 0)
            {
                if (volumeModification >= orderSelected.CurrentVolume)
                {
                    int orderVolume = orderSelected.CurrentVolume;
                    if (orderSelected.Close(slippage, null))
                    {
                        volumeModification -= orderVolume;
                        if (orderSelected.ClosePrice.HasValue)
                        {
                            closePrices.Add(new KeyValuePair <double, decimal>(orderVolume, orderSelected.ClosePrice.Value));
                        }
                        else
                        {
                            SystemMonitor.Error("Order [{" + orderSelected.Id + "}] closed but close price not assigned.");
                        }
                    }
                    else
                    {
                        ReleaseManipulationOrder(orderSelected);
                        operationResultMessage = "Failed to close corresponding reverse active order.";
                        return(false);
                    }
                }
                else
                {
                    if (orderSelected.DecreaseVolume(volumeModification, slippage, null))
                    {
                        volumeModification = 0;
                    }
                }

                ReleaseManipulationOrder(orderSelected);
                orderSelected = null;
            }

            if (suitableOrdersAvailable && volumeModification > 0 &&
                originalVolumeModification == volumeModification)
            {// Complete failure to close anything, and there are some suitable.
                executionInfo          = PositionExecutionInfo.Empty;
                operationResultMessage = "Suitable reverse market orders are available, but currently manipulated, so hedging rules forbid reverse orders placement at this moment.";
                return(false);
            }

            if (volumeModification > 0)
            {// We need to execute one more in the reverse direction.
                PositionExecutionInfo marketExecutionInfo;
                string tmp;

                string executionResult = ExecuteMarket(orderType, volumeModification, null, slippage, null, null,
                                                       timeOut, out marketExecutionInfo, out tmp);

                if (string.IsNullOrEmpty(executionResult) == false)
                {// Success.
                    volumeModification -= (int)marketExecutionInfo.VolumeExecuted;
                    if (marketExecutionInfo.ExecutedPrice.HasValue)
                    {
                        closePrices.Add(new KeyValuePair <double, decimal>(marketExecutionInfo.VolumeExecuted, marketExecutionInfo.ExecutedPrice.Value));
                    }
                    else
                    {
                        SystemMonitor.Error("MarketExecutionInfo for a valid execution [{" + executionResult + "}] does not have ExecutedPrice assigned.");
                    }
                }
                else
                {
                    operationResultMessage = tmp;
                    return(false);
                }
            }

            // Calculate the close price, combination from the operations.
            decimal closePrice  = 0;
            double  totalVolume = 0;

            if (FinancialHelper.CalculateAveragePrice(closePrices, out closePrice, out totalVolume) == false)
            {
                SystemMonitor.Error("Failed to calculate average price for market balanced execution.");
                closePrice = 0;
            }

            if (volumeModification > 0)
            {     // Failure.
                if (originalVolumeModification == volumeModification)
                { // Complete failure.
                    executionInfo          = PositionExecutionInfo.Empty;
                    operationResultMessage = "Failed to execute market operation.";
                    return(false);
                }
                else
                {// Partial execution success.
                    executionInfo = new PositionExecutionInfo(Guid.NewGuid().ToString(), _dataDelivery.SourceId, provider.SourceId, Symbol, orderType,
                                                              closePrice, originalVolumeModification, originalVolumeModification - volumeModification, DateTime.Now, PositionExecutionInfo.ExecutionResultEnum.PartialSuccess);
                }
            }
            else
            {// Success.
                executionInfo = new PositionExecutionInfo(Guid.NewGuid().ToString(), _dataDelivery.SourceId, provider.SourceId, Symbol, orderType,
                                                          closePrice, originalVolumeModification, originalVolumeModification, DateTime.Now, PositionExecutionInfo.ExecutionResultEnum.Success);
            }

            operationResultMessage = string.Empty;
            return(true);
        }
Example #16
0
        /// <summary>
        /// Places and tries to execute a market order synchronously. Since it might be a modification of an
        /// existing active order, no specific order Id is returned - instead a bool indicating operation result.
        /// </summary>
        /// <param name="manipulateExistingOrders">[where applicable] Is the operation allowed to close a matching existing order, or should we always open a new one. This is suitable for Active orders brokers, that dissallow hedged orders at the same time.</param>
        public string ExecuteMarket(OrderTypeEnum orderType, int volume, decimal?price, decimal?slippage,
                                    decimal?takeProfit, decimal?stopLoss, TimeSpan timeOut, out PositionExecutionInfo executionInfo,
                                    out string operationResultMessage)
        {
            //TracerHelper.TraceEntry();

            operationResultMessage = string.Empty;
            executionInfo          = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _provider;

            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not properly initialized.";
                return(string.Empty);
            }

            _isProcessing = true;

            string result = OnExecuteMarket(provider, orderType, volume, price, slippage, takeProfit, stopLoss, timeOut,
                                            out executionInfo, out operationResultMessage);

            SystemMonitor.CheckError(result == executionInfo.ExecutionId, operationResultMessage);

            _isProcessing = false;

            return(result);
        }
 /// <summary>
 /// 
 /// </summary>
 protected abstract string OnExecuteMarket(ISourceOrderExecution provider, OrderTypeEnum orderType, int volume, 
     decimal? price, decimal? slippage, decimal? takeProfit, decimal? stopLoss, TimeSpan timeOut,
     out PositionExecutionInfo executionInfo, out string operationResultMessage);
        /// <summary>
        /// This may contain a few operations on active orders, in order to match the rule "no opposing active orders"
        /// </summary>
        public virtual string ExecuteMarketBalanced(int volumeModification, decimal? desiredPrice, decimal? slippage, TimeSpan timeOut, 
            out PositionExecutionInfo executionInfo, out string operationResultMessage)
        {
            executionInfo = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _provider;
            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not properly initialized.";
                return string.Empty;
            }

            if (OnExecuteMarketBalanced(provider, volumeModification, desiredPrice, slippage, timeOut, out executionInfo, out operationResultMessage))
            {
                return Guid.NewGuid().ToString();
            }

            return string.Empty;
        }
        /// <summary>
        /// Places and tries to execute a market order synchronously. Since it might be a modification of an 
        /// existing active order, no specific order Id is returned - instead a bool indicating operation result.
        /// </summary>
        /// <param name="manipulateExistingOrders">[where applicable] Is the operation allowed to close a matching existing order, or should we always open a new one. This is suitable for Active orders brokers, that dissallow hedged orders at the same time.</param>
        public string ExecuteMarket(OrderTypeEnum orderType, int volume, decimal? price, decimal? slippage,
            decimal? takeProfit, decimal? stopLoss, TimeSpan timeOut, out PositionExecutionInfo executionInfo, 
            out string operationResultMessage)
        {
            //TracerHelper.TraceEntry();

            operationResultMessage = string.Empty;
            executionInfo = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _provider;
            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not properly initialized.";
                return string.Empty;
            }

            _isProcessing = true;

            string result = OnExecuteMarket(provider, orderType, volume, price, slippage, takeProfit, stopLoss, timeOut,
                out executionInfo, out operationResultMessage);

            SystemMonitor.CheckError(result == executionInfo.ExecutionId, operationResultMessage);

            _isProcessing = false;

            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        public string ExecuteMarketBalancedClose(int? closeVolume, TimeSpan timeOut, out PositionExecutionInfo executionResult, out string operationResultMessage)
        {
            operationResultMessage = string.Empty;
            executionResult = PositionExecutionInfo.Empty;

            ISourceOrderExecution provider = _orderProvider;
            if (provider == null || provider.DefaultAccount == null)
            {
                operationResultMessage = "Position not initialized.";
                return string.Empty;
            }

            if (Volume == 0)
            {
                operationResultMessage = "Position has no open volume (amount).";
                return string.Empty;
            }

            if (closeVolume.HasValue == false)
            {
                closeVolume = -(int)Volume;
            }
            else if (Volume > 0)
            {// Reverse of direction needed, since we make it directional.
                closeVolume = -closeVolume.Value;
            }

            if (Math.Abs(closeVolume.Value) > Math.Abs(Volume))
            {
                operationResultMessage = "Volume (amount) to close too big.";
                return string.Empty;
            }

            return ExecuteMarketBalanced(closeVolume.Value, null, null,
                timeOut, out executionResult, out operationResultMessage);
        }