예제 #1
0
파일: OrderP4.cs 프로젝트: kiquenet/B4F
        public static void CheckMaximalRoundOffError(bool isSizeBased, InstrumentSize size, Money amount, Price price, Money accruedInterest, Side side)
        {
            if (!isSizeBased)
            {
                InstrumentSize calcAmt = size.CalculateAmount(price) * (decimal)side * -1M;
                //if (accruedInterest != null && accruedInterest.IsNotZero)
                //{
                //    accruedInterest = accruedInterest.Abs() * (decimal)side * -1M;
                //    calcAmt += accruedInterest;
                //}

                InstrumentSize diff = (calcAmt.Abs() - amount.Abs());
                if (diff.IsNotZero && !diff.IsWithinTolerance(0.02m))
                {
                    decimal percLeft = diff.Abs().Quantity / amount.Abs().Quantity;
                    if (percLeft >= 0.05m)
                        throw new ApplicationException(string.Format(
                            "Price times Size ({0}) differs by {1}% from the provided Amount ({2}). Order cannot be filled.",
                            calcAmt.DisplayString, Math.Round(percLeft * 100m, 1), amount.DisplayString));
                }
            }
        }
예제 #2
0
        protected virtual TransactionFillDetails getTransactionFillDetailsAmountBasedOrderByGoalSeek(
            Money grossAmount, Side side, bool isCommissionRelevant, bool isValueInclComm,
            DateTime settlementDate, Price price, IExchange exchange,
            ICommRule rule, ICommClient client, decimal servChargePerc, int precision)
        {
            decimal realAmount;
            decimal guess = grossAmount.Abs().CalculateSize(price).Quantity;
            FinancialMath.MaxCycles = 200;

            // Check -> use Commission
            bool useComm = true;
            bool useAddComm = false;
            if (!isCommissionRelevant || rule == null)
                useComm = false;

            if (useComm)
                useAddComm = (rule.AdditionalCalculation != null);

            realAmount = FinancialMath.GoalSeek(x =>
                new InstrumentSize(x, this).CalculateAmount(price).Quantity +
                (useComm ? rule.CommCalculation.Calculate(client.GetNewInstance(new InstrumentSize(x, this), price, (useAddComm ? rule.AdditionalCalculation.Calculate(client.GetNewInstance(new InstrumentSize(x, this), price)) : null))).Quantity : 0M) +
                (useAddComm ? rule.AdditionalCalculation.Calculate(client.GetNewInstance(new InstrumentSize(x, this), price)).Quantity : 0M) +
                (new InstrumentSize(x, this).CalculateAmount(price).Abs().Quantity * servChargePerc),
                grossAmount.Abs().Quantity, guess, precision);

            InstrumentSize size = new InstrumentSize(realAmount, this);
            Money amount = size.CalculateAmount(price);
            InstrumentSize cleanSize = amount.CalculateSize(price);

            Money servCh = (amount.Abs() * servChargePerc);
            Money comm = amount.ZeroedAmount();
            Money addComm = amount.ZeroedAmount();
            if (useComm)
            {
                if (rule.AdditionalCalculation != null)
                    addComm = rule.AdditionalCalculation.Calculate(client.GetNewInstance(cleanSize, price));
                comm = rule.CommCalculation.Calculate(client.GetNewInstance(cleanSize, price, addComm));

                // if sell -> comm is already in the amount
                if (side == Side.Sell && (comm + addComm) != null && (comm + addComm).IsNotZero)
                {
                    amount += (comm + addComm);
                    cleanSize = amount.CalculateSize(price);
                    if (!isValueInclComm)
                    {
                        if (rule.AdditionalCalculation != null)
                            addComm = rule.AdditionalCalculation.Calculate(client.GetNewInstance(cleanSize, price));
                        comm = rule.CommCalculation.Calculate(client.GetNewInstance(cleanSize, price, addComm));
                    }
                }
            }
            return new TransactionFillDetails(cleanSize, amount, null, servCh, servChargePerc, comm + addComm, grossAmount.Abs(), side);
        }
예제 #3
0
파일: Price.cs 프로젝트: kiquenet/B4F
 /// <summary>
 /// Calculate the amount using a size
 /// </summary>
 /// <param name="size"></param>
 /// <returns></returns>
 public Money CalculateAmount(InstrumentSize size)
 {
     return size.CalculateAmount(this, false);
 }
