/// <summary>
 /// Creates the first ValuationMutation for a new position
 /// </summary>
 /// <param name="positionTx">The first positionTx that creates this Valuation Mutation</param>
 /// <param name="mutationDate">The date of the mutation</param>
 internal SecurityValuationMutation(IFundPositionTx positionTx)
 {
     this.Position = positionTx.ParentPosition;
     this.Account = Position.Account;
     this.Date = positionTx.TransactionDate;
     this.InstrumentCurrency = Position.InstrumentOfPosition.CurrencyNominal;
 }
 /// <summary>
 /// Creates a ValuationMutation for a new position, that originates from converted position(s) due to a corporate action (split/merger)
 /// </summary>
 /// <param name="convertedPositions">The positions that resulted in the new position due to a corporate action</param>
 /// <param name="positionTx">The positionTx that creates this Valuation Mutation</param>
 /// <param name="mutationDate">The date of the mutation</param>
 internal SecurityValuationMutation(IList<IFundPosition> convertedPositions, IFundPositionTx positionTx, DateTime mutationDate)
     : this(positionTx)
 {
     foreach (IFundPosition pos in convertedPositions)
     {
         BookValue += pos.LastMutation.BookValue;
         BookValueIC += pos.LastMutation.BookValueIC;
         RealisedAmountToDate += ((ISecurityValuationMutation)pos.LastMutation).RealisedAmountToDate;
         BaseRealisedAmountToDate += ((ISecurityValuationMutation)pos.LastMutation).BaseRealisedAmountToDate;
         pos.LastMutation.ConvertedMutation = this;
     }
 }
