public void WhatIfTest1()
        {
            PortfolioSetup testSetupParams = new PortfolioSetup(PortfolioDirection.LongShort, PortfolioMarginType.RegTMargin, 10000, new DateTime(2019, 11, 18));
            Portfolio      testPortfolio   = new Portfolio(testSetupParams);
            var            testSec         = testSecurity1();

            var testTrade1 = testTradeBuy(testSec);
            var testTrade2 = testTradeBuy(testSec);

            var balance = testSetupParams.InitialCashBalance;

            // Valid monday with full trading week
            DateTime date = new DateTime(2019, 11, 18);

            var tradeBar = testSec.GetPriceBar(date, true);

            tradeBar.SetPriceValues(10m, 15m, 5m, 12m);

            testTrade1.MarkExecuted(date, 10.0m);
            testPortfolio.AddExecutedTrade(testTrade1);

            var portCopy = testPortfolio.Copy();

            testTrade2.MarkExecuted(date, 15.0m);
            portCopy.AddExecutedTrade(testTrade2);

            Assert.AreNotEqual(testPortfolio.StockValue(date, TimeOfDay.MarketEndOfDay), portCopy.StockValue(date, TimeOfDay.MarketEndOfDay));

            //portCopy.ToStringAllActivity(date).ForEach(x => Console.WriteLine(x));

            //var log = portCopy.ToStringAllAccounting(date);
            //log.AddRange(portCopy.ToStringAllActivity(date));

            //OutputToTextFile(log);
        }
Пример #2
0
        private Portfolio testPortfolio(decimal startingBalance)
        {
            PortfolioSetup setup = new PortfolioSetup(PortfolioDirection.LongOnly,
                                                      PortfolioMarginType.RegTMargin,
                                                      startingBalance,
                                                      new DateTime(2019, 11, 20));

            return(new Portfolio(setup));
        }
Пример #3
0
        public Portfolio(IEnvironment environment, PortfolioSetup portfolioSetup, Strategy strategy)
        {
            Environment    = environment ?? throw new ArgumentNullException(nameof(environment));
            PortfolioSetup = portfolioSetup ?? throw new ArgumentNullException(nameof(portfolioSetup));
            Strategy       = strategy ?? throw new ArgumentNullException(nameof(strategy));

            Positions     = new List <Position>();
            PendingTrades = new List <Trade>();

            // Set initial value in PriorSMA for portfolio inception date
            PriorSmaValues.Add(Calendar.PriorTradingDay(portfolioSetup.InceptionDate), portfolioSetup.InitialCashBalance);
        }
