private Product GetProduct(SymmetryInfo info)
        {


            if (info.SecurityType.ToLowerInvariant() == "bonds")
            {
                var pr = Env.Current.Trade.GetProductByDescription(info.Security);
                if (pr != null) return pr;
                if (!Utilities.IsNullOrEmpty(info.Cusip))
                {
                    pr = Env.Current.Trade.GetProductByCode(Product.CusipProductCode, info.Cusip);
                    if (pr != null) return pr;
                }
                var ccys = new List<string> { info.Currency };
                var allBonds = Env.Current.Trade.LoadBondProducts(null, null, null, 0, ccys, -1, info.Coupon,
                                                                  info.Coupon, null, null, SimpleDate.Today, false,
                                                                  false, null, null);
                if (allBonds != null)
                {
                    foreach (var v in allBonds)
                    {
                        var bd = v as Bond;
                        if (bd == null) continue;
                        if (Math.Abs(bd.FixedRate - info.Coupon) < Utilities.Epsilon && bd.MaturityDate == info.Maturity)
                        {
                           if (!StatusDisabled.Equals(bd.Status)) return bd;
                        }
                    }
                }

                throw new Exception("Bonds " + info.Security + " not retrieved");
            }
            if (info.SecurityType.ToLower() == "currency")
            {
                return null;
            }
            if (info.SecurityType == "Caps/Floors")
            {

            }
            if (info.SecurityType.ToLower() == "currency swaps")
            {
                return null;
            }
            if (info.SecurityType.ToLower() == "interest rate swaps")
            {
                return null;
            }
            if (info.SecurityType.ToLower() == "swaptions")
            {
                return null;
            }
            if (info.SecurityType.ToLower() == "fras")
            {
                return null;
            }
            //Fx Vol Swap
            if (info.SecurityType.ToLower() == "flexible deal" && info.Security.Contains("VOLSWAP"))
            {
                //GBP/USD VOLSWAP 5.925 04 Dec 2014 (02 Sep 2014-02 Dec 2014)
                //USD/JPY VOLSWAP 8.05 17 Nov 2014 (12 Sep 2014-13 Nov 2014)
                var volswap = new VolSwap();
                var desc = info.Security.Split(' ');
                var cpl = desc[0].Split('/');
                var cp = Env.Current.Trade.GetCurrencyPair(cpl[0], cpl[1]);
                volswap.Underlier = cp;
                volswap.UnderlierId = cp.Id;
                volswap.EndDate = info.Maturity;
                volswap.Notional = Math.Abs(info.CurrentDayPosition/100);
                volswap.IsBuy = info.CurrentDayPosition > 0;
                volswap.PaymentCurrency = info.Currency;
                if (desc.Length > 2)
                {
                    double strike;
                    if (double.TryParse(desc[2], out strike))
                        volswap.Strike = strike;
                }
                return volswap;
            }
            //FX Option
            if (info.SecurityType.ToLower() == "simple option" || info.SecurityType.ToLower() == "simple barrier"
                || info.SecurityType.ToLower() == "touch rebate" || info.SecurityType.ToLower() == "flexible deal"
                || info.SecurityType.ToLower() == "double barrier")
            {
                // EUR/USD 1.3204 CALL (26 Nov 2014)
                var fxoption = info.SecurityType.ToLower() == "flexible deal" ?
                    new FxFva { FvaExpiryDate = info.Maturity } : new FXOption { ExpiryDate = info.Maturity };
                var desc = info.Security.Split(' ');
                var cpl = desc[0].Split('/');
                fxoption.Primary = cpl[0];
                fxoption.Quoting = cpl[1];
                if (!(fxoption is FxFva))
                    fxoption.OptionStrike = Convert.ToDouble(desc[1], CultureInfo.InvariantCulture);
                fxoption.PrimaryAmount = Math.Abs(info.CurrentDayPosition);
                fxoption.QuotingAmount = fxoption.PrimaryAmount * fxoption.OptionStrike;
                if (info.Security.Contains("CALL ")) fxoption.OptionType = OptionType.Call;
                else if (info.Security.Contains("PUT ")) fxoption.OptionType = OptionType.Put;
                else fxoption.OptionType = OptionType.None;
                if (info.CurrentDayPosition > 0)
                {
                    fxoption.IsBuy = true;
                    fxoption.QuotingAmount = -fxoption.QuotingAmount;
                }
                else
                {
                    fxoption.IsBuy = false;
                    fxoption.PrimaryAmount = -fxoption.PrimaryAmount;
                }
                fxoption.ExerciseType = OptionExerciseType.European;

                if (info.SecurityType.ToLower() == "flexible deal")
                {
                    // EUR/USD FVA 0 25 Feb 2015 (21 Nov 2014-23 Feb 2015)
                    var fva = fxoption as FxFva;
                    if (fva != null)
                        fva.Volatility = Convert.ToDouble(desc[2], CultureInfo.InvariantCulture) / 100;
                }
                else if (info.SecurityType.ToLower() == "simple barrier")
                {
                    // USD/CNY 6.16 PUT 16 Dec 2014 DO 6.07
                    // USD/SGD 1.265 CALL 24 Sep 2014 UI 1.2725
                    fxoption.ExerciseType = OptionExerciseType.Barrier;
                    var binfo = new BarrierInfo();
                    fxoption.OptionInfo = binfo;
                    var len = desc.Length;
                    var barrierType = desc[len - 2];
                    var barrierStrike = desc[len - 1];
                    if (barrierType.StartsWith("D"))
                    {
                        if (barrierType.EndsWith("I"))
                            binfo.LowerBarrierType = OptionBarrierType.KnockIn;
                        else
                            binfo.LowerBarrierType = OptionBarrierType.KnockOut;
                        binfo.LowerBarrierStrike = double.Parse(barrierStrike);
                    }
                    else
                    {
                        if (barrierType.EndsWith("I"))
                            binfo.BarrierType = OptionBarrierType.KnockIn;
                        else
                            binfo.BarrierType = OptionBarrierType.KnockOut;
                        binfo.BarrierStrike = double.Parse(barrierStrike);
                    }

                }
                else if (info.SecurityType.ToLower() == "double barrier")
                {
                    // USD/JPY 105 CALL 18 Dec 2014 KO 108 101
                    fxoption.ExerciseType = OptionExerciseType.Barrier;
                    var binfo = new BarrierInfo();
                    fxoption.OptionInfo = binfo;
                    var len = desc.Length;
                    var barrierType = desc[len - 3];
                    var barrierStrike1 = desc[len - 1];
                    var barrierStrike2 = desc[len - 2];
                    if (barrierType.Equals("KO"))
                    {
                        binfo.BarrierType = OptionBarrierType.KnockIn;
                        binfo.LowerBarrierType = OptionBarrierType.KnockIn;
                    }
                    else
                    {
                        binfo.BarrierType = OptionBarrierType.KnockOut;
                        binfo.LowerBarrierType = OptionBarrierType.KnockOut;
                    }
                    double strike1, strike2;
                    if (double.TryParse(barrierStrike1, out strike1))
                        binfo.BarrierStrike = strike1;
                    if (double.TryParse(barrierStrike2, out strike2))
                        binfo.LowerBarrierStrike = strike2;
                    if (binfo.BarrierStrike < binfo.LowerBarrierStrike)
                    {
                        var temp = binfo.BarrierStrike;
                        binfo.BarrierStrike = binfo.LowerBarrierStrike;
                        binfo.LowerBarrierStrike = temp;
                    }
                }
                else if (info.SecurityType.ToLower() == "touch rebate")
                {
                    // USD/MXN 13.45  10 Sep 2014 UO 13.45
                    // USD/CAD 1.105  12 Sep 2014 KI 1.105 1.082
                    // GBP/USD 1.59  04 Nov 2014 DO 1.59
                    // for touch, please only compare strikes
                    fxoption.ExerciseType = OptionExerciseType.Touch;
                    var tinfo = new DigitalInfo();
                    fxoption.OptionInfo = tinfo;
                    var len = desc.Length;
                    double strike1, strike2;
                    if (double.TryParse(desc[len - 2], out strike1))
                        tinfo.BarrierStrike = strike1;
                    if (double.TryParse(desc[len - 1], out strike2))
                        tinfo.LowerBarrierStrike = strike2;
                    if (tinfo.BarrierStrike < tinfo.LowerBarrierStrike)
                    {
                        var temp = tinfo.BarrierStrike;
                        tinfo.BarrierStrike = tinfo.LowerBarrierStrike;
                        tinfo.LowerBarrierStrike = temp;
                    }
                }
                return fxoption;
            }
            if (info.SecurityType.ToLower().Contains("futures") || info.SecurityType.ToLower().Contains("future options"))
            {
                var pr = Env.Current.Trade.GetProductByCode(Product.DefaultTicker, info.Security.Trim());
                if (pr != null) return pr;
                if (!info.SecurityType.ToLower().Equals("equity futures"))
                    pr = Env.Current.Trade.GetProductByCode(Product.DefaultTicker, info.Security.Trim() + " Comdty");
                if (pr != null) return pr;
                if (!info.SecurityType.ToLower().Equals("equity futures"))
                    pr = Env.Current.Trade.GetProductByCode(Product.DefaultTicker, info.Security.Trim() + " Curncy");
                if (pr != null) return pr;
                pr = Env.Current.Trade.GetProductByCode(Product.DefaultTicker, info.Security.Trim() + " Index");
                if (pr != null) return pr;
                pr = Env.Current.Trade.GetProductByCode(Product.DefaultTicker, info.Security.Trim() + " Equity");
                if (pr != null) return pr;
                throw new Exception("Futures " + info.SecurityType + " " + info.Security + " not retrieved");
            }


            if (info.SecurityType.ToLower() == "spot-forward")
            {
                var fx = new FX();
                var splits = info.Security.Substring(0, 7).Split('/');
                string ccy1 = splits[0];
                string ccy2 = splits[1];
                var cp = Env.Current.Trade.GetCurrencyPair(ccy1, ccy2);
                if (cp == null) return null;
                fx.Primary = cp.Primary;
                fx.Quoting = cp.Quoting;
                var settleDate = info.Maturity;
                fx.PrimarySettleDate = settleDate;
                fx.QuotingSettleDate = settleDate;

                /*
                var ccy2Obj = Env.Current.StaticData.GetCurrency(ccy2);
                if (ccy2Obj != null && ccy2Obj.IsNonDeliverable)
                {
                    var ndf = new NDF
                        {
                            Primary = cp.Primary,
                            Quoting = cp.Quoting,
                            PrimarySettleDate = settleDate,
                            QuotingSettleDate = settleDate
                        };
                    return ndf;
                }*/

                return fx;

            }
            throw new Exception("Reconciliation not supported for Product" + info.SecurityType.ToLower());
        }
        public Trade FromString(string[] items, IDictionary<string, int> headers, IList<Exception> exceps, Market market, CultureInfo info, SimpleDate asOfDate)
        {
            var symInfo = new SymmetryInfo(items, headers, info);



            //Ignore Currency
            if (symInfo.SecurityType.ToLower() == "currency") return null;
            //if (symInfo.Maturity <= asOfDate) return null;
            //if (symInfo.SecurityType.ToLower() != "spot-forward")
            {
                if (Math.Abs(symInfo.CurrentDayPosition - 0) < Utilities.Epsilon) return null;
            }


            var trade = new Trade();
            //Build Security
            Product product = null;
            try
            {
                product = GetProduct(symInfo);

            }
            catch (Exception x)
            {
                Logger.Error(x.Message);
                exceps.Add(
                    new Exception("No Product retrieved for Security Code:" + symInfo.SecurityType + "/" +
                                  symInfo.Security));

            }

            var pr = new SymmetryProduct();
            if (product != null)
            {

                trade.PriceType = QuotationType.Price;
                if (product.QuoteName != null)
                    trade.PriceType = product.QuoteName.QuoteType;

                if (product is FX)
                {
                    var fx = product as FX;
                    double dd = symInfo.CurrentDayPosition;
                    if (symInfo.Currency == "USD")
                    {
                        if (fx.Primary == "USD")
                        {
                            fx.PrimaryAmount = dd;
                            if (dd > 0) trade.Quantity = 1;
                            else trade.Quantity = -1;

                        }
                        else if (fx.Quoting == "USD")
                        {
                            fx.PrimaryAmount = dd;
                            if (dd < 0) trade.Quantity = 1;
                            else trade.Quantity = -1;
                        }

                    }
                    else
                    {
                        if (symInfo.Currency == fx.Quoting)
                        {
                            fx.QuotingAmount = dd;
                            if (dd < 0) trade.Quantity = 1;
                            else trade.Quantity = -1;
                        }
                        else if (symInfo.Currency == fx.Primary)
                        {
                            fx.PrimaryAmount = dd;
                            trade.Quantity = dd;
                        }
                    }
                    fx.PrimarySettleDate = symInfo.Maturity;
                    fx.QuotingSettleDate = symInfo.Maturity;
                    trade.SettlementDate = symInfo.Maturity;
                    pr = null;
                }
                else if (product is FXOption)
                {
                    trade.SetProperty(DPEDescription, symInfo.Security);
                    pr = null;
                }
                else if (product is VolSwap)
                    pr = null;
                else if (product.IsMultiplyTraded) pr = null;

            }
            if (pr != null)
            {

                pr.DetailQuantity = symInfo.CurrentDayPosition;
                pr.DetailCurrCode = symInfo.Currency;
                pr.Security = string.IsNullOrEmpty(symInfo.Security) ?
                    symInfo.Currency + "|" + symInfo.SecurityType + "|" + symInfo.Maturity : symInfo.Security;
                pr.SecurityType = symInfo.SecurityType;
                pr.MaturityDate = symInfo.Maturity;
                if (pr.Security == null) pr.Security = "Unknown";
                if (symInfo.SecurityType != null && symInfo.SecurityType.ToLowerInvariant().Equals("swaptions"))
                {
                    var desc = pr.Security.Split(' ');
                    for (int i = 0; i < desc.Length; i++)
                    {
                        if (desc[i] == "PAY" || desc[i] == "REC")
                        {
                            var strikes = desc[i + 1];
                            pr.Strike = Convert.ToDouble(strikes, CultureInfo.InvariantCulture) / 100;
                            break;
                        }
                    }
                }
                if (pr.Generator != null)
                    trade.SetProperty("Generator", pr.Generator);

            }
            trade.Product = product;
            if (pr != null) trade.Product = pr;

            trade.SettleCurrency = symInfo.Currency;
            if (!(trade.Product is FX))
            {
                trade.Quantity = symInfo.CurrentDayPosition;
                if (trade.Product is Mbs)
                {
                    trade.Quantity /= ((Mbs)trade.Product).GetPrincipalFactorAsOf(asOfDate, asOfDate);
                }
                else if (trade.Product is Bond)
                {
                    trade.Quantity /= ((Bond)trade.Product).Nominal;
                }
                else if (trade.Product is VolSwap)
                {
                    trade.Quantity /= 100;
                }
            }
            trade.SetProperty(ImportRef, symInfo.Security);
            //trade.SettleAmount = Convert.ToDouble(items[DetailLocalCost]);
            //Retrieve Book
            var ss = symInfo.MicroStrategy;
            string bookCode;
            if (Utilities.IsNullOrEmpty(ss))
            {
                var traderName = Env.Current.StaticData.GetAlias(new Alias
                    {
                        EntityId = 0,
                        AliasType = PortfolioAliasType,
                        Source = Source,
                        SourceReference = symInfo.Trader
                    });
                if (traderName != null)
                    bookCode = EntityPrefix + ":" + traderName.Name + ":" + "Default";
                else
                    bookCode = EntityPrefix + ":Default";
            }
            else
            {
                bookCode = EntityPrefix + ":" + ss;
            }
            var book = Env.Current.StaticData.GetPartyByCode(bookCode);
            if (book != null)
            {
                trade.BookId = book.Id;
            }

            return trade;

        }