예제 #1
0
파일: OrderP2.cs 프로젝트: kiquenet/B4F
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual OrderValidationResult Validate()
        {
            // Buy  -> Check Cash (Buying Power)
            // Sell -> Check the Positions

            string message = "";
            OrderValidationResult retVal = new OrderValidationResult(OrderValidationSubType.Success, "");

            //Check if an instruction exist - Invalid_InstructionExists
            retVal = checkInstructionExists();
            if (retVal.Type != OrderValidationSubType.Success)
                return retVal;

            if (Side == Side.Buy)
            {
                if (!Account.AccountOwner.IsStichting)
                {
                    // check the Cash -> Buying Power check
                    // BP = All Cash (incl cash management fund) - Open Orders - Open Trades (Not Approved)
                    Money currentOrderAmount;
                    Money totalCashAmount;
                    string oldPriceWarning = "";

                    if (!IsMonetary && ((ISecurityOrder)this).TradedInstrument.SecCategory.Key == SecCategories.CashManagementFund)
                        totalCashAmount = Account.TotalPositionAmount(PositionAmountReturnValue.Cash);
                    else
                        totalCashAmount = Account.TotalPositionAmount(PositionAmountReturnValue.BothCash);

                    if (totalCashAmount == null || totalCashAmount.IsZero)
                    {
                        message = string.Format("This order ({0}) can not be entered since there is no cash.", Value.ToString());
                        return new OrderValidationResult(OrderValidationSubType.Invalid_NoCash, message);
                    }

                    if (IsSizeBased)
                    {
                        // if closure -> check not another buy order already exists.
                        OrderValidationResult buyCloseCheck = checkBuyCloseOrders();
                        if (buyCloseCheck.Type != OrderValidationSubType.Success)
                            return buyCloseCheck;

                        // Get the Price of the Instrument
                        IPriceDetail priceDetail = RequestedInstrument.CurrentPrice;

                        if (priceDetail == null)
                        {
                            message = string.Format("The order validation is not very accurate since no current price is available for {0}.", Value.Underlying.Name);
                            return new OrderValidationResult(OrderValidationSubType.Warning_NoCurrentPrice, message);
                        }
                        else
                        {
                            Money accruedInterest = ((ISecurityOrder)this).AccruedInterest;
                            currentOrderAmount = ((Money)(Value.CalculateAmount(priceDetail.Price) + Commission + accruedInterest)).CurrentBaseAmount;
                            if (priceDetail.IsOldDate)
                            {
                                oldPriceWarning = string.Format("The order validation is not very accurate since the last available price ({0}) is from {1}.", priceDetail.Price.ToString(), priceDetail.Date.ToShortDateString());
                            }
                        }
                    }
                    else
                    {
                        currentOrderAmount = GrossAmountBase;

                        //// Check when Foreign currency amount -> if foreign currency is available
                        if (!Value.Underlying.ToCurrency.IsBase)
                        {
                            ICashPosition posFx = Account.Portfolio.PortfolioCashGL.GetPosition(Value.Underlying.ToCurrency);
                            Money orderAmtFx = Account.OpenOrdersForAccount.TotalAmountInSpecifiedNominalCurrency((ICurrency)Value.Underlying);
                            if (posFx == null)
                            {
                                message = string.Format("This order ({0}) can not be placed since the account doesn't have a {1} position.", GrossAmount.DisplayString, Value.Underlying.Name);
                                retVal = new OrderValidationResult(OrderValidationSubType.Invalid_NoCash, message);
                            }
                            else if (!((Money)(posFx.SettledSize - orderAmtFx - GrossAmount)).Sign)
                            {
                                string messageOpenOrders = "";
                                if (orderAmtFx != null && orderAmtFx.IsNotZero)
                                    messageOpenOrders = string.Format(" minus the open order amount ({0}) in {1}", orderAmtFx.ToString(), Value.Underlying.Name);
                                message = string.Format("This order ({0}) exceeds the current {1} cash amount ({2}){3}.", GrossAmount.DisplayString, Value.Underlying.Name, posFx.SettledSize.ToString(), messageOpenOrders);
                                retVal = new OrderValidationResult(OrderValidationSubType.Invalid_NotEnoughCash, message);
                            }
                            if (retVal.Type != OrderValidationSubType.Success)
                            {
                                retVal.Message += Environment.NewLine + string.Format("Place a {0} order instead.", Account.AccountOwner.StichtingDetails.BaseCurrency.ToString());
                                return retVal;
                            }
                        }
                    }

                    // Consider both Buy & Sell orders
                    Money openOrderAmount = Account.OpenOrderAmount(OpenOrderAmountReturnValue.Gross);
                    if (!((Money)(totalCashAmount - openOrderAmount - currentOrderAmount)).Sign)
                    {
                        if (openOrderAmount != null && openOrderAmount.IsNotZero)
                            message = string.Format(" minus the open order amount ({0})", openOrderAmount.DisplayString);
                        message = string.Format("This order ({0}) exceeds the total cash amount ({1}){2}.", currentOrderAmount.DisplayString, totalCashAmount.DisplayString, message);
                        retVal = new OrderValidationResult(OrderValidationSubType.Invalid_NotEnoughCash, message);
                    }

                    retVal.Message += oldPriceWarning;
                    if (oldPriceWarning != string.Empty && retVal.Type == OrderValidationSubType.Success)
                    {
                        retVal.Type = OrderValidationSubType.Warning_OldPrice;
                    }
                }
            }
            else
            {
                // Get the current Position size
                InstrumentSize positionSize = null;
                IFundPosition position = Account.Portfolio.PortfolioInstrument.GetPosition((ITradeableInstrument) RequestedInstrument);
                if (position != null)
                    positionSize = position.Size;

                if (positionSize == null || positionSize.IsZero)
                {
                    message = string.Format("You tried to sell {0} but there are no positions found.", RequestedInstrument.Name);
                    return new OrderValidationResult(OrderValidationSubType.Invalid_NoPosition, message);
                }

                // Get the positions size of the order
                PredictedSize predSize;
                if (!IsSizeBased)
                {
                    // Amount based -> Get the Price/ExRate
                    predSize = RequestedInstrument.PredictSize(Amount);

                    // If there is no Price/ExRate found -> warning
                    if (predSize.Status == PredictedSizeReturnValue.NoRate)
                    {
                        message = string.Format("The order validation is not very accurate since no current {0} is available for {1}.", (RequestedInstrument.IsCash ? "exchangerate" : "price"), Value.Underlying.Name);
                        return new OrderValidationResult(OrderValidationSubType.Warning_NoCurrentPrice, message);
                    }
                }
                else
                {
                    predSize = new PredictedSize(Value, DateTime.Now);
                }

                // Get the open order size
                InstrumentSize openOrderSize = null;
                if (Account.OpenOrdersForAccount != null && Account.OpenOrdersForAccount.Count > 0)
                    openOrderSize = Account.OpenOrdersForAccount.TotalSize(RequestedInstrument);

                if (!((InstrumentSize)(positionSize + (predSize.Size + openOrderSize))).Sign)
                {
                    message = string.Format("You tried to sell {0} {1} but in the portfolio only {2} positions were found", predSize.Size.Abs().ToString(), RequestedInstrument.Name, positionSize.ToString());
                    if (openOrderSize != null && openOrderSize.IsNotZero)
                        message += Environment.NewLine + string.Format(" and order(s) existed for {0}.", openOrderSize.ToString());
                    else
                        message += ".";
                    retVal = new OrderValidationResult(OrderValidationSubType.Invalid_NotEnoughPosition, message);
                }

                if (predSize.Status == PredictedSizeReturnValue.OldRateDate)
                {
                    retVal.Message += (retVal.Message == string.Empty ? "" : Environment.NewLine) + string.Format("The order validation is not very accurate since the last available {0} ({1}) is from {2}.", (RequestedInstrument.IsCash ? "exchangerate" : "price"), predSize.Rate, predSize.RateDate.ToShortDateString());
                    if (retVal.Type == OrderValidationSubType.Success)
                    {
                        retVal.Type = OrderValidationSubType.Warning_OldPrice;
                    }
                }
            }

            // Check opposite orders
            OrderValidationResult sideCheck = checkSideOrders();
            if (sideCheck.Type != OrderValidationSubType.Success)
            {
                retVal.Message += (retVal.Message == string.Empty ? "" : Environment.NewLine) + sideCheck.Message;
                if (retVal.Type == OrderValidationSubType.Success)
                {
                    retVal.Type = sideCheck.Type;
                }
            }

            return retVal;
        }
예제 #2
0
        /// <summary>
        /// Get the educated guess of the size of a instrument for a amount of money
        /// </summary>
        /// <param name="inputAmount"></param>
        /// <returns></returns>
        public override PredictedSize PredictSize(Money inputAmount)
        {
            PredictedSize retVal = new PredictedSize(PredictedSizeReturnValue.NoRate);
            Money amount;

            if (CurrentPrice != null)
            {
                retVal.RateDate = CurrentPrice.Date;
                if (inputAmount.Underlying.Equals(CurrentPrice.Price.Underlying))
                    retVal.Size = inputAmount.CalculateSize(CurrentPrice.Price);
                else
                {
                    amount = inputAmount.Convert(CurrentPrice.Price.Underlying);
                    retVal.Size = amount.CalculateSize(CurrentPrice.Price);
                }
                retVal.Rate = currentPrice.Price.ToString();
            }
            return retVal;
        }
예제 #3
0
파일: BenchMark.cs 프로젝트: kiquenet/B4F
 public override PredictedSize PredictSize(Money inputAmount)
 {
     PredictedSize retVal = new PredictedSize(PredictedSizeReturnValue.NoRate);
      return retVal;
 }