Ejemplo n.º 1
0
        internal static void ReverseUnrealizedPnl(PostingEngineEnvironment env, Transaction openTaxLot, Transaction trade, double unrealizedPnl, double start, double end, double fxrate)
        {
            var accountToFrom = UnRealizedPnlPostingAccounts(openTaxLot, unrealizedPnl);

            new AccountUtils().SaveAccountDetails(env, accountToFrom.From);
            new AccountUtils().SaveAccountDetails(env, accountToFrom.To);

            var fromJournal = new Journal(openTaxLot)
            {
                When       = env.ValueDate,
                Event      = Event.REVERSE_UNREALIZED_PNL,
                FxRate     = fxrate,
                Fund       = env.GetFund(openTaxLot),
                StartPrice = start,
                EndPrice   = end,
                Quantity   = trade.Quantity,

                Account     = accountToFrom.To,
                CreditDebit = env.DebitOrCredit(accountToFrom.To, unrealizedPnl),
                Value       = env.SignedValue(accountToFrom.To, accountToFrom.From, true, unrealizedPnl),
            };

            var toJournal = new Journal(fromJournal)
            {
                Account     = accountToFrom.From,
                CreditDebit = env.DebitOrCredit(accountToFrom.From, unrealizedPnl),
                Value       = env.SignedValue(accountToFrom.To, accountToFrom.From, false, unrealizedPnl),
            };

            env.Journals.AddRange(new[] { fromJournal, toJournal });
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Contra Journal Entries
        /// </summary>
        /// <param name="env"></param>
        /// <param name="element"></param>
        /// <param name="tags"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="value"></param>
        internal static void GenerateJournalEntries(PostingEngineEnvironment env, Transaction element, List <Tag> tags, string from, string to, double value)
        {
            var fromAccount = new AccountUtils().CreateAccount(AccountType.Find(from), tags, element);
            var toAccount   = new AccountUtils().CreateAccount(AccountType.Find(to), tags, element);

            new AccountUtils().SaveAccountDetails(env, fromAccount);
            new AccountUtils().SaveAccountDetails(env, toAccount);

            var debitJournal = new Journal(element)
            {
                Account     = fromAccount,
                When        = env.ValueDate,
                StartPrice  = 0,
                EndPrice    = 0,
                CreditDebit = env.DebitOrCredit(fromAccount, value),
                Value       = env.SignedValue(fromAccount, toAccount, true, value),
                FxRate      = element.TradePrice,
                Event       = Event.REALIZED_PNL,
                Fund        = env.GetFund(element),
            };

            var creditJournal = new Journal(debitJournal)
            {
                Account     = toAccount,
                CreditDebit = env.DebitOrCredit(toAccount, value),
                Value       = env.SignedValue(fromAccount, toAccount, false, value),
            };

            env.Journals.AddRange(new[] { debitJournal, creditJournal });
        }
        private void PostUnrealizedFxGain(PostingEngineEnvironment env, Transaction element, double realizedFxPnl, double start, double end, double fxrate)
        {
            var m2mtranslation = "Mark to Market longs fx translation gain or loss";

            if (element.IsShort())
            {
                m2mtranslation = "Mark to Market shorts fx translation gain or loss";
            }

            var fromTo = new AccountUtils().GetAccounts(env, m2mtranslation, "change in unrealized do to fx translation", new string[] { element.SettleCurrency }.ToList());

            var debit = new Journal(fromTo.From, Event.UNREALIZED_FX_TRANSLATION, env.ValueDate)
            {
                Source     = element.LpOrderId,
                Fund       = env.GetFund(element),
                FxCurrency = element.SettleCurrency,
                Symbol     = element.Symbol,
                SecurityId = element.SecurityId,
                Quantity   = Convert.ToDouble(element.Quantity),

                FxRate     = fxrate,
                StartPrice = start,
                EndPrice   = end,

                Value       = env.SignedValue(fromTo.From, fromTo.To, true, realizedFxPnl * -1),
                CreditDebit = env.DebitOrCredit(fromTo.From, realizedFxPnl),
            };

            var credit = new Journal(fromTo.To, Event.UNREALIZED_FX_TRANSLATION, env.ValueDate)
            {
                Source     = element.LpOrderId,
                Fund       = env.GetFund(element),
                FxCurrency = element.SettleCurrency,
                Symbol     = element.Symbol,
                SecurityId = element.SecurityId,
                Quantity   = Convert.ToDouble(element.Quantity),

                FxRate     = fxrate,
                StartPrice = start,
                EndPrice   = end,

                Value       = env.SignedValue(fromTo.From, fromTo.To, false, realizedFxPnl * -1),
                CreditDebit = env.DebitOrCredit(fromTo.To, realizedFxPnl),
            };

            env.Journals.AddRange(new List <Journal>(new[] { debit, credit }));
        }
Ejemplo n.º 4
0
        private void AccrualPayment(PostingEngineEnvironment env, Transaction element, Accrual accrual)
        {
            var accountToFrom = GetFromToAccount(element);

            if (accountToFrom.To == null || accountToFrom.From == null)
            {
                env.AddMessage($"Unable to identify From/To accounts for trade {element.OrderSource} :: {element.Side}");
                return;
            }

            new AccountUtils().SaveAccountDetails(env, accountToFrom.From);
            new AccountUtils().SaveAccountDetails(env, accountToFrom.To);

            double fxrate = 1.0;

            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            var moneyUSD = element.LocalNetNotional * fxrate;

            var debit = new Journal(element)
            {
                Account     = accountToFrom.From,
                When        = env.ValueDate,
                FxRate      = fxrate,
                CreditDebit = env.DebitOrCredit(accountToFrom.From, moneyUSD),
                Value       = env.SignedValue(accountToFrom.From, accountToFrom.To, true, moneyUSD),
                Event       = "prepaid-expense",
                Fund        = env.GetFund(element),
            };

            var credit = new Journal(element)
            {
                Account     = accountToFrom.To,
                When        = env.ValueDate,
                FxRate      = fxrate,
                CreditDebit = env.DebitOrCredit(accountToFrom.To, moneyUSD),
                Value       = env.SignedValue(accountToFrom.From, accountToFrom.To, false, moneyUSD),
                Event       = "prepaid-expense",
                Fund        = env.GetFund(element),
            };

            env.Journals.Add(debit);
            env.Journals.Add(credit);
        }
Ejemplo n.º 5
0
        internal static void PostRealizedPnl(PostingEngineEnvironment env, Transaction element, double pnL, double start, double end, double fxrate = 1.0)
        {
            var accountToFrom = RealizedPnlPostingAccounts(element, pnL);

            new AccountUtils().SaveAccountDetails(env, accountToFrom.From);
            new AccountUtils().SaveAccountDetails(env, accountToFrom.To);


            if (element.IsDerivative())
            {
                // Need to Credit the From and Debit the to
                pnL *= -1;
            }
            else
            {
                if (element.IsShort() || element.IsCover())
                {
                    pnL *= -1;
                }
            }

            var debitJournal = new Journal(element)
            {
                Account     = accountToFrom.From,
                When        = env.ValueDate,
                StartPrice  = start,
                EndPrice    = end,
                CreditDebit = env.DebitOrCredit(accountToFrom.From, pnL),
                Value       = env.SignedValue(accountToFrom.From, accountToFrom.To, true, pnL),
                FxRate      = fxrate,
                Event       = Event.REALIZED_PNL,
                Fund        = env.GetFund(element),
            };

            var creditJournal = new Journal(element, accountToFrom.To, Event.REALIZED_PNL, env.ValueDate)
            {
                StartPrice  = start,
                EndPrice    = end,
                FxRate      = fxrate,
                CreditDebit = env.DebitOrCredit(accountToFrom.To, pnL * -1),
                Value       = env.SignedValue(accountToFrom.From, accountToFrom.To, false, pnL),
                Fund        = env.GetFund(element),
            };

            env.Journals.AddRange(new[] { debitJournal, creditJournal });
        }
        private void PostRealizedFxGain(PostingEngineEnvironment env, Transaction element, double realizedFxPnl, double start, double end, double fxrate)
        {
            var accountType = (element.IsShort() || element.IsCover()) ? "SHORT POSITIONS AT COST" : "LONG POSITIONS AT COST";
            var fromTo      = new AccountUtils().GetAccounts(env, accountType, "REALIZED GAIN/(LOSS) DUE TO FX", new string[] { element.SettleCurrency }.ToList());

            var debit = new Journal(fromTo.From, "realized-cash-fx", env.ValueDate)
            {
                Source     = element.LpOrderId,
                Fund       = env.GetFund(element),
                FxCurrency = element.SettleCurrency,
                Symbol     = element.Symbol,
                SecurityId = element.SecurityId,
                Quantity   = Convert.ToDouble(element.Quantity),

                FxRate     = fxrate,
                StartPrice = start,
                EndPrice   = end,

                Value       = env.SignedValue(fromTo.From, fromTo.To, true, realizedFxPnl),
                CreditDebit = env.DebitOrCredit(fromTo.From, realizedFxPnl),
            };

            var credit = new Journal(fromTo.To, "realized-cash-fx", env.ValueDate)
            {
                Source     = element.LpOrderId,
                Fund       = env.GetFund(element),
                FxCurrency = element.SettleCurrency,
                Symbol     = element.Symbol,
                SecurityId = element.SecurityId,
                Quantity   = Convert.ToDouble(element.Quantity),

                FxRate     = fxrate,
                StartPrice = start,
                EndPrice   = end,

                Value       = env.SignedValue(fromTo.From, fromTo.To, false, realizedFxPnl),
                CreditDebit = env.DebitOrCredit(fromTo.To, realizedFxPnl),
            };


            env.Journals.AddRange(new List <Journal>(new[] { debit, credit }));
        }
        private void ReversePosting(PostingEngineEnvironment env, string fromAccount, string toAccount, Transaction element, double reversalAmount)
        {
            var fromTo = new AccountUtils().GetAccounts(env, fromAccount, toAccount, new string[] { element.SettleCurrency }.ToList());

            var debit = new Journal(fromTo.From, "reversal-unrealized-cash-fx", env.ValueDate)
            {
                Source     = element.LpOrderId,
                Fund       = env.GetFund(element),
                FxCurrency = element.SettleCurrency,
                Symbol     = element.Symbol,
                SecurityId = element.SecurityId,
                Quantity   = Convert.ToDouble(element.Quantity),
                FxRate     = 0,
                StartPrice = 0,
                EndPrice   = 0,

                Value       = env.SignedValue(fromTo.From, fromTo.To, true, reversalAmount * -1),
                CreditDebit = env.DebitOrCredit(fromTo.From, reversalAmount),
            };

            var credit = new Journal(fromTo.To, "reversal-unrealized-cash-fx", env.ValueDate)
            {
                Source     = element.LpOrderId,
                Fund       = env.GetFund(element),
                FxCurrency = element.SettleCurrency,
                Symbol     = element.Symbol,
                SecurityId = element.SecurityId,
                Quantity   = Convert.ToDouble(element.Quantity),

                FxRate     = 0,
                StartPrice = 0,
                EndPrice   = 0,

                Value       = env.SignedValue(fromTo.From, fromTo.To, false, reversalAmount * -1),
                CreditDebit = env.DebitOrCredit(fromTo.To, reversalAmount),
            };

            env.Journals.AddRange(new List <Journal>(new[] { debit, credit }));
        }
Ejemplo n.º 8
0
        internal static void PostRealizedPnl(PostingEngineEnvironment env, Transaction element, double realizedPnl, string from, string to)
        {
            var listOfTags = new List <Tag> {
                Tag.Find("SecurityType"),
                Tag.Find("CustodianCode")
            };

            var fromAccount = new AccountUtils().CreateAccount(AccountType.Find(from), listOfTags, element);
            var toAccount   = new AccountUtils().CreateAccount(AccountType.Find(to), listOfTags, element);

            new AccountUtils().SaveAccountDetails(env, fromAccount);
            new AccountUtils().SaveAccountDetails(env, toAccount);

            var debitJournal = new Journal(element)
            {
                Account     = fromAccount,
                When        = env.ValueDate,
                StartPrice  = 0,
                EndPrice    = 0,
                CreditDebit = env.DebitOrCredit(fromAccount, realizedPnl),
                Value       = env.SignedValue(fromAccount, toAccount, true, realizedPnl),
                FxRate      = element.TradePrice,
                Event       = Event.REALIZED_PNL,
                Fund        = env.GetFund(element),
            };

            var creditJournal = new Journal(element, toAccount, Event.REALIZED_PNL, env.ValueDate)
            {
                StartPrice  = 0,
                EndPrice    = 0,
                FxRate      = element.TradePrice,
                CreditDebit = env.DebitOrCredit(toAccount, realizedPnl),
                Value       = env.SignedValue(fromAccount, toAccount, false, realizedPnl),
                Fund        = env.GetFund(element),
            };

            env.Journals.AddRange(new[] { debitJournal, creditJournal });
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Single Sided Entry Journal
        /// </summary>
        /// <param name="env"></param>
        /// <param name="element"></param>
        /// <param name="tags"></param>
        /// <param name="accountType"></param>
        /// <param name="value"></param>
        internal static void GenerateJournalEntry(PostingEngineEnvironment env, Transaction element, List <Tag> tags, AccountType accountType, string eventName, double value)
        {
            var account = new AccountUtils().CreateAccount(accountType, tags, element);

            new AccountUtils().SaveAccountDetails(env, account);

            var journal = new Journal(element)
            {
                Account     = account,
                When        = env.ValueDate,
                StartPrice  = 0,
                EndPrice    = 0,
                CreditDebit = env.DebitOrCredit(account, value),
                Value       = value,
                FxRate      = element.TradePrice,
                Event       = eventName,
                Fund        = env.GetFund(element),
            };

            env.Journals.AddRange(new[] { journal });
        }
Ejemplo n.º 10
0
        public void SettlementDateEvent(PostingEngineEnvironment env, Transaction element)
        {
            var accrual     = env.FindAccruals(element.AccrualId);
            var allocations = env.FindAllocations(element.AccrualId);
            var allocation  = allocations.Where(i => !i.Symbol.Equals(element.Symbol)).FirstOrDefault();

            if (element.Status.Equals("Cancelled"))
            {
                env.AddMessage($"Entry has been cancelled {element.LpOrderId} :: {element.Side}");
                return;
            }

            // If they are the same we need to do nothing
            if (element.TradeDate.Date == element.SettleDate.Date)
            {
                //env.AddMessage($"Journal needs to be checked {element.LpOrderId}, {element.TradeDate}, {element.SettleDate}");
                return;
            }

            var accountToFrom = GetSettlementFromToAccount(element);

            if (accountToFrom.To == null)
            {
                env.AddMessage($"Unable to identify From/To accounts for trade {element.OrderSource} :: {element.Side}");
                return;
            }

            new AccountUtils().SaveAccountDetails(env, accountToFrom.From);
            new AccountUtils().SaveAccountDetails(env, accountToFrom.To);

            double fxrate = 1.0;

            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            var moneyUSD = element.LocalNetNotional * fxrate;

            if (element.LocalNetNotional != 0.0)
            {
                var symbol     = allocation != null ? allocation.Symbol : element.ParentSymbol;
                var securityId = allocation != null ? allocation.SecurityId : element.SecurityId;

                if (symbol == null)
                {
                    symbol = element.Symbol;
                }

                var debit = new Journal(accountToFrom.From, "journal", env.ValueDate)
                {
                    Symbol     = symbol,
                    SecurityId = allocation != null ? allocation.SecurityId : element.SecurityId,

                    Source      = element.LpOrderId,
                    Quantity    = element.Quantity,
                    FxCurrency  = element.SettleCurrency,
                    FxRate      = fxrate,
                    CreditDebit = env.DebitOrCredit(accountToFrom.From, moneyUSD),
                    Value       = moneyUSD,
                    Fund        = env.GetFund(element),
                };

                var credit = new Journal(accountToFrom.To, "journal", env.ValueDate)
                {
                    Symbol     = symbol,
                    SecurityId = allocation != null ? allocation.SecurityId : element.SecurityId,

                    Source      = element.LpOrderId,
                    Quantity    = element.Quantity,
                    FxCurrency  = element.SettleCurrency,
                    FxRate      = fxrate,
                    CreditDebit = env.DebitOrCredit(accountToFrom.To, moneyUSD * -1),
                    Value       = moneyUSD * -1,
                    Fund        = env.GetFund(element),
                };

                env.Journals.Add(debit);
                env.Journals.Add(credit);
            }

            return;
        }
Ejemplo n.º 11
0
        public void TradeDateEvent(PostingEngineEnvironment env, Transaction element)
        {
            var accrual     = env.FindAccruals(element.AccrualId);
            var allocations = env.FindAllocations(element.AccrualId);
            var allocation  = allocations.Where(i => !i.Symbol.Equals(element.Symbol)).FirstOrDefault();

            //Console.WriteLine(element.Symbol);

            if (element.Symbol.Equals("ZZ_INVESTOR_CONTRIBUTIONS"))
            {
            }

            if (element.Status.Equals("Cancelled"))
            {
                env.AddMessage($"Entry has been cancelled {element.LpOrderId} :: {element.Side}");
                return;
            }

            // Need to consider both
            if (element.TradeDate.Date != element.SettleDate.Date)
            {
                env.AddMessage($"Journal needs to be checked {element.LpOrderId}, {element.TradeDate}, {element.SettleDate}");
                return;
            }

            var accountToFrom = GetFromToAccount(element);

            if (accountToFrom.To == null)
            {
                env.AddMessage($"Unable to identify From/To accounts for trade {element.OrderSource} :: {element.Side}");
                return;
            }

            new AccountUtils().SaveAccountDetails(env, accountToFrom.From);
            new AccountUtils().SaveAccountDetails(env, accountToFrom.To);

            double fxrate = 1.0;

            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            var moneyUSD = element.LocalNetNotional * fxrate;

            if (element.LocalNetNotional != 0.0)
            {
                var symbol     = allocation != null ? allocation.Symbol : element.ParentSymbol;
                var securityId = allocation != null ? allocation.SecurityId : element.SecurityId;

                if (symbol == null)
                {
                    symbol = element.Symbol;
                }

                var debit = new Journal(element)
                {
                    Symbol     = symbol,
                    SecurityId = securityId,

                    Account     = accountToFrom.From,
                    When        = env.ValueDate,
                    FxRate      = fxrate,
                    CreditDebit = env.DebitOrCredit(accountToFrom.From, moneyUSD),
                    Value       = moneyUSD,
                    Event       = Event.JOURNAL,
                    Fund        = env.GetFund(element),
                };

                var credit = new Journal(element)
                {
                    Symbol     = symbol,
                    SecurityId = securityId,

                    Account     = accountToFrom.To,
                    When        = env.ValueDate,
                    FxRate      = fxrate,
                    CreditDebit = env.DebitOrCredit(accountToFrom.To, moneyUSD),
                    Value       = moneyUSD,
                    Event       = Event.JOURNAL,
                    Fund        = env.GetFund(element),
                };

                env.Journals.Add(debit);
                env.Journals.Add(credit);
            }

            return;
        }
Ejemplo n.º 12
0
        internal static void GenerateCloseOutPostings(PostingEngineEnvironment env, TaxLotDetail lot, TaxLot taxlot, Transaction element, TaxLotStatus taxlotStatus, string fund)
        {
            double multiplier = 1.0;

            if (env.SecurityDetails.ContainsKey(element.BloombergCode))
            {
                multiplier = env.SecurityDetails[element.BloombergCode].Multiplier;
            }

            double fxrate = 1.0;

            // Lets get fx rate if needed
            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            var prevPrice     = MarketPrices.GetPrice(env, env.PreviousValueDate, lot.Trade).Price;
            var unrealizedPnl = Math.Abs(taxlotStatus.Quantity) * (element.SettleNetPrice - prevPrice) * multiplier;

            unrealizedPnl = Math.Abs(unrealizedPnl) * CommonRules.DetermineSign(taxlotStatus.Trade);

            var buyTrade = env.FindTrade(lot.Trade.LpOrderId);

            ReverseUnrealizedPnl(
                env,
                buyTrade,
                element,
                unrealizedPnl,
                MarketPrices.GetPrice(env, env.PreviousValueDate, lot.Trade).Price,
                element.SettleNetPrice, fxrate);

            var PnL = taxlot.RealizedPnl;

            PostRealizedPnl(
                env,
                buyTrade,
                PnL,
                taxlot.TradePrice,
                taxlot.CostBasis, fxrate);

            var listOfFromTags = new List <Tag>
            {
                Tag.Find("SecurityType"),
                Tag.Find("CustodianCode")
            };

            Account fromAccount = null;
            Account toAccount   = null;

            if (element.IsDerivative())
            {
                return;
            }
            else
            {
                var accountType         = (buyTrade.IsShort() || buyTrade.IsCover()) ? "SHORT POSITIONS AT COST" : "LONG POSITIONS AT COST";
                var markToMarketAccount = (buyTrade.IsShort() || buyTrade.IsCover()) ? "Mark to Market Shorts" : "Mark to Market Longs";

                fromAccount = new AccountUtils().CreateAccount(AccountType.Find(accountType), listOfFromTags, element);
                toAccount   = new AccountUtils().CreateAccount(AccountType.Find(markToMarketAccount), listOfFromTags, element);
            }

            new AccountUtils().SaveAccountDetails(env, fromAccount);
            new AccountUtils().SaveAccountDetails(env, toAccount);

            // Now Generate Entries
            var fromJournal = new Journal(element)
            {
                Account     = fromAccount,
                CreditDebit = env.DebitOrCredit(fromAccount, PnL),
                When        = env.ValueDate,
                StartPrice  = taxlot.TradePrice,
                EndPrice    = taxlot.CostBasis,
                Value       = PnL,
                FxRate      = 1,
                Event       = Event.REALIZED_PNL,
                Fund        = env.GetFund(element),
            };

            var toJournal = new Journal(fromJournal)
            {
                Account     = toAccount,
                CreditDebit = env.DebitOrCredit(toAccount, PnL * -1),
                Value       = PnL * -1,
            };

            env.Journals.AddRange(new[] { fromJournal, toJournal });
        }
        private void GenerateDailyUnrealized(PostingEngineEnvironment env, TaxLotStatus taxLotStatus, Transaction element, double quantity, double fxRate)
        {
            var prevEodPrice = 0.0;
            var eodPrice     = 0.0;

            if (env.ValueDate == taxLotStatus.Trade.TradeDate)
            {
                prevEodPrice = taxLotStatus.Trade.SettleNetPrice;
                eodPrice     = MarketPrices.GetPrice(env, env.ValueDate, taxLotStatus.Trade).Price;
            }
            else
            {
                prevEodPrice = MarketPrices.GetPrice(env, env.PreviousValueDate, taxLotStatus.Trade).Price;
                eodPrice     = MarketPrices.GetPrice(env, env.ValueDate, taxLotStatus.Trade).Price;
            }

            var endPrice = element.SettleNetPrice;

            if (taxLotStatus.Quantity == 0.0)
            {
                eodPrice = endPrice;
            }

            var unrealizedPnl = CommonRules.CalculateUnrealizedPnl(env, taxLotStatus, quantity, eodPrice);

            var originalAccount = taxLotStatus.Side == "SHORT" ? "Mark to Market Shorts" : "Mark to Market Longs";
            var fromToAccounts  = new AccountUtils().GetAccounts(env, originalAccount, "CHANGE IN UNREALIZED GAIN/(LOSS)", listOfTags, taxLotStatus.Trade);

            if (taxLotStatus.Side == "SHORT")
            {
                unrealizedPnl *= -1;
            }

            var fund = env.GetFund(taxLotStatus.Trade);

            var debit = new Journal(taxLotStatus.Trade)
            {
                Account     = fromToAccounts.From,
                When        = env.ValueDate,
                Symbol      = taxLotStatus.Symbol,
                Quantity    = quantity,
                FxRate      = fxRate,
                Value       = env.SignedValue(fromToAccounts.From, fromToAccounts.To, true, unrealizedPnl),
                CreditDebit = env.DebitOrCredit(fromToAccounts.From, unrealizedPnl),
                StartPrice  = prevEodPrice,
                EndPrice    = eodPrice,
                Event       = Event.DAILY_UNREALIZED_PNL,
                Fund        = fund,
            };

            var credit = new Journal(debit)
            {
                Account     = fromToAccounts.To,
                Value       = env.SignedValue(fromToAccounts.From, fromToAccounts.To, false, unrealizedPnl),
                CreditDebit = env.DebitOrCredit(fromToAccounts.To, unrealizedPnl),
            };

            env.Journals.AddRange(new[] { debit, credit });

            if (fxRate != 1.0)
            {
                if (element.TradeDate != env.ValueDate && element.SettleDate >= env.ValueDate)
                {
                    var fxJournals = FxPosting.CreateFx(
                        env,
                        "DUE FROM/(TO) PRIME BROKERS ( Unsettled Activity )",
                        "fx gain or loss on unsettled balance",
                        "daily",
                        quantity, null, element);
                    env.Journals.AddRange(fxJournals);
                }

                if (taxLotStatus.Quantity != 0.0)
                {
                    if (env.ValueDate.Equals(new DateTime(2019, 12, 17)))
                    {
                    }

                    if (element.TradeDate != env.ValueDate)
                    {
                        // Has to happen for every day
                        var fxJournalsForInvestmentAtCost = FxPosting.CreateFx(
                            env,
                            CommonRules.GetFXMarkToMarketAccountType(element, "FX MARKET TO MARKET ON STOCK COST"),
                            "Change in unrealized due to fx on original Cost",
                            "daily", quantity, taxLotStatus, element);
                        env.Journals.AddRange(fxJournalsForInvestmentAtCost);

                        new FxPosting().CreateFxUnsettled(env, element);
                    }
                }
            }
        }
Ejemplo n.º 14
0
        internal static void GenerateSettlementDateJournals(PostingEngineEnvironment env, Transaction element)
        {
            double fxrate = 1.0;

            // Lets get fx rate if needed
            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            var accountToFrom = new AccountingRules().GetFromToAccountOnSettlement(env, element);

            if (accountToFrom.To == null || accountToFrom.From == null)
            {
                env.AddMessage($"Unable to identify From/To accounts for trade {element.OrderSource} :: {element.Side}");
                return;
            }

            // This is the fully loaded value to tbe posting

            if (element.NetMoney != 0.0)
            {
                var moneyUSD = Math.Abs(element.NetMoney) * fxrate;

                // BUY -- Debit
                // SELL -- Credit

                if (element.IsShort() || element.IsSell())
                {
                    moneyUSD = moneyUSD * -1;
                }

                var debit = new Journal
                {
                    Source      = element.LpOrderId,
                    Account     = accountToFrom.From,
                    When        = env.ValueDate,
                    FxCurrency  = element.SettleCurrency,
                    Symbol      = element.Symbol,
                    SecurityId  = element.SecurityId,
                    Quantity    = element.Quantity,
                    FxRate      = fxrate,
                    CreditDebit = env.DebitOrCredit(accountToFrom.From, moneyUSD),
                    Value       = env.SignedValue(accountToFrom.From, accountToFrom.To, true, moneyUSD),
                    Event       = Event.SETTLEMENT,
                    Fund        = env.GetFund(element)
                };

                var credit = new Journal
                {
                    Source     = element.LpOrderId,
                    FxCurrency = element.SettleCurrency,
                    Symbol     = element.Symbol,
                    SecurityId = element.SecurityId,
                    Quantity   = element.Quantity,

                    FxRate  = fxrate,
                    When    = env.ValueDate,
                    Account = accountToFrom.To,

                    CreditDebit = env.DebitOrCredit(accountToFrom.To, moneyUSD * -1),
                    Value       = env.SignedValue(accountToFrom.From, accountToFrom.To, false, moneyUSD),
                    Event       = Event.SETTLEMENT,
                    Fund        = env.GetFund(element)
                };

                env.Journals.AddRange(new[] { debit, credit });
            }
        }
Ejemplo n.º 15
0
        internal static void GenerateTradeDateJournals(PostingEngineEnvironment env, Transaction element)
        {
            double multiplier = 1.0;

            if (env.SecurityDetails.ContainsKey(element.BloombergCode))
            {
                multiplier = env.SecurityDetails[element.BloombergCode].Multiplier;
            }

            double fxrate = 1.0;

            // Lets get fx rate if needed
            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            var tradeAllocations = env.Allocations.Where(i => i.LpOrderId == element.LpOrderId).ToList();

            // Retrieve Allocation Objects for this trade
            if (tradeAllocations.Count() > 2)
            {
                env.AddMessage($"#of allocations > 2 please investigate {element.LpOrderId}");
                return;
            }

            if (tradeAllocations.Count() == 2)
            {
                var debitEntry = tradeAllocations[0].Side == element.Side ? tradeAllocations[0] : tradeAllocations[1];
                if (debitEntry.Symbol.Equals("@CASHUSD"))
                {
                    env.AddMessage($"Unexpected Cash allocation please investigate {element.LpOrderId}");
                    return;
                }
            }

            var accountToFrom = GetFromToAccount(env, element);

            if (accountToFrom.To == null || accountToFrom.From == null)
            {
                env.AddMessage($"Unable to identify From/To accounts for trade {element.OrderSource} :: {element.Side}");
                return;
            }

            if (element.NetMoney != 0.0)
            {
                var moneyUSD = Math.Abs(element.NetMoney) * fxrate;

                // BUY -- Debit
                // SELL -- Credit

                if (element.IsSell() || element.IsCover())
                {
                    moneyUSD = moneyUSD * -1;
                }

                var eodPrice = MarketPrices.GetPrice(env, env.ValueDate, element).Price;

                var fromJournal = new Journal(element, accountToFrom.From, Event.TRADE_DATE, env.ValueDate)
                {
                    CreditDebit = env.DebitOrCredit(accountToFrom.From, moneyUSD),
                    Value       = env.SignedValue(accountToFrom.From, accountToFrom.To, true, moneyUSD),
                    FxRate      = fxrate,
                    StartPrice  = element.SettleNetPrice,
                    EndPrice    = eodPrice,
                    Fund        = env.GetFund(element),
                };

                var toJournal = new Journal(element, accountToFrom.To, Event.TRADE_DATE, env.ValueDate)
                {
                    FxRate      = fxrate,
                    CreditDebit = env.DebitOrCredit(accountToFrom.To, moneyUSD * -1),
                    Value       = env.SignedValue(accountToFrom.From, accountToFrom.To, false, moneyUSD),
                    StartPrice  = element.SettleNetPrice,
                    EndPrice    = eodPrice,
                    Fund        = env.GetFund(element),
                };

                env.Journals.AddRange(new[] { fromJournal, toJournal });
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Run for each day that the Tax Lot remains open / partially closed
        /// </summary>
        /// <param name="env"></param>
        /// <param name="element">Trade we aee interested in</param>
        public void DailyEvent(PostingEngineEnvironment env, Transaction element)
        {
            double fxrate = 1.0;

            // Lets get fx rate if needed
            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            // Calculate the unrealized PNL
            if (env.TaxLotStatus.ContainsKey(element.LpOrderId))
            {
                // Determine if we need to accumulate unrealized PNL
                var taxlot = env.TaxLotStatus[element.LpOrderId];

                // Check to see if the TaxLot is still open and it has a non zero Quantity
                if (!taxlot.Status.ToLowerInvariant().Equals("closed") && Math.Abs(taxlot.Quantity) > 0)
                {
                    var listOfTags = new List <Tag>
                    {
                        Tag.Find("SecurityType"),
                        Tag.Find("CustodianCode")
                    };

                    var split        = element.Symbol.Split(new char[] { '/', ' ' });
                    var baseCurrency = split[0];
                    var riskCurrency = split[1];

                    var eodPrice     = MarketPrices.GetPrice(env, env.ValueDate, element).Price;
                    var prevEodPrice = MarketPrices.GetPrice(env, env.PreviousValueDate, element).Price;

                    if (baseCurrency.Equals(env.BaseCurrency))
                    {
                        if (env.ValueDate == element.TradeDate)
                        {
                            prevEodPrice = element.SettleNetPrice;
                        }
                    }
                    else
                    {
                        if (env.ValueDate == element.TradeDate)
                        {
                            prevEodPrice = element.SettleNetPrice;
                        }
                    }

                    // we need to do this when there is no price for the trade from market data
                    if (prevEodPrice == 0.0)
                    {
                        prevEodPrice = element.SettleNetPrice;
                    }

                    if (eodPrice == 0.0)
                    {
                        eodPrice = element.SettleNetPrice;
                    }

                    // We have an open / partially closed tax lot so now need to calculate unrealized Pnl
                    var quantity = taxlot.Quantity;

                    var rateDiff = (eodPrice - prevEodPrice);

                    var unrealizedPnl = (rateDiff * quantity);

                    if (baseCurrency.Equals(env.BaseCurrency))
                    {
                        unrealizedPnl = unrealizedPnl / eodPrice;
                    }

                    var originalAccount = AccountUtils.GetDerivativeAccountType(unrealizedPnl);
                    var fromToAccounts  = new AccountUtils().GetAccounts(env, originalAccount, "Change in Unrealized Derivatives Contracts at Fair Value", listOfTags, taxlot.Trade);

                    var fund = env.GetFund(element);

                    var debit = new Journal(element)
                    {
                        Account     = fromToAccounts.From,
                        When        = env.ValueDate,
                        Symbol      = taxlot.Symbol,
                        Quantity    = quantity,
                        FxRate      = rateDiff,
                        Value       = env.SignedValue(fromToAccounts.From, fromToAccounts.To, false, unrealizedPnl),
                        CreditDebit = env.DebitOrCredit(fromToAccounts.From, unrealizedPnl),
                        StartPrice  = prevEodPrice,
                        EndPrice    = eodPrice,
                        Event       = Event.DAILY_UNREALIZED_PNL,
                        Fund        = fund,
                    };

                    var credit = new Journal(debit)
                    {
                        Account     = fromToAccounts.To,
                        Value       = env.SignedValue(fromToAccounts.From, fromToAccounts.To, true, unrealizedPnl),
                        CreditDebit = env.DebitOrCredit(fromToAccounts.To, unrealizedPnl),
                    };

                    env.Journals.AddRange(new[] { debit, credit });

                    if (element.LpOrderId.Equals("3bbf9793-d01a-4a08-b25c-448fd1777ef1"))
                    {
                    }

                    if (element.TradeDate != env.ValueDate && element.SettleDate >= env.ValueDate)
                    {
                        var fxJournals = FxPosting.CreateFx(
                            env,
                            "daily",
                            quantity, null, element);
                        env.Journals.AddRange(fxJournals);
                    }
                }
            }
            else
            {
                if (fxrate != 1.0)
                {
                    if (element.TradeDate != env.ValueDate && element.SettleDate >= env.ValueDate)
                    {
                        var fxJournals = FxPosting.CreateFx(
                            env,
                            "daily",
                            element.Quantity, null, element);
                        env.Journals.AddRange(fxJournals);
                    }
                }
            }
        }
Ejemplo n.º 17
0
        public void SettlementDateEvent(PostingEngineEnvironment env, Transaction element)
        {
            if (env.TaxLotStatus.ContainsKey(element.LpOrderId))
            {
                var taxlot = env.TaxLotStatus[element.LpOrderId];

                var tradeCurrency  = element.TradeCurrency;
                var settleCurrency = element.SettleCurrency;
                var allocations    = env.FindTradeAllocations(element);

                var buy  = allocations.Where(i => i.SecurityType.Equals("SPOT") && i.Side.Equals("BUY")).FirstOrDefault();
                var sell = allocations.Where(i => i.SecurityType.Equals("SPOT") && i.Side.Equals("SELL")).FirstOrDefault();

                if (buy == null || sell == null)
                {
                    Logger.Error($"Unable to process {element.SecurityType}::{element.LpOrderId}");
                    return;
                }

                var accountSell = new AccountUtils().CreateAccount(atSettledCash, listOfTradeTags, sell);
                var accountBuy  = new AccountUtils().CreateAccount(atSettledCash, listOfTradeTags, buy);

                new AccountUtils().SaveAccountDetails(env, accountSell);
                new AccountUtils().SaveAccountDetails(env, accountBuy);

                var sellFx = FxRates.Find(env.ValueDate, sell.TradeCurrency);
                var buyFx  = FxRates.Find(env.ValueDate, buy.TradeCurrency);

                var sellValue = sell.Quantity * sellFx.Rate;
                var buyValue  = buy.Quantity * buyFx.Rate;


                if (element.IsBuy())   // BUY
                {
                    var realizedPnl = buyValue + sellValue;

                    var debit = new Journal(accountBuy, Event.SETTLED_CASH, env.ValueDate)
                    {
                        Source     = element.LpOrderId,
                        Fund       = env.GetFund(element),
                        FxCurrency = element.TradeCurrency,
                        Symbol     = element.Symbol,
                        SecurityId = element.SecurityId,
                        Quantity   = Convert.ToDouble(buy.Quantity),

                        FxRate     = buyFx.Rate,
                        StartPrice = 0,
                        EndPrice   = 0,

                        Value       = env.SignedValue(accountBuy, accountSell, true, buyValue),
                        CreditDebit = env.DebitOrCredit(accountBuy, buy.Quantity),
                    };

                    var credit = new Journal(accountSell, Event.SETTLED_CASH, env.ValueDate)
                    {
                        Source     = element.LpOrderId,
                        Fund       = env.GetFund(element),
                        FxCurrency = element.SettleCurrency,
                        Symbol     = element.Symbol,
                        SecurityId = element.SecurityId,
                        Quantity   = Convert.ToDouble(sell.Quantity),

                        FxRate     = sellFx.Rate,
                        StartPrice = 0,
                        EndPrice   = 0,

                        Value       = env.SignedValue(accountBuy, accountSell, true, sellValue),
                        CreditDebit = env.DebitOrCredit(accountSell, sell.Quantity),
                    };

                    env.Journals.AddRange(new[] { credit, debit });

                    var originalAccount = AccountUtils.GetDerivativeAccountType(realizedPnl);

                    // Realized Pnl to go along with the Settled Cash
                    CommonRules.GenerateJournalEntry(env, element, listOfTags, realizedAccountType, Event.REALIZED_PNL, realizedPnl);

                    CommonRules.GenerateJournalEntries(env, element, listOfTags, originalAccount, "Change in Unrealized Derivatives Contracts at Fair Value", realizedPnl * -1);
                }
                else // SELL
                {
                    var realizedPnl = buyValue + sellValue;

                    var debit = new Journal(accountBuy, Event.SETTLED_CASH, env.ValueDate)
                    {
                        Source     = element.LpOrderId,
                        Fund       = env.GetFund(element),
                        FxCurrency = element.TradeCurrency,
                        Symbol     = element.Symbol,
                        SecurityId = element.SecurityId,
                        Quantity   = Convert.ToDouble(buy.Quantity),

                        FxRate     = buyFx.Rate,
                        StartPrice = 0,
                        EndPrice   = 0,

                        Value       = env.SignedValue(accountBuy, accountSell, true, buy.Quantity * buyFx.Rate),
                        CreditDebit = env.DebitOrCredit(accountBuy, buy.Quantity),
                    };

                    var credit = new Journal(accountSell, Event.SETTLED_CASH, env.ValueDate)
                    {
                        Source     = element.LpOrderId,
                        Fund       = env.GetFund(element),
                        FxCurrency = element.SettleCurrency,
                        Symbol     = element.Symbol,
                        SecurityId = element.SecurityId,
                        Quantity   = Convert.ToDouble(sell.Quantity),

                        FxRate     = sellFx.Rate,
                        StartPrice = 0,
                        EndPrice   = 0,

                        Value       = env.SignedValue(accountBuy, accountSell, true, sell.Quantity * sellFx.Rate),
                        CreditDebit = env.DebitOrCredit(accountSell, sell.Quantity),
                    };

                    env.Journals.AddRange(new[] { credit, debit });

                    var originalAccount = AccountUtils.GetDerivativeAccountType(realizedPnl);

                    // Realized Pnl to go along with the Settled Cash
                    CommonRules.GenerateJournalEntry(env, element, listOfTags, realizedAccountType, Event.REALIZED_PNL, realizedPnl);

                    CommonRules.GenerateJournalEntries(env, element, listOfTags, originalAccount, "Change in Unrealized Derivatives Contracts at Fair Value", realizedPnl * -1);
                }

                if (taxlot.Quantity != 0)
                {
                    var buyTrade = env.FindTrade(taxlot.OpenId);
                    CommonRules.RelieveTaxLot(env, buyTrade, element, taxlot.Quantity * -1, true);
                    taxlot.Quantity = 0;
                    taxlot.Status   = "Closed";

                    //Now we have Realized Pnl
                }
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Create the entries for Unsettled Fx gain / loss
        /// </summary>
        /// <param name="env">Environment</param>
        /// <param name="taxlotStatus"></param>
        /// <param name="tradeEvent"></param>
        /// <param name="element">Transaction</param>
        /// <returns>a list of the created journal entries</returns>
        internal static List <Journal> CreateFx(PostingEngineEnvironment env,
                                                string fromAccount,
                                                string toAccount,
                                                string tradeEvent,
                                                double quantity,
                                                TaxLotStatus taxlotStatus,
                                                Transaction element)
        {
            if (tradeEvent.Equals(Event.TRADE_DATE))
            {
                return(new List <Journal>());
            }

            // TBD: THIS IS FOR BOBBY
            if (element.SecurityType.Equals("FORWARD"))
            {
                return(new List <Journal>());
            }

            // Check to see if the BaseCurrency == SettleCurrency because if it is then no need to do the FX translation
            if (env.BaseCurrency.Equals(element.SettleCurrency))
            {
                return(new List <Journal>());
            }

            var currency = element.SettleCurrency;

            var prevEodFxRate = Convert.ToDouble(FxRates.Find(env.PreviousValueDate, currency).Rate);
            var eodFxRate     = Convert.ToDouble(FxRates.Find(env.ValueDate, currency).Rate);
            var effectiveRate = eodFxRate - prevEodFxRate;

            var usdEquivalent = element.NetMoney * effectiveRate;

            if (element.IsBuy())
            {
                usdEquivalent *= -1;
            }
            else if (element.IsShort())
            {
            }

            // Get accounts
            var toFrom = new AccountUtils().GetAccounts(env, fromAccount, toAccount, _TAGS, element);

            var debit = new Journal(element, toFrom.From, $"{tradeEvent}-unrealizedpnl-fx", env.ValueDate)
            {
                Quantity   = quantity,
                FxRate     = effectiveRate,
                StartPrice = prevEodFxRate,
                EndPrice   = eodFxRate,
                Fund       = env.GetFund(element),

                Value       = env.SignedValue(toFrom.From, toFrom.To, true, usdEquivalent),
                CreditDebit = env.DebitOrCredit(toFrom.From, usdEquivalent),
            };

            var credit = new Journal(element, toFrom.To, $"{tradeEvent}-unrealizedpnl-fx", env.ValueDate)
            {
                Quantity   = quantity,
                FxRate     = effectiveRate,
                StartPrice = prevEodFxRate,
                EndPrice   = eodFxRate,
                Fund       = env.GetFund(element),

                Value       = env.SignedValue(toFrom.From, toFrom.To, false, usdEquivalent),
                CreditDebit = env.DebitOrCredit(toFrom.To, usdEquivalent),
            };


            return(new List <Journal>(new[] { debit, credit }));
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Run for each day that the Tax Lot remains open / partially closed
        /// </summary>
        /// <param name="env"></param>
        /// <param name="element">Trade we aee interested in</param>
        public void DailyEvent(PostingEngineEnvironment env, Transaction element)
        {
            double fxrate = 1.0;

            // Lets get fx rate if needed
            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            // Calculate the unrealized PNL
            if (env.TaxLotStatus.ContainsKey(element.LpOrderId))
            {
                // Determine if we need to accumulate unrealized PNL
                var taxlot = env.TaxLotStatus[element.LpOrderId];

                // Check to see if the TaxLot is still open and it has a non zero Quantity
                if (!taxlot.Status.ToLowerInvariant().Equals("closed") && Math.Abs(taxlot.Quantity) > 0)
                {
                    var listOfTags = new List <Tag>
                    {
                        Tag.Find("SecurityType"),
                        Tag.Find("CustodianCode")
                    };

                    // We have an open / partially closed tax lot so now need to calculate unrealized Pnl
                    var quantity = taxlot.Quantity;

                    var prevEodPrice = 0.0;
                    var eodPrice     = 0.0;

                    if (env.ValueDate == element.TradeDate)
                    {
                        eodPrice     = MarketPrices.GetPrice(env, env.ValueDate, element).Price;
                        prevEodPrice = element.SettleNetPrice;
                    }
                    else
                    {
                        prevEodPrice = MarketPrices.GetPrice(env, env.PreviousValueDate, element).Price;
                        eodPrice     = MarketPrices.GetPrice(env, env.ValueDate, element).Price;
                    }

                    var unrealizedPnl = CommonRules.CalculateUnrealizedPnl(env, taxlot);

                    AccountToFrom fromToAccounts = null;

                    if (element.IsDerivative())
                    {
                        var originalAccount = AccountUtils.GetDerivativeAccountType(unrealizedPnl);
                        if (originalAccount.Contains("(Liabilities)"))
                        {
                            // This needs to be registered as a Credit to the Libabilities
                            unrealizedPnl *= -1;
                        }
                        fromToAccounts = new AccountUtils().GetAccounts(env, originalAccount, "Change in Unrealized Derivatives Contracts at Fair Value", listOfTags, taxlot.Trade);
                    }
                    else
                    {
                        var originalAccount = taxlot.Side == "SHORT" ? "Mark to Market Shorts" : "Mark to Market Longs";
                        fromToAccounts = new AccountUtils().GetAccounts(env, originalAccount, "CHANGE IN UNREALIZED GAIN/(LOSS)", listOfTags, taxlot.Trade);
                    }

                    var fund = env.GetFund(element);

                    var debit = new Journal(element)
                    {
                        Account     = fromToAccounts.From,
                        When        = env.ValueDate,
                        Symbol      = taxlot.Symbol,
                        Quantity    = quantity,
                        FxRate      = fxrate,
                        Value       = env.SignedValue(fromToAccounts.From, fromToAccounts.To, true, unrealizedPnl),
                        CreditDebit = env.DebitOrCredit(fromToAccounts.From, unrealizedPnl),
                        StartPrice  = prevEodPrice,
                        EndPrice    = eodPrice,
                        Event       = Event.DAILY_UNREALIZED_PNL,
                        Fund        = fund,
                    };

                    var credit = new Journal(element)
                    {
                        Account     = fromToAccounts.To,
                        When        = env.ValueDate,
                        FxRate      = fxrate,
                        Quantity    = quantity,
                        Value       = env.SignedValue(fromToAccounts.From, fromToAccounts.To, false, unrealizedPnl),
                        CreditDebit = env.DebitOrCredit(fromToAccounts.To, env.SignedValue(fromToAccounts.From, fromToAccounts.To, false, unrealizedPnl)),
                        Event       = Event.DAILY_UNREALIZED_PNL,
                        StartPrice  = prevEodPrice,
                        EndPrice    = eodPrice,
                        Fund        = fund,
                    };

                    Logger.Info($"[Journals] ==> From : {debit.CreditDebit}::{debit.Value}::{debit.Account.Type.Category.Name} --> To : {credit.CreditDebit}::{credit.Value}::{credit.Account.Type.Category.Name} ({unrealizedPnl})");

                    env.Journals.AddRange(new[] { debit, credit });

                    // For Derivatives this is un-necessary as we do not have an investment at cost, but we do have Fx on unsettled
                    if (taxlot.Quantity != 0.0)
                    {
                        if (element.TradeDate != env.ValueDate)
                        {
                            new FxPosting().CreateFxUnsettled(env, element);
                        }
                    }
                }
            }
            else
            {
                if (fxrate != 1.0)
                {
                    if (element.TradeDate != env.ValueDate && element.SettleDate >= env.ValueDate)
                    {
                        /*
                         * var fxJournals = FxPosting.CreateFx(
                         *  env,
                         *  "DUE FROM/(TO) PRIME BROKERS ( Unsettled Activity )",
                         *  "fx gain or loss on unsettled balance",
                         *  "daily",
                         *  element.Quantity, null, element);
                         * env.Journals.AddRange(fxJournals);
                         */
                    }
                }
            }
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Run for each day that the Tax Lot remains open / partially closed
        /// </summary>
        /// <param name="env"></param>
        /// <param name="element">Trade we aee interested in</param>
        public void DailyEvent(PostingEngineEnvironment env, Transaction element)
        {
            double fxrate = 1.0;

            // Lets get fx rate if needed
            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            // Calculate the unrealized PNL
            if (env.TaxLotStatus.ContainsKey(element.LpOrderId))
            {
                // Determine if we need to accumulate unrealized PNL
                var taxlot = env.TaxLotStatus[element.LpOrderId];

                // Check to see if the TaxLot is still open and it has a non zero Quantity
                if (!taxlot.Status.ToLowerInvariant().Equals("closed") && Math.Abs(taxlot.Quantity) > 0)
                {
                    var prevEodPrice = 0.0;
                    var eodPrice     = 0.0;
                    var fxRate       = 0.0;

                    if (element.TradeCurrency.Equals(env.BaseCurrency))
                    {
                        if (env.ValueDate == element.TradeDate)
                        {
                            prevEodPrice = 1 / element.SettleNetPrice;
                            fxRate       = FxRates.Find(env.ValueDate, element.SettleCurrency).Rate;
                            eodPrice     = fxRate;
                        }
                        else
                        {
                            prevEodPrice = FxRates.Find(env.PreviousValueDate, element.SettleCurrency).Rate;
                            fxRate       = FxRates.Find(env.PreviousValueDate, element.SettleCurrency).Rate;
                            eodPrice     = fxRate;
                        }
                    }
                    else
                    {
                        if (env.ValueDate == element.TradeDate)
                        {
                            prevEodPrice = element.SettleNetPrice;
                            fxRate       = FxRates.Find(env.ValueDate, element.TradeCurrency).Rate;
                            eodPrice     = fxRate;
                        }
                        else
                        {
                            prevEodPrice = FxRates.Find(env.PreviousValueDate, element.TradeCurrency).Rate;
                            fxRate       = FxRates.Find(env.ValueDate, element.TradeCurrency).Rate;
                            eodPrice     = fxRate;
                        }
                    }

                    var unrealizedPnl = 0.0;

                    var quantity = taxlot.Quantity;
                    var rateDiff = (eodPrice - prevEodPrice);

                    if (element.SettleCurrency.Equals(env.BaseCurrency))
                    {
                        unrealizedPnl = (rateDiff * quantity);
                    }
                    else
                    {
                        unrealizedPnl = (rateDiff * quantity) * fxRate;
                    }

                    var originalAccount = AccountUtils.GetDerivativeAccountType(unrealizedPnl);
                    var fromToAccounts  = new AccountUtils().GetAccounts(env, originalAccount, "Change in Unrealized Derivatives Contracts at Fair Value", listOfTags, taxlot.Trade);

                    var fund = env.GetFund(element);

                    var debit = new Journal(element)
                    {
                        Account     = fromToAccounts.From,
                        When        = env.ValueDate,
                        Symbol      = taxlot.Symbol,
                        Quantity    = quantity,
                        FxRate      = rateDiff,
                        Value       = env.SignedValue(fromToAccounts.From, fromToAccounts.To, false, unrealizedPnl),
                        CreditDebit = env.DebitOrCredit(fromToAccounts.From, unrealizedPnl),
                        StartPrice  = prevEodPrice,
                        EndPrice    = eodPrice,
                        Event       = Event.DAILY_UNREALIZED_PNL,
                        Fund        = fund,
                    };

                    var credit = new Journal(debit)
                    {
                        Account     = fromToAccounts.To,
                        Value       = env.SignedValue(fromToAccounts.From, fromToAccounts.To, true, unrealizedPnl),
                        CreditDebit = env.DebitOrCredit(fromToAccounts.To, unrealizedPnl),
                    };

                    env.Journals.AddRange(new[] { debit, credit });

                    if (element.TradeDate != env.ValueDate && element.SettleDate >= env.ValueDate)
                    {
                        var fxJournals = FxPosting.CreateFx(
                            env,
                            "daily",
                            quantity, null, element);
                        env.Journals.AddRange(fxJournals);
                    }
                }
            }
            else
            {
                if (fxrate != 1.0)
                {
                    if (element.TradeDate != env.ValueDate && element.SettleDate >= env.ValueDate)
                    {
                        var fxJournals = FxPosting.CreateFx(
                            env,
                            "daily",
                            element.Quantity, null, element);
                        env.Journals.AddRange(fxJournals);
                    }
                }
            }
        }
Ejemplo n.º 21
0
        internal static List <Journal> CreateFx(PostingEngineEnvironment env,
                                                string tradeEvent,
                                                double quantity,
                                                TaxLotStatus taxlotStatus,
                                                Transaction element)
        {
            if (tradeEvent.Equals(Event.TRADE_DATE))
            {
                return(new List <Journal>());
            }

            var riskCurrency = element.SettleCurrency;

            if (element.SecurityType.Equals("FORWARD"))
            {
                var split        = element.Symbol.Split(new char[] { '/', ' ' });
                var baseCurrency = split[0];
                riskCurrency = split[1];
            }

            // Check to see if the BaseCurrency == SettleCurrency because if it is then no need to do the FX translation
            if (env.BaseCurrency.Equals(riskCurrency))
            {
                return(new List <Journal>());
            }

            var prevEodFxRate = Convert.ToDouble(FxRates.Find(env.PreviousValueDate, riskCurrency).Rate);
            var eodFxRate     = Convert.ToDouble(FxRates.Find(env.ValueDate, riskCurrency).Rate);
            var effectiveRate = eodFxRate - prevEodFxRate;

            var usdEquivalent = element.Quantity * effectiveRate;

            var fromAccount = "Mark to Market Derivatives Contracts due to FX (Liabilities)";
            var toAccount   = "Change in Unrealized Derivatives Contracts due to FX";

            if (usdEquivalent > 0)
            {
                fromAccount = "Mark to Market Derivatives Contracts due to FX (Assets)";
            }

            // Get accounts
            var toFrom = new AccountUtils().GetAccounts(env, fromAccount, toAccount, _TAGS, element);

            var fund = env.GetFund(element);

            var debit = new Journal(element, toFrom.From, $"{tradeEvent}-unrealizedpnl-fx", env.ValueDate)
            {
                Quantity    = quantity,
                FxRate      = effectiveRate,
                StartPrice  = prevEodFxRate,
                FxCurrency  = riskCurrency,
                EndPrice    = eodFxRate,
                Fund        = fund,
                Value       = env.SignedValue(toFrom.From, toFrom.To, true, usdEquivalent),
                CreditDebit = env.DebitOrCredit(toFrom.From, usdEquivalent),
            };

            var credit = new Journal(element, toFrom.To, $"{tradeEvent}-unrealizedpnl-fx", env.ValueDate)
            {
                Quantity   = quantity,
                FxRate     = effectiveRate,
                FxCurrency = riskCurrency,
                StartPrice = prevEodFxRate,
                EndPrice   = eodFxRate,
                Fund       = fund,

                Value       = env.SignedValue(toFrom.From, toFrom.To, false, usdEquivalent),
                CreditDebit = env.DebitOrCredit(toFrom.To, usdEquivalent),
            };


            return(new List <Journal>(new[] { debit, credit }));
        }
Ejemplo n.º 22
0
        public void TradeDateEvent(PostingEngineEnvironment env, Transaction element)
        {
            double fxrate = 1.0;

            double multiplier = 1.0;

            if (env.SecurityDetails.ContainsKey(element.BloombergCode))
            {
                multiplier = env.SecurityDetails[element.BloombergCode].Multiplier;
            }

            // Lets get fx rate if needed
            if (!element.SettleCurrency.Equals(env.BaseCurrency))
            {
                fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate);
            }

            if (element.IsBuy() || element.IsShort())
            {
                var t1 = env.GenerateOpenTaxLot(element, fxrate);

                if (element.Quantity == 0)
                {
                    // TODO: Need to review this as we need to see if there is a parent, and what the parents actuall is
                    return;
                }
            }
            else if (element.IsSell() || element.IsCover())
            {
                // Get Matching Lots
                var openLots = env.Methodology.GetOpenLots(env, element, element.Quantity);

                if (openLots.Count() == 0)
                {
                    var t1 = env.GenerateOpenTaxLot(element, fxrate);
                    // Whats going on here?
                    // We are skipping anything that does not get an OpenLot
                    env.AddMessage($"There should be for a sell {element.Symbol} have at least one open lot, non found");
                }
                else
                {
                    var workingQuantity = element.Quantity;

                    foreach (var lot in openLots)
                    {
                        if (workingQuantity == 0)
                        {
                            break;
                        }

                        if (!env.TaxLotStatus.ContainsKey(lot.Trade.LpOrderId))
                        {
                            // TODO: For this open lot there should be a corresponding open to
                            continue;
                        }

                        var taxlotStatus = env.TaxLotStatus[lot.Trade.LpOrderId];
                        if (taxlotStatus != null && taxlotStatus.Quantity != 0 && !taxlotStatus.Status.ToLowerInvariant().Equals("closed"))
                        {
                            // Does the open Lot fully fullfill the quantity ?
                            if (Math.Abs(taxlotStatus.Quantity) >= Math.Abs(workingQuantity))
                            {
                                var taxlot = CommonRules.RelieveTaxLot(env, lot, element, workingQuantity, true);

                                taxlotStatus.Quantity += workingQuantity;
                                if (taxlotStatus.Quantity == 0)
                                {
                                    taxlotStatus.Status = "Closed";
                                }
                                else
                                {
                                    taxlotStatus.Status = "Partially Closed";
                                }

                                CommonRules.GenerateCloseOutPostings(env, lot, taxlot, element, taxlotStatus, env.GetFund(element));

                                break;
                            }
                            else
                            {
                                var taxlot = CommonRules.RelieveTaxLot(env, lot, element, taxlotStatus.Quantity * -1);

                                workingQuantity -= Math.Abs(taxlotStatus.Quantity);

                                var accountTypes = AccountType.All;

                                var listOfTags = new List <Tag> {
                                    Tag.Find("SecurityType"),
                                    Tag.Find("CustodianCode")
                                };

                                Account fromAccount = null; // Debiting Account
                                Account toAccount   = null; // Crediting Account

                                var realizedPnl = taxlot.RealizedPnl;

                                var originalAccount = AccountUtils.GetDerivativeAccountType(realizedPnl);
                                if (originalAccount.Contains("(Liabilities)"))
                                {
                                    // This needs to be registered as a Credit to the Libabilities
                                    realizedPnl *= -1;
                                }

                                var fromToAccounts = new AccountUtils().GetAccounts(env, originalAccount, "REALIZED GAIN/(LOSS)", listOfTags, taxlot.Trade);
                                fromAccount = fromToAccounts.From;
                                toAccount   = fromToAccounts.To;

                                var debitJournal = new Journal(element)
                                {
                                    Account     = fromAccount,
                                    When        = env.ValueDate,
                                    StartPrice  = taxlot.TradePrice,
                                    EndPrice    = taxlot.CostBasis,
                                    CreditDebit = env.DebitOrCredit(fromAccount, taxlot.RealizedPnl),
                                    Value       = env.SignedValue(fromAccount, toAccount, true, taxlot.RealizedPnl),
                                    FxRate      = fxrate,
                                    Event       = Event.REALIZED_PNL,
                                    Fund        = env.GetFund(element),
                                };

                                var creditJournal = new Journal(debitJournal)
                                {
                                    Account     = toAccount,
                                    CreditDebit = env.DebitOrCredit(toAccount, taxlot.RealizedPnl * -1),
                                    Value       = env.SignedValue(fromAccount, toAccount, false, taxlot.RealizedPnl),
                                };

                                env.Journals.AddRange(new[] { debitJournal, creditJournal });

                                taxlotStatus.Quantity = 0;
                                taxlotStatus.Status   = "Closed";
                            }
                        }
                    }
                }
            }
            else
            {
                // We have a Debit / Credit Dividends
            }
        }
        /// <summary>
        /// Get the open Tax lots for the specified trade passed in, general rule of thumb is that I will get a SELL or COVER which then
        /// is matched off against a BUY Or SHORT, but for some instrument types this rule is broken
        /// </summary>
        /// <param name="env"></param>
        /// <param name="element"></param>
        /// <returns></returns>
        public static List <TaxLotDetail> OpenTaxLots(PostingEngineEnvironment env, Transaction element, double workingQuantity)
        {
            var fund = env.GetFund(element);

            // TBD: DLG This may be wrong, as we do get Sells / Covers prior to a Buy or a Sell
            if (element.IsBuy() || element.IsShort())
            {
                return(new List <TaxLotDetail>());
            }

            var openLots = new List <TaxLotDetail>();

            // Need to ensure that we only get trades that are prior to this trade's trade time, and don't inlcude this trade
            var lots = env.Trades.Where(i =>
                                        i.TradeTime <= element.TradeTime &&
                                        i.Symbol == element.Symbol &&
                                        env.GetFund(i) == fund &&
                                        !i.Status.Equals("Cancelled") &&
                                        env.TaxLotsIsOpen(i) &&
                                        i.LpOrderId != element.LpOrderId);

            // We need to grab the opposite of the past trade
            if (element.IsSell())
            {
                var local = lots.Where(i => i.IsBuy())
                            .ToList();

                openLots.AddRange(local.Select(i => new TaxLotDetail {
                    Trade        = i,
                    TaxLotStatus = env.FindTaxLotStatus(i),
                    TaxRate      = env.TradeTaxRate(i)
                }));
            }
            else if (element.IsBuy())
            {
                var local = lots.Where(i => i.IsSell())
                            .ToList();

                openLots.AddRange(local.Select(i => new TaxLotDetail
                {
                    Trade        = i,
                    TaxLotStatus = env.FindTaxLotStatus(i),
                    TaxRate      = env.TradeTaxRate(i)
                }));
            }
            else if (element.IsCover())
            {
                var local = lots.Where(i => i.IsShort())
                            .ToList();

                openLots.AddRange(local.Select(i => new TaxLotDetail {
                    Trade        = i,
                    TaxLotStatus = env.FindTaxLotStatus(i),
                    TaxRate      = env.TradeTaxRate(i)
                }));
            }
            else if (element.IsShort())
            {
                var local = lots.Where(i => i.IsCover())
                            .ToList();

                openLots.AddRange(local.Select(i => new TaxLotDetail
                {
                    Trade        = i,
                    TaxLotStatus = env.FindTaxLotStatus(i),
                    TaxRate      = env.TradeTaxRate(i)
                }));
            }


            return(openLots);
        }
Ejemplo n.º 24
0
        public void SettlementDateEvent(PostingEngineEnvironment env, Transaction element)
        {
            // On Settlement Date we backout the Tax Lot for FORWARDS
            if (env.TaxLotStatus.ContainsKey(element.LpOrderId))
            {
                var taxlotStatus = env.TaxLotStatus[element.LpOrderId];

                var split        = element.Symbol.Split(new char[] { '/', ' ' });
                var baseCurrency = split[0];
                var riskCurrency = split[1];

                var accountBuy = new AccountUtils().CreateAccount(atSettledCash, new List <string> {
                    element.SecurityType, element.CustodianCode, baseCurrency
                });
                var accountSell = new AccountUtils().CreateAccount(atSettledCash, new List <string> {
                    element.SecurityType, element.CustodianCode, riskCurrency
                });

                new AccountUtils().SaveAccountDetails(env, accountBuy);
                new AccountUtils().SaveAccountDetails(env, accountSell);

                var fxCurrency   = riskCurrency;
                var tradePrice   = taxlotStatus.TradePrice;
                var baseQuantity = element.Quantity;

                var eodPrice = MarketPrices.GetPrice(env, env.ValueDate, element).Price;
                var fxRate   = FxRates.Find(env.ValueDate, fxCurrency).Rate;

                var buyValue  = baseQuantity * tradePrice * fxRate;
                var sellValue = baseQuantity * eodPrice * fxRate;

                if (element.IsBuy()) // BUY
                {
                    var realizedPnl = sellValue - buyValue;

                    var debit = new Journal(accountBuy, Event.SETTLED_CASH, env.ValueDate)
                    {
                        Source     = element.LpOrderId,
                        Fund       = env.GetFund(element),
                        FxCurrency = baseCurrency,
                        Symbol     = element.Symbol,
                        SecurityId = element.SecurityId,
                        Quantity   = Convert.ToDouble(element.Quantity),

                        FxRate     = tradePrice,
                        StartPrice = tradePrice,
                        EndPrice   = eodPrice,

                        Value       = env.SignedValue(accountBuy, accountSell, true, buyValue),
                        CreditDebit = env.DebitOrCredit(accountBuy, buyValue),
                    };

                    var credit = new Journal(accountSell, Event.SETTLED_CASH, env.ValueDate)
                    {
                        Source     = element.LpOrderId,
                        Fund       = env.GetFund(element),
                        FxCurrency = riskCurrency,
                        Symbol     = element.Symbol,
                        SecurityId = element.SecurityId,
                        Quantity   = Convert.ToDouble(element.Quantity),

                        FxRate     = tradePrice,
                        StartPrice = 0,
                        EndPrice   = 0,

                        Value       = env.SignedValue(accountBuy, accountSell, true, sellValue * -1),
                        CreditDebit = env.DebitOrCredit(accountSell, sellValue),
                    };

                    env.Journals.AddRange(new[] { credit, debit });

                    var originalAccount = AccountUtils.GetDerivativeAccountType(realizedPnl);

                    // Realized Pnl to go along with the Settled Cash
                    CommonRules.GenerateJournalEntry(env, element, listOfTags, realizedAccountType, Event.REALIZED_PNL, realizedPnl);

                    CommonRules.GenerateJournalEntries(env, element, listOfTags, originalAccount, "Change in Unrealized Derivatives Contracts at Fair Value", realizedPnl * -1);
                }
                else // SELL
                {
                    var realizedPnl = buyValue - sellValue;

                    var debit = new Journal(accountBuy, Event.SETTLED_CASH, env.ValueDate)
                    {
                        Source     = element.LpOrderId,
                        Fund       = env.GetFund(element),
                        FxCurrency = baseCurrency,
                        Symbol     = element.Symbol,
                        SecurityId = element.SecurityId,
                        Quantity   = Convert.ToDouble(element.Quantity),

                        FxRate     = tradePrice,
                        StartPrice = 0,
                        EndPrice   = 0,

                        Value       = env.SignedValue(accountBuy, accountSell, true, sellValue),
                        CreditDebit = env.DebitOrCredit(accountBuy, element.Quantity),
                    };

                    var credit = new Journal(accountSell, Event.SETTLED_CASH, env.ValueDate)
                    {
                        Source     = element.LpOrderId,
                        Fund       = env.GetFund(element),
                        FxCurrency = riskCurrency,
                        Symbol     = element.Symbol,
                        SecurityId = element.SecurityId,
                        Quantity   = Convert.ToDouble(element.Quantity),

                        FxRate     = tradePrice,
                        StartPrice = 0,
                        EndPrice   = 0,

                        Value       = env.SignedValue(accountBuy, accountSell, true, buyValue * -1),
                        CreditDebit = env.DebitOrCredit(accountSell, element.Quantity),
                    };

                    env.Journals.AddRange(new[] { credit, debit });

                    var originalAccount = AccountUtils.GetDerivativeAccountType(realizedPnl);

                    // Realized Pnl to go along with the Settled Cash
                    CommonRules.GenerateJournalEntry(env, element, listOfTags, realizedAccountType, Event.REALIZED_PNL, realizedPnl);

                    CommonRules.GenerateJournalEntries(env, element, listOfTags, originalAccount, "Change in Unrealized Derivatives Contracts at Fair Value", realizedPnl * -1);
                }

                if (taxlotStatus.Quantity != 0)
                {
                    var buyTrade = env.FindTrade(taxlotStatus.OpenId);
                    var taxlot   = CommonRules.RelieveTaxLot(env, buyTrade, element, taxlotStatus.Quantity * -1, true);
                    taxlotStatus.Quantity = 0;
                    taxlotStatus.Status   = "Closed";
                }
            }
        }