Example #3
0
        private ISecurityValuationMutation getNearestMutation(ref List<IValuationMutation> mutationsToSave, IFundPositionTx posTx)
        {
            ISecurityValuationMutation mut = null;
            TimeSpan days = TimeSpan.MaxValue;

            foreach (IValuationMutation mutation in mutationsToSave)
            {
                if (posTx.Instrument.Equals(mutation.Instrument))
                {
                    //if (mut != null && ((TimeSpan)(mutation.Date - posTx.TransactionDate)).Days > 0)
                    //    return mut;

                    if (mut == null || (days < (mutation.Date - posTx.TransactionDate)))
                    {
                        mut = (ISecurityValuationMutation)mutation;
                        days = mut.Date - posTx.TransactionDate;
                    }

                    if (days.Days >= 0)
                        return mut;
                }
            }
            if (mut == null)
            {
                // if no match, just take the first the first one
                mut = (ISecurityValuationMutation)mutationsToSave[0];
            }
            return mut;
        }
        protected void getPosTxInfo(IFundPositionTx posTx, out InstrumentSize newSize, out IsOpenClose isOpen)
        {
            isOpen = IsOpenClose.Close;
            newSize = InstrumentSize.Add(posTx.Size, Size, true);

            // Determine if it is opening or closing
            if (Size == null || Size.IsZero)
                isOpen = IsOpenClose.Open;
            else if (newSize.Sign != Size.Sign && newSize.IsNotZero)
                isOpen = IsOpenClose.Both;
            // short position -> gets larger
            else if (!Size.Sign && newSize.Sign == Size.Sign && newSize.Abs() > Size.Abs())
                isOpen = IsOpenClose.Open;
            else
            {
                if (IsSecurityValuationMutation)
                {
                    if (posTx.Side == Side.Sell || posTx.Side == Side.XO)
                        isOpen = IsOpenClose.Close;
                    else
                        isOpen = IsOpenClose.Open;
                }
                else
                {
                    // Cash -> just check the effect of the transaction
                    if (Size.Sign == posTx.Size.Sign)
                        isOpen = IsOpenClose.Open;
                    else
                        isOpen = IsOpenClose.Close;
                }
            }
        }
 protected void checkData(IFundPositionTx posTx)
 {
     if (!Position.Equals(posTx.ParentPosition))
         throw new ApplicationException("It is not possible to create Valuations when multiple positions exists for one instrument.");
 }
 protected Money calculateCurrencyGain(IFundPositionTx posTx, IsOpenClose isOpen)
 {
     Money gain = null;
     if (!posTx.DoNotRealize)
     {
         // calculate the gain caused by the foreign currency
         if (!this.InstrumentCurrency.IsBase && isOpen != IsOpenClose.Open)
         {
             Money realisedAmount = null;
             if (isOpen == IsOpenClose.Close)
                 realisedAmount = posTx.BookValueIC;
             else // if (isOpen == IsOpenClose.Both)
                 realisedAmount = Money.Multiply(posTx.BookValueIC, (Size.Quantity / posTx.Size.Quantity), true);
             if (posTx.ExchangeRate - AvgOpenExRate != 0)
             {
                 gain = realisedAmount.Convert(posTx.ExchangeRate - AvgOpenExRate, InstrumentCurrency.BaseCurrency, 7);
                 RealisedCurrencyGain = Money.Add(RealisedCurrencyGain, gain, true);
                 RealisedCurrencyGainToDate = Money.Add(RealisedCurrencyGainToDate, gain, true);
             }
         }
     }
     return gain;
 }
        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);
            }
        }
        public void AddTx(IFundPositionTx posTx)
        {
            IsOpenClose isOpen;
            InstrumentSize newSize;

            if (posTx.Price == null)
                throw new ApplicationException(string.Format("Price is NULL for posTxID: {0}", posTx.Key));

            getPosTxInfo(posTx, out newSize, out isOpen);

            if (CostPrice != null && !CostPrice.Underlying.Equals(posTx.Price.Underlying))
                throw new ApplicationException(string.Format("Can not handle one instrument with different currencies for instrument {0} (posTxID: {1}", posTx.Instrument.DisplayIsinWithName, posTx.Key));

            Money currencyGain = calculateCurrencyGain(posTx, isOpen);
            Money realAmount = null;
            Money baseRealAmount = null;
            Money baseChange = null;

            if (posTx.ParentTransaction.TransactionType == TransactionTypes.NTM && posTx.Price != null && posTx.Price.IsNotZero)
            {
                baseChange = (posTx.BookValue);
                if (isOpen == IsOpenClose.Close)
                    TransferOutToday = Money.Add(TransferOutToday, baseChange, true);
                else
                    TransferInToday = Money.Add(TransferInToday, baseChange, true);
            }

            // Realised Amount
            if (!posTx.DoNotRealize)
            {
                if (isOpen == IsOpenClose.Close)
                {
                    // In instrument currency
                    //realAmount = Money.Multiply(InstrumentSize.Multiply(posTx.Size, -1M, true), (posTx.Price - CostPrice), true);
                    realAmount = InstrumentSize.Multiply(posTx.Size, -1M, true).CalculateAmount((posTx.Price - CostPrice), true);
                    RealisedAmount = Money.Add(RealisedAmount, realAmount, true);
                    RealisedAmountToDate = Money.Add(RealisedAmountToDate, realAmount, true);

                    // In Base Currency
                    //baseRealAmount = Money.Add(realAmount.Convert(1M / posTx.ExchangeRate, InstrumentCurrency.BaseCurrency, 7), currencyGain, true);
                    //baseRealAmount = (this.BookPrice * posTx.Size) - posTx.BookValue;
                    baseRealAmount = Money.Subtract(posTx.Size.CalculateAmount(this.BookPrice, true), posTx.BookValue, true);
                    BaseRealisedAmount = Money.Add(BaseRealisedAmount, baseRealAmount, true);
                    BaseRealisedAmountToDate = Money.Add(BaseRealisedAmountToDate, baseRealAmount, true);

                }
                else if (isOpen == IsOpenClose.Both)
                {
                    // Position has swapped -> the old position size has relised
                    // all in same currency -> no fuckup
                    realAmount = Size.CalculateAmount((posTx.Price - CostPrice), true);
                    RealisedAmount = Money.Add(RealisedAmount, realAmount, true);
                    RealisedAmountToDate = Money.Add(RealisedAmountToDate, realAmount, true);

                    // In Base Currency
                    baseRealAmount = Money.Add(realAmount.Convert(1M / posTx.ExchangeRate, InstrumentCurrency.BaseCurrency, 7), currencyGain, true);
                    BaseRealisedAmount = Money.Add(BaseRealisedAmount, baseRealAmount, true);
                    BaseRealisedAmountToDate = Money.Add(BaseRealisedAmountToDate, baseRealAmount, true);
                }
            }
            else
            {
                // In case of conversion, there might be some cash involved
                realAmount = posTx.Value;
                RealisedAmount = Money.Add(RealisedAmount, realAmount, true);
                RealisedAmountToDate = Money.Add(RealisedAmountToDate, realAmount, true);

                baseRealAmount = posTx.ValueInBaseCurrency;
                BaseRealisedAmount = Money.Add(BaseRealisedAmount, baseRealAmount, true);
                BaseRealisedAmountToDate = Money.Add(BaseRealisedAmountToDate, baseRealAmount, true);
            }

            //// Cost Price
            if (isOpen == IsOpenClose.Both)
                CostPrice = posTx.Price;
            else if (isOpen == IsOpenClose.Open)
            {
                if (posTx.IsConversion)
                {
                    // This is a conversion ->
                    // Use the Book Value in instrument currency to calculate the price
                    CostPrice = BookValueIC / newSize;
                }
                else if (CostPrice == null)
                    CostPrice = posTx.Price;
                else
                {
                    if (newSize.IsNotZero)
                    {
                        Money newValue = Money.Add(Size.CalculateAmount(CostPrice, true), posTx.BookValueIC, true);
                        CostPrice = Money.Divide(newValue, newSize, true);
                    }
                }
            }

            calculateBookStuff(posTx, isOpen, newSize, realAmount, baseRealAmount);
            Size = newSize;
            Mappings.Add(new PositionTxValuationMapping(posTx, this));
        }
 public void AddNotRelevantPositionTx(IFundPositionTx notRelevantPosTx)
 {
     Mappings.Add(new PositionTxValuationMapping(notRelevantPosTx, this));
 }