예제 #4
0
파일: Price.cs 프로젝트: kiquenet/B4F
        /// <summary>
        /// This method gives back the weighted average of two size & price pairs
        /// </summary>
        /// <param name="price1">The first instance of the <see cref="T:B4F.TotalGiro.Instruments.Price">Price</see> class</param>
        /// <param name="size1">The first instance of the <see cref="T:B4F.TotalGiro.Instruments.InstrumentSize">InstrumentSize</see> class</param>
        /// <param name="price2">The second instance of the <see cref="T:B4F.TotalGiro.Instruments.Price">Price</see> class</param>
        /// <param name="size2">The second instance of the <see cref="T:B4F.TotalGiro.Instruments.InstrumentSize">InstrumentSize</see> class</param>
        /// <returns>A new instance of the <see cref="T:B4F.TotalGiro.Instruments.Price">Price</see> class with the weighted price</returns>
        public static Price GetAveragePrice(Price price1, InstrumentSize size1, Price price2, InstrumentSize size2)
        {
            if (price1 == null && size1 == null && price2 == null && size2 == null)
            {
                return null;
            }

            if (price1 == null || size1 == null)
            {
                return price2;
            }
            if (price2 == null || size2 == null)
            {
                return price1;
            }

            if (price1.Underlying != price2.Underlying)
            {
                throw new ApplicationException("Both prices have to be in the same currency");
            }

            if (price1.Instrument != price2.Instrument)
            {
                throw new ApplicationException("Both prices have to be for the same Instrument");
            }

            if (size1.Underlying != size2.Underlying)
            {
                throw new ApplicationException("Both amounts/sizes have to be in the same instrument");
            }

            if (price1.Instrument != size1.Underlying)
            {
                throw new ApplicationException("The price and the size have to be for the same Instrument");
            }

            Money total = size1.CalculateAmount(price1) + size2.CalculateAmount(price2);
            return total / (size1 + size2);
        }
예제 #5
0
        public static void PriceChanged(OrderFillView orderFillView)
        {
            IDalSession session = NHSessionFactory.CreateSession();

            try
            {
                Price price;
                InstrumentSize size;
                Money amount;
                ITradeableInstrument tradedInstrument;

                IOrder order = OrderMapper.GetOrder(session, orderFillView.OrderId);

                if (!orderFillView.IsSizeBased)
                {
                    // Exchange rate (in base currency)
                    tradedInstrument = ((IOrderAmountBased)order).TradedInstrument;
                    price = new Price(orderFillView.Price, tradedInstrument.CurrencyNominal, tradedInstrument);
                    amount = new Money(orderFillView.Amount, (ICurrency)order.Value.Underlying);
                    if (tradedInstrument.CurrencyNominal.Key != amount.Underlying.Key)
                    {
                        if (!(tradedInstrument.CurrencyNominal.IsObsoleteCurrency && tradedInstrument.CurrencyNominal.ParentInstrument.Key == amount.Underlying.Key))
                            throw new ApplicationException("It is not possible to fill an order in a different currency.");
                    }
                    size = amount.CalculateSize(price);
                    orderFillView.Size = size.Quantity;
                }
                else
                {
                    tradedInstrument = ((IOrderSizeBased)order).TradedInstrument;
                    price = new Price(orderFillView.Price, tradedInstrument.CurrencyNominal, tradedInstrument);
                    size = new InstrumentSize(orderFillView.Size, tradedInstrument);
                    amount = size.CalculateAmount(price);
                    amount.XRate = orderFillView.ExchangeRate;
                    orderFillView.Amount = amount.Quantity;
                }

                // Check if the Price is still reliable
                IPriceDetail lastValidHistoricalPrice = HistoricalPriceMapper.GetLastValidHistoricalPrice(
                                                                                    session, tradedInstrument, orderFillView.TransactionDate);
                if (lastValidHistoricalPrice == null || lastValidHistoricalPrice.Price.IsZero)
                    orderFillView.Warning = string.Format("No price was found for {0:d}, so validation is not very reliable.",
                                                             orderFillView.TransactionDate);
                else
                {
                    // check if the price is within 1% of the last historical price
                    decimal rate = lastValidHistoricalPrice.Price.Quantity;

                    decimal diff = (price.Quantity - rate) / rate;
                    decimal diffPct = Math.Round(Math.Abs(diff), 4) * 100;
                    if (diffPct > 1)
                        orderFillView.Warning = string.Format("The price entered is {0:0.##}% {1} than the last known price for {2:d} ({3}).",
                                                              diffPct, (diff < 0 ? "lower" : "higher"), orderFillView.TransactionDate,
                                                              lastValidHistoricalPrice.Price.ShortDisplayString);

                    if (lastValidHistoricalPrice.WasOldDateBy(orderFillView.TransactionDate))
                        orderFillView.Warning += (orderFillView.Warning != string.Empty ? "\n" : "") +
                            string.Format("The last known price for {0:d} is {1} days old (last updated on {2:d}), so validation is not very reliable.",
                                          orderFillView.TransactionDate, (orderFillView.TransactionDate - lastValidHistoricalPrice.Date).Days,
                                          lastValidHistoricalPrice.Date);
                }
            }
            finally
            {
                session.Close();
            }
        }