Пример #4
0
        /// <summary>
        /// Returns a new, initialized portfolio manager
        /// </summary>
        /// <returns></returns>
        private PortfolioManager testPm()
        {
            DataManager dataManager = new DataManager(
                new InteractiveBrokersDataprovider(4002),
                new PriceDatabase());

            PortfolioSetup portfolioSetup = new PortfolioSetup(
                PortfolioDirection.LongOnly,
                PortfolioMarginType.RegTMargin,
                10000m,
                true,
                new DateTime(2015, 1, 2));

            IEnvironment ibkrEnvironment = new IbkrEnvironment();

            ibkrEnvironment.PositionManagementRulesPipeline.AppendRule(
                new Finance.Rules.PositionManagementRule_LiquidityCheck());

            ibkrEnvironment.PositionManagementRulesPipeline.AppendRule(
                new Finance.Rules.PositionManagementRule_StoplossUpdate());

            ibkrEnvironment.PositionManagementRulesPipeline.AppendRule(
                new Finance.Rules.PositionManagementRule_PositionScaling());

            ibkrEnvironment.PreTradeApprovalRulesPipeline.AppendRule(
                new Finance.Rules.TradePreApprovalRule_1());

            ibkrEnvironment.PreTradeApprovalRulesPipeline.AppendRule(
                new Finance.Rules.TradePreApprovalRule_2());

            ibkrEnvironment.PreTradeApprovalRulesPipeline.AppendRule(
                new Finance.Rules.TradePreApprovalRule_3());

            ibkrEnvironment.PreTradeApprovalRulesPipeline.AppendRule(
                new Finance.Rules.TradePreApprovalRule_4());

            ibkrEnvironment.TradeExecutionApprovalRulesPipeline.AppendRule(
                new Finance.Rules.TradeApprovalRule_1());

            ibkrEnvironment.TradeExecutionApprovalRulesPipeline.AppendRule(
                new Finance.Rules.TradeApprovalRule_2());

            ibkrEnvironment.TradeExecutionApprovalRulesPipeline.AppendRule(
                new Finance.Rules.TradeApprovalRule_3());

            Strategy strategy = new Strategy_HighBreakoutLongAtrRisk();

            return(new PortfolioManager(dataManager, portfolioSetup, ibkrEnvironment, strategy));
        }
        public void EmptyPortfolioAccounting()
        {
            PortfolioSetup testSetupParams = new PortfolioSetup(PortfolioDirection.LongShort, PortfolioMarginType.RegTMargin, 10000, new DateTime(2019, 11, 18));
            Portfolio      testPortfolio   = new Portfolio(testSetupParams);

            DateTime AsOf    = new DateTime(2019, 11, 18);
            decimal  balance = testSetupParams.InitialCashBalance;

            Assert.AreEqual(balance, testPortfolio.TotalCashValue(AsOf));

            Assert.AreEqual(0, testPortfolio.TotalCashPurchasesAndProceeds(AsOf));

            Assert.AreEqual(0, testPortfolio.TotalCommissions(AsOf));

            Assert.AreEqual(0, testPortfolio.StockValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.LongStockValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.ShortStockValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.LongOptionValue(AsOf, TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0, testPortfolio.ShortOptionValue(AsOf, TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0, testPortfolio.BondValue(AsOf, TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0, testPortfolio.FundValue(AsOf, TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0, testPortfolio.EuroAndAsianOptionsValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(balance, testPortfolio.EquityWithLoanValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.GrossPositionValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(balance, testPortfolio.NetLiquidationValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.FuturesOptionsValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(balance, testPortfolio.ExcessLiquidity(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.BrokerMaintenanceMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.RegTMaintenanceMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.BrokerInitialMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.RegTInitialMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(balance, testPortfolio.SpecialMemorandumAccountBalance(AsOf, TimeOfDay.MarketEndOfDay));
        }
        public void MultiTradeTest2()
        {
            PortfolioSetup testSetupParams = new PortfolioSetup(PortfolioDirection.LongShort, PortfolioMarginType.RegTMargin, 10000, new DateTime(2019, 11, 18));
            Portfolio      testPortfolio   = new Portfolio(testSetupParams);
            var            testSec         = testSecurity1();
            var            testTrade       = testTradeBuy(testSec);
            var            balance         = testSetupParams.InitialCashBalance;

            // Valid monday with full trading week
            DateTime date = new DateTime(2019, 11, 18);

            var tradeBar = testSec.GetPriceBar(date, true);

            tradeBar.SetPriceValues(10m, 15m, 5m, 10m);

            var executionPrice = tradeBar.Open;

            // Mark this as an executed trade - buy 100 shares @ 10.00

            testTrade.MarkExecuted(tradeBar.BarDateTime, executionPrice);
            testPortfolio.AddExecutedTrade(testTrade);

            decimal commission = TradingEnvironment.Instance.CommissionCharged(testTrade);

            // Execute another 100 shates @ $11.00
            testTrade = testTradeBuy(testSec);
            testTrade.MarkExecuted(tradeBar.BarDateTime, 11.0m);
            testPortfolio.AddExecutedTrade(testTrade);

            Assert.AreEqual(1, testPortfolio.GetPositions(PositionStatus.Open, date).Count);

            var pos = testPortfolio.GetPosition(testSec, date);

            Assert.AreEqual(2, pos.ExecutedTrades.Count);
            Assert.AreEqual(10.5m, pos.AverageCost(date));
            Assert.AreEqual(200, pos.Size(date));
            Assert.AreEqual(2000.0m, pos.GrossPositionValue(date, TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(-100.0m, pos.TotalUnrealizedPnL(date, TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(-2100.0m, pos.NetCashImpact(date));
            Assert.AreEqual(-2.0m, pos.TotalCommissionPaid(date));
        }
        public void SimpleTradeTestLong1()
        {
            PortfolioSetup testSetupParams = new PortfolioSetup(PortfolioDirection.LongShort, PortfolioMarginType.RegTMargin, 10000, new DateTime(2019, 11, 18));
            Portfolio      testPortfolio   = new Portfolio(testSetupParams);

            var testSec   = testSecurity1();
            var testTrade = testTradeBuy(testSec);
            var balance   = testSetupParams.InitialCashBalance;

            // Valid monday with full trading week
            DateTime date = new DateTime(2019, 11, 18);

            var tradeBar = testSec.GetPriceBar(date, true);

            tradeBar.SetPriceValues(10m, 15m, 5m, 11m);

            var executionPrice = tradeBar.Open;

            // Mark this as an executed trade - buy 100 shares @ 10.00
            testTrade.MarkExecuted(date, executionPrice);
            testPortfolio.AddExecutedTrade(testTrade);

            // Check position functions
            var pos = testPortfolio.GetPosition(testSec, date);

            Assert.IsTrue(pos.PositionDirection == PositionDirection.LongPosition);
            Assert.IsTrue(pos.IsOpen(date));

            Assert.AreEqual(100, pos.Size(date));
            Assert.AreEqual(10.0m, pos.AverageCost(date));

            Assert.AreEqual(1100.0m, pos.GrossPositionValue(date, TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(-1000.0m, pos.NetCashImpact(date));
            Assert.AreEqual(100.0m, pos.TotalUnrealizedPnL(date, TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0.0m, pos.TotalRealizedPnL(date));

            // Check portfolio accounting

            Assert.AreEqual(1, testPortfolio.Positions.Count);

            DateTime AsOf = new DateTime(2019, 11, 18);

            decimal commission = TradingEnvironment.Instance.CommissionCharged(testTrade);


            Assert.AreEqual(-1.0m, commission);

            Assert.AreEqual(balance - 1000.0m - 1.0m, testPortfolio.TotalCashValue(AsOf));

            Assert.AreEqual(-1000m, testPortfolio.TotalCashPurchasesAndProceeds(AsOf));

            Assert.AreEqual(-1.0m, testPortfolio.TotalCommissions(AsOf));

            Assert.AreEqual(1100m, testPortfolio.StockValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(1100m, testPortfolio.LongStockValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0, testPortfolio.ShortStockValue(AsOf, TimeOfDay.MarketEndOfDay));

            //Assert.AreEqual(0, testPortfolio.LongOptionValue(asof));
            //Assert.AreEqual(0, testPortfolio.ShortOptionValue(asof));
            //Assert.AreEqual(0, testPortfolio.BondValue(asof));
            //Assert.AreEqual(0, testPortfolio.FundValue(asof));
            //Assert.AreEqual(0, testPortfolio.EuroAndAsianOptionsValue(asof));

            Assert.AreEqual(8999m + 1100m, testPortfolio.EquityWithLoanValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(1100.0m, testPortfolio.GrossPositionValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(8999m + 1100m, testPortfolio.NetLiquidationValue(AsOf, TimeOfDay.MarketEndOfDay));

            //Assert.AreEqual(0, testPortfolio.FuturesOptionsValue(asof));

            Assert.AreEqual(1100.0m, testPortfolio.BrokerMaintenanceMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(550.0m, testPortfolio.RegTMaintenanceMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(1100.0m, testPortfolio.BrokerInitialMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(500.0m, testPortfolio.RegTInitialMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(8999.0m, testPortfolio.ExcessLiquidity(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(9549.0m, testPortfolio.SpecialMemorandumAccountBalance(AsOf, TimeOfDay.MarketEndOfDay));
        }
        public void RegTTest()
        {
            // Test scenario outlined at IBKR https://www.interactivebrokers.com/en/index.php?f=24862

            PortfolioSetup testSetupParams = new PortfolioSetup(PortfolioDirection.LongShort, PortfolioMarginType.RegTMargin, 10000, new DateTime(2019, 11, 18));
            Portfolio      testPortfolio   = new Portfolio(testSetupParams);

            TradingEnvironment.Instance.NegateCommissionForTesting = true;

            var testSecXYZ = new Security("XYZ", SecurityType.USCommonEquity);
            var testSecABC = new Security("ABC", SecurityType.USCommonEquity);

            DateTime[] day = new DateTime[]
            {
                new DateTime(2019, 11, 15),
                new DateTime(2019, 11, 18), // Day 1
                new DateTime(2019, 11, 19),
                new DateTime(2019, 11, 20),
                new DateTime(2019, 11, 21),
                new DateTime(2019, 11, 22)  // Day 5
            };

            // Setup stock as described
            testSecXYZ.GetPriceBar(day[1], true).SetPriceValues(40m, 40m, 40m, 40m);
            testSecXYZ.GetPriceBar(day[2], true).SetPriceValues(40m, 40m, 40m, 40m);
            testSecXYZ.GetPriceBar(day[3], true).SetPriceValues(40m, 45m, 35m, 40m);
            testSecXYZ.GetPriceBar(day[4], true).SetPriceValues(45m, 45m, 45m, 45m);
            testSecXYZ.GetPriceBar(day[5], true).SetPriceValues(40m, 40m, 40m, 40m);

            testSecABC.GetPriceBar(day[1], true).SetPriceValues(101m, 101m, 101m, 101m);
            testSecABC.GetPriceBar(day[2], true).SetPriceValues(101m, 101m, 101m, 101m);
            testSecABC.GetPriceBar(day[3], true).SetPriceValues(101m, 101m, 101m, 101m);
            testSecABC.GetPriceBar(day[4], true).SetPriceValues(101m, 101m, 101m, 101m);
            testSecABC.GetPriceBar(day[5], true).SetPriceValues(101m, 101m, 75m, 100m);

            // Day 1

            /*
             * Deposit $10,000.00 Cash in Margin Account.
             * After the deposit, account values look like this:
             * Cash	$10,000.00	(Initial deposit)
             * Securities Market Value	$0.00	(No positions held)
             * Equity with Loan Value (ELV1)	$10,000.00
             * Initial Margin	$0.00	IM = 25% * Stock Value
             * Maintenance Margin (MM)	$0.00	MM = 25% * Stock Value
             * Available Funds	$10,000.00	ELV - IM
             * Excess Liquidity	$10,000.00	ELV - MM
             *
             * Reg T Margin	$0.00	Reg T Margin = 50% * Stock Value
             * SMA2	$10,000.00	SMA >= 0
             * SMA Requirement Satisfied, NO liquidation
             */

            Assert.AreEqual(10000.00m, testPortfolio.TotalCashValue(day[1]));
            Assert.AreEqual(0.0m, testPortfolio.SecuritiesMarketValue(day[1], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(10000.00m, testPortfolio.EquityWithLoanValue(day[1], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0.0m, testPortfolio.BrokerInitialMarginRequirement(day[1], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0.0m, testPortfolio.BrokerMaintenanceMarginRequirement(day[1], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(10000.0m, testPortfolio.AvailableFunds(day[1], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(10000.0m, testPortfolio.ExcessLiquidity(day[1], TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(10000.0m, testPortfolio.SpecialMemorandumAccountBalance(day[1], TimeOfDay.MarketEndOfDay));

            // Day 2

            /*
             * Customer BUYS 500 shares of XYZ stock at $40.00/share.
             * Total Amount = $20,000.00. After the trade, account values look like this:
             * Cash	($10,000.00)
             * Securities Market Value	$20,000.00
             * Equity with Loan Value (ELV1)	$10,000.00
             * Initial Margin	$5,000.00	IM = 25% * Stock Value
             * Maintenance Margin (MM)	$5,000.00	MM = 25% * Stock Value
             * Available Funds	$5,000.00	ELV-IM
             * Available Funds were >=0 at the time of the trade, so the trade was submitted.
             * Excess Liquidity	$5,000.00	ELV - MM
             */

            var trade1 = new Trade(testSecXYZ, TradeActionBuySell.Buy, 500, TradeType.Limit, 40.0m)
            {
                TradeStatus = TradeStatus.Pending
            };

            trade1.MarkExecuted(day[2], 40.0m);
            testPortfolio.AddExecutedTrade(trade1);

            Assert.AreEqual(-10000.00m, testPortfolio.TotalCashValue(day[2]));
            Assert.AreEqual(20000.0m, testPortfolio.SecuritiesMarketValue(day[2], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(10000.00m, testPortfolio.EquityWithLoanValue(day[2], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5000.0m, testPortfolio.BrokerInitialMarginRequirement(day[2], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5000.0m, testPortfolio.BrokerMaintenanceMarginRequirement(day[2], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5000.0m, testPortfolio.AvailableFunds(day[2], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5000.0m, testPortfolio.ExcessLiquidity(day[2], TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0.0m, testPortfolio.SpecialMemorandumAccountBalance(day[2], TimeOfDay.MarketEndOfDay));

            // Day 3 - 1

            /*
             * First, the price of XYZ rises to 45.00/share.
             * Account values now look like this:
             * Cash	($10,000.00)
             * Securities Market Value	$22,500.00
             * Equity with Loan Value (ELV1)	$12,500.00
             * Initial Margin	$5,625.00	IM = 25% * Stock Value
             * Maintenance Margin (MM)	$5,625.00	MM = 25% * Stock Value
             * Available Funds	$6,875.00	ELVIM
             * Excess Liquidity	$6,875.00	ELV - MM
             * Excess Liquidity >=0, so NO LIQUIDATION occurs.
             */

            // Our methods calculate EOD, so set price bar accordingly for this intraday scenario
            testSecXYZ.GetPriceBar(day[3]).SetPriceValues(45m, 45m, 45m, 45m);

            Assert.AreEqual(-10000.00m, testPortfolio.TotalCashValue(day[3]));
            Assert.AreEqual(22500, testPortfolio.SecuritiesMarketValue(day[3], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(12500.0m, testPortfolio.EquityWithLoanValue(day[3], TimeOfDay.MarketEndOfDay));

            // IBKR initial and maintenance margin is the same; our methods calculate initial based on the execution price for use in trade approval
            // Assert.AreEqual(5625.0m, testPortfolio.BrokerInitialMarginRequirement(day[3]));

            Assert.AreEqual(5625.0m, testPortfolio.BrokerMaintenanceMarginRequirement(day[3], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(6875.0m, testPortfolio.AvailableFunds(day[3], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(6875.0m, testPortfolio.ExcessLiquidity(day[3], TimeOfDay.MarketEndOfDay));

            //var log = testPortfolio.ToStringAllAccounting(day[3]);
            //log.AddRange(testPortfolio.ToStringAllActivity(day[3]));

            //OutputToTextFile(log);

            // Day 3 - 2

            /*
             * Then the price of XYZ falls to $35.00/share.
             * Account values now look like this:
             * Cash	($10,000.00)
             * Securities Market Value	$17,500.00
             * Equity with Loan Value (ELV1)	$7,500.00
             * Initial Margin	$4,375.00	IM = 25% * Stock Value
             * Maintenance Margin (MM)	$4,375.00	MM = 25% * Stock Value
             * Available Funds	$3,125.00	ELVIM
             * Excess Liquidity	$3,125.00	ELV - MM
             * Reg T Margin	$8,750.00	Reg T Margin = 50% * Stock Value
             * SMA2	$0.00
             */

            testSecXYZ.GetPriceBar(day[3]).SetPriceValues(35m, 35m, 35m, 35m);

            Assert.AreEqual(-10000.00m, testPortfolio.TotalCashValue(day[3]));
            Assert.AreEqual(17500.0m, testPortfolio.SecuritiesMarketValue(day[3], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(7500.0m, testPortfolio.EquityWithLoanValue(day[3], TimeOfDay.MarketEndOfDay));

            // Assert.AreEqual(5625.0m, testPortfolio.BrokerInitialMarginRequirement(day[3]));

            Assert.AreEqual(4375.0m, testPortfolio.BrokerMaintenanceMarginRequirement(day[3], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(3125.0m, testPortfolio.AvailableFunds(day[3], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(3125.0m, testPortfolio.ExcessLiquidity(day[3], TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0.0m, testPortfolio.SpecialMemorandumAccountBalance(day[3], TimeOfDay.MarketEndOfDay));

            // Day 4

            /*
             * Customer SELLS 500 shares of XYZ at $45.00/share.
             * Total Amount = $22,500.00. After the trade, account values look like this:
             * Cash	$12,500.00
             * Securities Market Value	$0.00	Positions no longer held.
             * Equity with Loan Value (ELV1)	$12,500.00
             * Initial Margin	$0.00	IM = 25% * Stock Value
             * Maintenance Margin (MM)	$0.00	MM = 25% * Stock Value
             * Available Funds	$12,500.00	ELV-IM
             * Excess Liquidity	$12,500.00	ELV - MM
             * Reg T Margin	$0.00	Reg T Margin = 50% * Stock Value
             * SMA2	$12,500.00
             */

            var trade2 = new Trade(testSecXYZ, TradeActionBuySell.Sell, 500, TradeType.Limit, 45.00m)
            {
                TradeStatus = TradeStatus.Pending
            };

            trade2.MarkExecuted(day[4], 45.0m);
            testPortfolio.AddExecutedTrade(trade2);

            Assert.AreEqual(12500.0m, testPortfolio.TotalCashValue(day[4]));
            Assert.AreEqual(0.0m, testPortfolio.SecuritiesMarketValue(day[4], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(12500.0m, testPortfolio.EquityWithLoanValue(day[4], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0.0m, testPortfolio.BrokerInitialMarginRequirement(day[4], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(0.0m, testPortfolio.BrokerMaintenanceMarginRequirement(day[4], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(12500.0m, testPortfolio.AvailableFunds(day[4], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(12500.0m, testPortfolio.ExcessLiquidity(day[4], TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(12500.0m, testPortfolio.SpecialMemorandumAccountBalance(day[4], TimeOfDay.MarketEndOfDay));

            // Day 5 - 1

            /*
             * Customer attempts to BUY 500 shares of ABC stock at $101.00/share.
             * Total Amount = $50,500.00. Account values at the time of the attempted trade would look like this:
             * Cash	$12,500.00
             * Securities Market Value	$0.00
             * Equity with Loan Value (ELV1)	$12,500.00
             * Initial Margin	$12,625.00	IM = 25% * Stock Value
             * Maintenance Margin (MM)	$12,625.00	MM = 25% * Stock Value
             * Available Funds	($125.00)	ELV-IM
             * Available Funds <=0 so the trade is Rejected.
             * Excess Liquidity	($125.00)	ELV - MM
             */

            var trade3 = new Trade(testSecABC, TradeActionBuySell.Buy, 500, TradeType.Limit, 101.00m)
            {
                TradeStatus = TradeStatus.Pending
            };

            var copyPort  = testPortfolio.Copy();
            var copyTrade = trade3.Copy();

            copyTrade.MarkExecuted(day[5], 101.00m);
            copyPort.AddExecutedTrade(copyTrade);

            // Post-trade available funds are negative, so this trade would be rejected

            Assert.AreEqual(-125.0m, copyPort.AvailableFunds(day[5], TimeOfDay.MarketOpen));

            // Test rule implementation
            var rule = new TradeApprovalRule_2("Rule2");

            Assert.IsFalse(rule.Run(trade3, testPortfolio, day[5], TimeOfDay.MarketOpen));


            copyTrade = null;
            copyPort  = null;

            // Day 5 - 2

            /*
             * Later on Day 5, the customer buys some stock.
             * Customer BUYS 300 shares of ABC stock at $100.00/share.
             * Total Amount = $30,000.00. After the trade, account values look like this:
             * Cash	($17,500.00)
             * Securities Market Value	$30,000.00
             * Equity with Loan Value (ELV1)	$12,500.00
             * Initial Margin	$7,500.00	IM = 25% * Stock Value
             * Maintenance Margin (MM)	$7,500.00	MM = 25% * Stock Value
             * Available Funds	$5,000.00	ELVIM
             * Excess Liquidity	$5,000.00	ELV - MM
             * Reg T Margin	$15,000.00	Reg T Margin = 50% * Stock Value
             * SMA2	-$2,500.00
             */

            testSecABC.GetPriceBar(day[5]).SetPriceValues(100m, 100m, 100m, 100m);

            var trade4 = new Trade(testSecABC, TradeActionBuySell.Buy, 300, TradeType.Limit, 100.00m)
            {
                TradeStatus = TradeStatus.Pending
            };

            trade4.MarkExecuted(day[5], 100.0m);
            testPortfolio.AddExecutedTrade(trade4);

            Assert.AreEqual(-17500.0m, testPortfolio.TotalCashValue(day[5]));
            Assert.AreEqual(30000.0m, testPortfolio.SecuritiesMarketValue(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(12500.0m, testPortfolio.EquityWithLoanValue(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(7500.0m, testPortfolio.BrokerInitialMarginRequirement(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(7500.0m, testPortfolio.BrokerMaintenanceMarginRequirement(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5000.0m, testPortfolio.AvailableFunds(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5000.0m, testPortfolio.ExcessLiquidity(day[5], TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(-2500.0m, testPortfolio.SpecialMemorandumAccountBalance(day[5], TimeOfDay.MarketEndOfDay));

            // Day 5 - 2 alternate

            /*
             * Consider an alternate Day 5 scenario in which the price of ABC stock drops.
             * Price of ABC stock drops to $75.00/share.
             * Account values would now look like this:
             * Cash	($17,500.00)
             * Securities Market Value	$22,500.00
             * Equity with Loan Value (ELV1)	$5,000.00
             * Initial Margin	$5,625.00	IM = 25% * Stock Value
             * Maintenance Margin (MM)	$5,625.00	MM = 25% * Stock Value
             * Available Funds	($625.00)	ELVIM
             * Excess Liquidity	($625.00)
             */

            testSecABC.GetPriceBar(day[5]).SetPriceValues(75m, 75m, 75m, 75m);

            Assert.AreEqual(-17500.0m, testPortfolio.TotalCashValue(day[5]));
            Assert.AreEqual(22500.0m, testPortfolio.SecuritiesMarketValue(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5000.0m, testPortfolio.EquityWithLoanValue(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5625.0m, testPortfolio.BrokerInitialMarginRequirement(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(5625.0m, testPortfolio.BrokerMaintenanceMarginRequirement(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(-625.0m, testPortfolio.AvailableFunds(day[5], TimeOfDay.MarketEndOfDay));
            Assert.AreEqual(-625.0m, testPortfolio.ExcessLiquidity(day[5], TimeOfDay.MarketEndOfDay));

            TradingEnvironment.Instance.NegateCommissionForTesting = false;
        }
        public void MultiTradeTest4()
        {
            PortfolioSetup testSetupParams = new PortfolioSetup(PortfolioDirection.LongShort, PortfolioMarginType.RegTMargin, 10000, new DateTime(2019, 11, 18));
            Portfolio      testPortfolio   = new Portfolio(testSetupParams);
            var            testSec         = testSecurity1();
            var            testTrade       = testTradeSell(testSec);
            var            balance         = testSetupParams.InitialCashBalance;

            // Valid monday with full trading week
            DateTime date = new DateTime(2019, 11, 18);

            var tradeBar = testSec.GetPriceBar(date, true);

            tradeBar.SetPriceValues(10m, 15m, 5m, 12m);

            var executionPrice = tradeBar.Open;

            // Mark this as an executed trade - buy 100 shares @ 10.00
            testTrade.TradeDate = tradeBar.BarDateTime;
            testTrade.MarkExecuted(tradeBar.BarDateTime, 10.0m);
            testPortfolio.AddExecutedTrade(testTrade);

            decimal commission = TradingEnvironment.Instance.CommissionCharged(testTrade);

            // Execute another 100 shares @ $9.00
            testTrade = testTradeSell(testSec);
            testTrade.MarkExecuted(tradeBar.BarDateTime, 9.0m);
            testPortfolio.AddExecutedTrade(testTrade);

            // Execute another 50 shares @ $8.00
            testTrade          = testTradeSell(testSec);
            testTrade.Quantity = 50;
            testTrade.MarkExecuted(tradeBar.BarDateTime, 8.0m);
            testPortfolio.AddExecutedTrade(testTrade);

            // Execute another 50 shares @ 6.00
            testTrade          = testTradeSell(testSec);
            testTrade.Quantity = 50;
            testTrade.MarkExecuted(tradeBar.BarDateTime, 6.0m);
            testPortfolio.AddExecutedTrade(testTrade);

            var avgCostExp = ((100 * 10.0m) + (100 * 9.0m) + (50 * 8.0m) + (50 * 6.0m)) / 300;
            var pos        = testPortfolio.GetPosition(testSec, date);

            Assert.AreEqual(avgCostExp.ToDouble(), pos.AverageCost(date).ToDouble(), .001);

            // Buy some shares - average cost should not change
            testTrade = testTradeBuy(testSec);
            testTrade.MarkExecuted(tradeBar.BarDateTime, 7.5m);
            testPortfolio.AddExecutedTrade(testTrade);

            Assert.AreEqual(avgCostExp.ToDouble(), pos.AverageCost(date).ToDouble(), .001);

            // Buy more

            // Execute another 50 shares @ $6.5
            testTrade          = testTradeSell(testSec);
            testTrade.Quantity = 50;
            testTrade.MarkExecuted(tradeBar.BarDateTime, 6.5m);
            testPortfolio.AddExecutedTrade(testTrade);

            avgCostExp = ((avgCostExp * 200) + (50 * 6.50m)) / 250;

            Assert.AreEqual(avgCostExp.ToDouble(), pos.AverageCost(date).ToDouble(), .001);
        }
        public void MultiTradeTest1()
        {
            PortfolioSetup testSetupParams = new PortfolioSetup(PortfolioDirection.LongShort, PortfolioMarginType.RegTMargin, 10000, new DateTime(2019, 11, 18));
            Portfolio      testPortfolio   = new Portfolio(testSetupParams);
            var            testSec         = testSecurity1();
            var            testTrade       = testTradeBuy(testSec);
            var            balance         = testSetupParams.InitialCashBalance;

            // Valid monday with full trading week
            DateTime date = new DateTime(2019, 11, 18);

            var tradeBar = testSec.GetPriceBar(date, true);

            tradeBar.SetPriceValues(10m, 15m, 5m, 10m);

            var executionPrice = tradeBar.Open;

            // Mark this as an executed trade - buy 100 shares @ 10.00
            testTrade.MarkExecuted(tradeBar.BarDateTime, executionPrice);
            testPortfolio.AddExecutedTrade(testTrade);

            decimal commission = TradingEnvironment.Instance.CommissionCharged(testTrade);

            // No do a sell of 100 at $1 higher
            testTrade = testTradeSell(testSec);
            testTrade.MarkExecuted(tradeBar.BarDateTime, 11.0m);
            testPortfolio.AddExecutedTrade(testTrade);

            commission += TradingEnvironment.Instance.CommissionCharged(testTrade);
            // Everything should be zeroed out, less $2 commission

            Assert.AreEqual(1, testPortfolio.Positions.Count);

            var closePos = testPortfolio.GetPositions(PositionStatus.Closed, date);

            Assert.IsTrue(closePos.Count == 1);
            Assert.IsTrue(closePos[0].IsOpen(date) == false);
            Assert.IsTrue(closePos[0].PositionDirection == PositionDirection.LongPosition);

            var openPos = testPortfolio.GetPositions(PositionStatus.Open, date);

            Assert.IsTrue(openPos.Count == 0);

            DateTime AsOf = new DateTime(2019, 11, 18);

            Assert.AreEqual(-2.0m, commission);

            // We should have made $100 minus $2 commission
            Assert.AreEqual(balance + 100.0m + commission, testPortfolio.TotalCashValue(AsOf));

            Assert.AreEqual(100.0m, testPortfolio.TotalCashPurchasesAndProceeds(AsOf));

            Assert.AreEqual(-2.0m, testPortfolio.TotalCommissions(AsOf));

            Assert.AreEqual(0m, testPortfolio.StockValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0m, testPortfolio.LongStockValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0m, testPortfolio.ShortStockValue(AsOf, TimeOfDay.MarketEndOfDay));

            //Assert.AreEqual(0, testPortfolio.LongOptionValue(asof));
            //Assert.AreEqual(0, testPortfolio.ShortOptionValue(asof));
            //Assert.AreEqual(0, testPortfolio.BondValue(asof));
            //Assert.AreEqual(0, testPortfolio.FundValue(asof));
            //Assert.AreEqual(0, testPortfolio.EuroAndAsianOptionsValue(asof));

            Assert.AreEqual(balance + 100.0m + commission, testPortfolio.EquityWithLoanValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0.0m, testPortfolio.GrossPositionValue(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(balance + 100.0m + commission, testPortfolio.NetLiquidationValue(AsOf, TimeOfDay.MarketEndOfDay));

            //Assert.AreEqual(0, testPortfolio.FuturesOptionsValue(asof));

            Assert.AreEqual(0m, testPortfolio.BrokerMaintenanceMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0.0m, testPortfolio.RegTMaintenanceMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(0.0m, testPortfolio.BrokerInitialMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(-50.0m, testPortfolio.RegTInitialMarginRequirement(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(balance + 100.0m + commission, testPortfolio.ExcessLiquidity(AsOf, TimeOfDay.MarketEndOfDay));

            Assert.AreEqual(balance + 100.0m + commission, testPortfolio.SpecialMemorandumAccountBalance(AsOf, TimeOfDay.MarketEndOfDay));
        }