コード例 #1
0
        public static MarketPrice GetPrice(PostingEngineEnvironment env, DateTime valueDate, Transaction element)
        {
            var eodMarketPrice = Find(valueDate, element);

            if (!eodMarketPrice.Valid)
            {
                env.AddMessage(eodMarketPrice.Error);
            }

            return(eodMarketPrice);
        }
コード例 #2
0
        /// <summary>
        /// Calcualte the Unrealized Pnl for this Tax lot
        /// </summary>
        /// <param name="env"></param>
        /// <returns></returns>
        public static double CalculateUnrealizedPnl(PostingEngineEnvironment env, TaxLotStatus taxLotStatus, double residualQuantity = 0, double endPrice = 0)
        {
            double multiplier = 1.0;

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

            double fxrate = 1.0;

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

            var eodPrice     = 0.0;
            var prevEodPrice = 0.0;

            if (env.ValueDate == taxLotStatus.Trade.TradeDate)
            {
                prevEodPrice = taxLotStatus.Trade.SettleNetPrice;
                var eodMarketPrice = MarketPrices.GetPrice(env, env.ValueDate, taxLotStatus.Trade);

                if (!eodMarketPrice.Valid)
                {
                    env.AddMessage(eodMarketPrice.Error);
                }

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

            eodPrice = endPrice != 0 ? endPrice : eodPrice;

            // Use residual Quantity if specified
            var quantity = residualQuantity != 0.0 ? residualQuantity : taxLotStatus.Quantity;

            var priceDiff = (eodPrice - prevEodPrice);

            var unrealizedPnl = priceDiff * quantity;

            return(unrealizedPnl * fxrate * multiplier);
        }
コード例 #3
0
        public bool IsValid(PostingEngineEnvironment env, Transaction element)
        {
            if (element.AccrualId == null)
            {
                return(true);
            }

            var validAccrual = env.IsValidAccrual(element.AccrualId);

            if (!validAccrual)
            {
                env.AddMessage($"trade does not tie back to a valid accrual {element.AccrualId}");
            }
            return(validAccrual);
        }
コード例 #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);
        }
コード例 #5
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);
            }

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

            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;
                }

                //tl.Save(env.Connection, env.Transaction);
            }
            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, tradeAllocations[0].Fund);

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

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

                                CommonRules.PostRealizedPnl(env, element, taxlot.RealizedPnl, taxlot.TradePrice, taxlot.CostBasis);

                                taxlotStatus.Quantity = 0;
                                taxlotStatus.Status   = "Closed";
                            }
                        }
                    }
                }
            }
            else
            {
                // We have a Debit / Credit Dividends
            }
        }
コード例 #6
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;
        }
コード例 #7
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;
        }
コード例 #8
0
        internal void TradeDateEvent(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);
            }


            if (element.IsCredit() || element.IsDebit())
            {
                if (element.TransactionCategory == "Cash Dividends")
                {
                    // We have a Cash Dividend, so how do we treat this
                    return;
                }
            }

            if (element.IsBuy() || element.IsShort())
            {
                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;
                }

                var tl = env.GenerateOpenTaxLot(element, fxrate);
            }
            else if (element.IsSell() || element.IsCover())
            {
                // Get Matching Lots
                var taxLotMethodology = ConfigurationManager.AppSettings["TaxMethod"].ToString();

                var workingQuantity = element.Quantity;
                if (taxLotMethodology.Equals("MINTAX"))
                {
                    while (workingQuantity != 0.0)
                    {
                        var localOpenTaxLots = env.Methodology.GetOpenLots(env, element, workingQuantity);

                        var lot = localOpenTaxLots[0];

                        if (!env.TaxLotStatus.ContainsKey(lot.Trade.LpOrderId))
                        {
                            // TODO: For this open lot there should be a corresponding open to
                            env.AddMessage($"Unable to Find Tax Lot for {lot.Trade.Symbol}::{lot.Trade.Side}::{lot.Trade.Status}");
                            //Logger.Warn($"Unable to Find Tax Lot for {element.Symbol}::{element.Side}::{element.Status}");
                            continue;
                        }

                        var taxlotStatus = env.TaxLotStatus[lot.Trade.LpOrderId];
                        if (taxlotStatus != null && taxlotStatus.Quantity != 0 && !taxlotStatus.Status.ToLowerInvariant().Equals("closed"))
                        {
                            Logger.Info($"Relieving Tax Lot {taxlotStatus.Symbol}::{taxlotStatus.TradePrice}::{taxlotStatus.TradeDate.ToString("MM-dd-yyyy")}::{taxlotStatus.OpenId}::{lot.TaxLiability}::{lot.TaxRate.Rate}::{lot.PotentialPnl}");

                            // Does the open Lot fully fullfill the quantity ?
                            if (Math.Abs(taxlotStatus.Quantity) >= Math.Abs(workingQuantity))
                            {
                                // Lets generate all the journal entries we need
                                GenerateJournals(env, lot, taxlotStatus, element, workingQuantity, fxrate, multiplier);

                                break;
                            }
                            else
                            {
                                var quantity = taxlotStatus.Quantity;

                                GenerateJournals(env, lot, taxlotStatus, element, taxlotStatus.Quantity * -1, fxrate, multiplier);

                                workingQuantity += quantity;
                            }
                        }
                    }
                }
                else
                {
                    var openLots = env.Methodology.GetOpenLots(env, element, workingQuantity);

                    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
                            env.AddMessage($"Unable to Find Tax Lot for {lot.Trade.Symbol}::{lot.Trade.Side}::{lot.Trade.Status}");
                            //Logger.Warn($"Unable to Find Tax Lot for {element.Symbol}::{element.Side}::{element.Status}");
                            continue;
                        }

                        var taxlotStatus = env.TaxLotStatus[lot.Trade.LpOrderId];
                        if (taxlotStatus != null && taxlotStatus.Quantity != 0 && !taxlotStatus.Status.ToLowerInvariant().Equals("closed"))
                        {
                            Logger.Info($"Relieving Tax Lot {taxlotStatus.TradeDate.ToString("MM-dd-yyyy")}::{taxlotStatus.Symbol}::{taxlotStatus.OpenId}::{lot.TaxLiability}::{lot.TaxRate.Rate}::{lot.PotentialPnl}");

                            // Does the open Lot fully fullfill the quantity ?
                            if (Math.Abs(taxlotStatus.Quantity) >= Math.Abs(workingQuantity))
                            {
                                // Lets generate all the journal entries we need
                                GenerateJournals(env, lot, taxlotStatus, element, workingQuantity, fxrate, multiplier);

                                break;
                            }
                            else
                            {
                                var quantity = taxlotStatus.Quantity;

                                GenerateJournals(env, lot, taxlotStatus, element, taxlotStatus.Quantity * -1, fxrate, multiplier);

                                workingQuantity += quantity;
                            }
                        }
                    }
                }
            }
            else
            {
                // We have a Debit / Credit Dividends
            }

            CommonRules.GenerateTradeDateJournals(env, element);
        }
コード例 #9
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
            }
        }
コード例 #10
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 });
            }
        }
コード例 #11
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 });
            }
        }