// parses the additional GenericSecurityPosition information
        internal static Position parseNonEtdPosition(CsvRow row, PositionInfo info, PositionCsvInfoResolver resolver)
        {
            SecurityPosition    @base        = parseSecurityPosition(row, info, resolver);
            double?             tickSizeOpt  = row.findValue(TICK_SIZE).map(str => LoaderUtils.parseDouble(str));
            Optional <Currency> currencyOpt  = row.findValue(CURRENCY).map(str => Currency.of(str));
            double?             tickValueOpt = row.findValue(TICK_VALUE).map(str => LoaderUtils.parseDouble(str));
            double              contractSize = row.findValue(CONTRACT_SIZE).map(str => LoaderUtils.parseDouble(str)).orElse(1d);

            if (tickSizeOpt.HasValue && currencyOpt.Present && tickValueOpt.HasValue)
            {
                SecurityPriceInfo priceInfo = SecurityPriceInfo.of(tickSizeOpt.Value, CurrencyAmount.of(currencyOpt.get(), tickValueOpt.Value), contractSize);
                GenericSecurity   sec       = GenericSecurity.of(SecurityInfo.of(@base.SecurityId, priceInfo));
                return(GenericSecurityPosition.ofLongShort(@base.Info, sec, @base.LongQuantity, @base.ShortQuantity));
            }
            return(@base);
        }
        // parses a trade from the CSV row
        internal static SecurityQuantityTrade parseTrade(CsvRow row, TradeInfo info, TradeCsvInfoResolver resolver)
        {
            SecurityTrade trade = parseSecurityTrade(row, info, resolver);
            SecurityTrade @base = resolver.completeTrade(row, trade);

            double?tickSizeOpt = row.findValue(TICK_SIZE).map(str => LoaderUtils.parseDouble(str));
            Optional <Currency> currencyOpt = row.findValue(CURRENCY).map(str => Currency.of(str));
            double?tickValueOpt             = row.findValue(TICK_VALUE).map(str => LoaderUtils.parseDouble(str));
            double contractSize             = row.findValue(CONTRACT_SIZE).map(str => LoaderUtils.parseDouble(str)).orElse(1d);

            if (tickSizeOpt.HasValue && currencyOpt.Present && tickValueOpt.HasValue)
            {
                SecurityPriceInfo priceInfo = SecurityPriceInfo.of(tickSizeOpt.Value, CurrencyAmount.of(currencyOpt.get(), tickValueOpt.Value), contractSize);
                GenericSecurity   sec       = GenericSecurity.of(SecurityInfo.of(@base.SecurityId, priceInfo));
                return(GenericSecurityTrade.of(@base.Info, sec, @base.Quantity, @base.Price));
            }
            return(@base);
        }
        // parse an FxSingle
        internal static FxSingle parseFxSingle(CsvRow row, string prefix)
        {
            PayReceive direction1   = LoaderUtils.parsePayReceive(row.getValue(prefix + LEG_1_DIRECTION_FIELD));
            Currency   currency1    = Currency.of(row.getValue(prefix + LEG_1_CURRENCY_FIELD));
            double     notional1    = LoaderUtils.parseDouble(row.getValue(prefix + LEG_1_NOTIONAL_FIELD));
            LocalDate  paymentDate1 = row.findValue(prefix + LEG_1_PAYMENT_DATE_FIELD).map(str => LoaderUtils.parseDate(str)).orElseGet(() => LoaderUtils.parseDate(row.getValue(prefix + PAYMENT_DATE_FIELD)));
            PayReceive direction2   = LoaderUtils.parsePayReceive(row.getValue(prefix + LEG_2_DIRECTION_FIELD));
            Currency   currency2    = Currency.of(row.getValue(prefix + LEG_2_CURRENCY_FIELD));
            double     notional2    = LoaderUtils.parseDouble(row.getValue(prefix + LEG_2_NOTIONAL_FIELD));
            LocalDate  paymentDate2 = row.findValue(prefix + LEG_2_PAYMENT_DATE_FIELD).map(str => LoaderUtils.parseDate(str)).orElseGet(() => LoaderUtils.parseDate(row.getValue(prefix + PAYMENT_DATE_FIELD)));
            Optional <BusinessDayAdjustment> paymentAdj = parsePaymentDateAdjustment(row);

            if (direction1.Equals(direction2))
            {
                throw new System.ArgumentException(Messages.format("FxSingle legs must not have the same direction: {}, {}", direction1.ToString(), direction2.ToString()));
            }
            Payment payment1 = Payment.of(currency1, direction1.normalize(notional1), paymentDate1);
            Payment payment2 = Payment.of(currency2, direction2.normalize(notional2), paymentDate2);

            return(paymentAdj.map(adj => FxSingle.of(payment1, payment2, adj)).orElseGet(() => FxSingle.of(payment1, payment2)));
        }