예제 #6
0
파일: CommClient.cs 프로젝트: kiquenet/B4F
 public ICommClient GetNewInstance(InstrumentSize size, Price price, Money previousCalculatedFee)
 {
     this.Value = size;
     this.Price = price;
     this.PreviousCalculatedFee = previousCalculatedFee;
     this.GrossAmount = size.CalculateAmount(price);
     this.amountIsNett = true;
     return this;
 }
예제 #7
0
        protected void calculateBookStuff(IFundPositionTx posTx, IsOpenClose isOpen, InstrumentSize newSize, Money realisedAmount, Money baseRealisedAmount)
        {
            // Book Value & AvgOpenExRate
            if (isOpen == IsOpenClose.Close)
            {
                if (!posTx.DoNotRealize)
                {
                    Money oldBookValue = BookValue;
                    Money oldBookValueIC = BookValueIC;

                    if (Size.IsNotZero && newSize.IsNotZero)
                    {
                        BookValueIC = Money.Add(Money.Add(BookValueIC, posTx.BookValueIC, true), realisedAmount, true);
                        if (newSize.IsZero && BookValueIC.IsNotZero) BookValueIC = BookValueIC.ZeroedAmount();

                        //BookValue = Money.Add(Money.Add(BookValue, posTx.BookValue, true), baseRealisedAmount, true);
                        BookValue = Money.Add(BookValue, posTx.Size.CalculateAmount(this.BookPrice), true);
                        if (newSize.IsZero && BookValue.IsNotZero) BookValue = BookValue.ZeroedAmount();
                    }
                    else
                    {
                        BookValueIC = BookValueIC.Clone(0M);
                        BookValue = BookValue.Clone(0M);
                    }

                    BookChange = Money.Add(BookChange, Money.Subtract(BookValue, oldBookValue, true), true);
                    BookChangeIC = Money.Add(BookChangeIC, Money.Subtract(BookValueIC, oldBookValueIC, true), true);
                }
                else
                {
                    BookChange = BookValue.Clone(0M);
                    BookChangeIC = BookValueIC.Clone(0M);
                }
            }
            else if (isOpen == IsOpenClose.Open)
            {
                Money bookChange = posTx.BookValue;
                BookChange = Money.Add(BookChange, bookChange, true);
                BookValue = Money.Add(BookValue, bookChange, true);

                Money bookChangeIC = posTx.BookValueIC;
                BookChangeIC = Money.Add(BookChangeIC, bookChangeIC, true);
                BookValueIC = Money.Add(BookValueIC, bookChangeIC, true);

                if (newSize.IsNotZero)
                {
                    BookPrice = Money.Divide(BookValue, newSize, true);
                    if (Size != null)
                    {
                        // for a conversion the avg ExRate does not change
                        if (!posTx.IsConversion)
                        {
                            if (!InstrumentCurrency.IsBase)
                            {
                                Money currentCostAmount = Size.CalculateAmount(CostPrice, true);
                                Money totalAmtIC = Money.Add(currentCostAmount, posTx.BookValueIC, true);
                                //Money totalAmt = Money.Add(Money.Convert(Money.Multiply(Size, CostPrice, true), (1M / AvgOpenExRate), InstrumentCurrency.BaseCurrency, true), posTx.BookValue, true);
                                Money totalAmt = Money.Add(currentCostAmount.ConvertToBase((1M / AvgOpenExRate), true), posTx.BookValue, true);

                                AvgOpenExRate = totalAmtIC.Quantity / totalAmt.Quantity;
                            }
                            else
                                AvgOpenExRate = 1M;
                        }
                    }
                    else
                        AvgOpenExRate = posTx.ExchangeRate;
                }
            }
            else //  IsOpenClose.Both
            {
                // if swap -> take the price from the Tx
                if (posTx.Price.Underlying.IsBase)
                    BookPrice = posTx.Price;
                else
                    BookPrice = posTx.Price.Convert((1 / posTx.ExchangeRate), posTx.Price.Underlying.BaseCurrency);

                // In Instrument currency
                Money bookChange = newSize.CalculateAmount(posTx.Price, true);
                BookChangeIC = bookChange;
                BookValueIC = bookChange;

                // Convert to Base Currency
                if (!((ICurrency)bookChange.Underlying).IsBase)
                    bookChange = bookChange.Convert(1 / posTx.ExchangeRate, ((ICurrency)bookChange.Underlying).BaseCurrency, 7);
                BookChange = bookChange;
                BookValue = bookChange;
                AvgOpenExRate = Math.Round(posTx.ExchangeRate, 7);
            }
        }