public static bool TryTrade(Security security, Portfolio source, Portfolio target, BigRational amount, out BigRational sourceNew, out BigRational targetNew)
 {
     if (amount < BigRational.Zero)
     {
         throw new ArgumentOutOfRangeException("Must be greater than zero (swap source and target)", "amount");
     }
     targetNew = target.Get(security); // so if source transaction fails targetnew isnt null
     // if the source is denying the transaction then we can end the whole thing without much harm
     if (!source.AttemptTransact(security, BigRational.Negate(amount), out sourceNew))
     {
         return(false);
     }
     // if the target is denying the transaction then we need to rollback the state
     if (!target.AttemptTransact(security, amount, out targetNew))
     {
         // naive rollback
         // dont bother checking if its valid, we need to force this through
         sourceNew = target.ForceTransact(security, amount);
     }
     return(true);
 }
        public void big_rational_static_methods()
        {
            Assert.True(0.5 == BigRational.Abs(0.5d));
            Assert.True(0.5 == BigRational.Abs(-0.5d));
            Assert.False(0.5 == BigRational.Abs(-1));
            Assert.False(0.5 == BigRational.Abs(1));

            Assert.True(-0.5 == BigRational.Negate(0.5d));
            Assert.True(0.5 == BigRational.Negate(-0.5d));
            Assert.False(0.5 == BigRational.Negate(-1));
            Assert.False(-0.5 == BigRational.Negate(1));

            //Doesn't work great... testing with equals doubles fails
            Assert.True(new BigRational(1, 2) == BigRational.Invert(new BigRational(2, 1)));
            Assert.True(new BigRational(2, 1) == BigRational.Invert(new BigRational(1, 2)));
            Assert.True(new BigRational(-1, 2) == BigRational.Invert(new BigRational(-2, 1)));
            Assert.True(new BigRational(-2, 1) == BigRational.Invert(new BigRational(-1, 2)));

            Assert.True(new BigRational(BigInteger.One) + new BigRational(BigInteger.One) == 2);
            Assert.True(BigRational.Add(new BigRational(BigInteger.One), new BigRational(BigInteger.One)) == 2);

            //Not working for me
            //BigRational big1 = new BigRational(1.0);
            //big1++;
            //Assert.AreEqual(new BigRational(2, 1), big1);

            //Not working for me
            //BigRational big2 = new BigRational(1.0);
            //big2--;
            //Assert.True(0 == big2);

            Assert.True(new BigRational(BigInteger.One) - new BigRational(BigInteger.One) == 0);
            Assert.True(BigRational.Subtract(new BigRational(BigInteger.One), new BigRational(BigInteger.One)) == 0);

            BigRational big3 = new BigRational(1.0);

            Assert.True(-1.0 == -big3);

            BigRational big4 = new BigRational(1.0);

            Assert.True(1.0 == +big3);

            Assert.True(new BigRational(BigInteger.One) * new BigRational(BigInteger.One) == 1);
            Assert.True(BigRational.Multiply(new BigRational(BigInteger.One), new BigRational(BigInteger.One)) == 1);
            Assert.True(new BigRational(BigInteger.One) * new BigRational(2.0) == 2.0);
            Assert.True(BigRational.Multiply(new BigRational(BigInteger.One), new BigRational(2.0)) == 2.0);

            Assert.True(new BigRational(BigInteger.One) / new BigRational(BigInteger.One) == 1);
            Assert.True(BigRational.Divide(new BigRational(BigInteger.One), new BigRational(BigInteger.One)) == 1);
            Assert.AreEqual(new BigRational(1, 2), new BigRational(new BigInteger(1)) / new BigRational(new BigInteger(2)));                    //Again, mixing consructors doesn't work well.
            Assert.AreEqual(new BigRational(1, 2), BigRational.Divide(new BigRational(new BigInteger(1)), new BigRational(new BigInteger(2)))); //Again, mixing consructors doesn't work well. Testing with equals double 0.5 fails

            //Assert.True(new BigRational(BigInteger.One) < new BigRational(2.0)); //Don't mix the constructors for comparison!!!
            Assert.True(new BigRational(1.0) < new BigRational(2.0));
            Assert.False(new BigRational(2.0) < new BigRational(1.0));
            Assert.False(new BigRational(1.0) < new BigRational(1.0));
            Assert.True(new BigRational(1.0) <= new BigRational(2.0));
            Assert.True(new BigRational(1.0) <= new BigRational(1.0));
            Assert.False(new BigRational(2.0) <= new BigRational(1.0));
            Assert.True(new BigRational(1.0) == new BigRational(1.0));
            Assert.True(new BigRational(1.0) != new BigRational(2.0));

            Assert.False(new BigRational(1.0) > new BigRational(2.0));
            Assert.True(new BigRational(2.0) > new BigRational(1.0));
            Assert.False(new BigRational(BigInteger.One) > new BigRational(BigInteger.One));
            Assert.False(new BigRational(1.0) >= new BigRational(2.0));
            Assert.True(new BigRational(BigInteger.One) >= new BigRational(BigInteger.One));
            Assert.True(new BigRational(2.0) >= new BigRational(1.0));

            //Modulus doesn't seem to work well
            //Assert.AreEqual(BigRational.Zero, new BigRational(2.0) % new BigRational(1.0));
            //Assert.AreEqual(BigRational.One, new BigRational(3.0) % new BigRational(2.0));
            //Assert.True(new BigRational(1.5) % new BigRational(1.0) == new BigRational(0.5));
            //Assert.True(new BigRational(1.0) % new BigRational(2.0) == 0);
        }
        public bool IsTransactionPossible(Transaction transaction)
        {
            var targetPortfolio = transaction.Target;
            var sourcePortfolio = transaction.Source;

            return(sourcePortfolio.ValidateTransactionAmount(transaction.TradedSecurity, BigRational.Negate(transaction.TradedSecurityAmount)) && // check if we can withdraw the traded security
                   targetPortfolio.ValidateTransactionAmount(transaction.TradedSecurity, transaction.TradedSecurityAmount) && // check that we can deposit the traded security into the other account
                   sourcePortfolio.ValidateTransactionAmount(transaction.BackingSecurity, transaction.BackingSecurityAmount) && // check that we can deposit the backing security into the source account
                   targetPortfolio.ValidateTransactionAmount(transaction.BackingSecurity, BigRational.Negate(transaction.BackingSecurityAmount))); // check that there's actually enough backing security to take out
        }
 /// <summary>
 /// Checks to make sure an amount can be successfully be transacted to or from this portfolio
 /// Negative numbers for withdrawals and positive numbers for deposits
 /// </summary>
 /// <param name="security"></param>
 /// <param name="amount"></param>
 /// <returns></returns>
 public bool Validate(Security security, BigRational amount)
 {
     return(BigRational.Negate(amount) <= Get(security));
 }
 internal static void ForceTrade(Security security, Portfolio source, Portfolio target, BigRational amount)
 {
     source.ForceTransact(security, BigRational.Negate(amount));
     target.ForceTransact(security, amount);
 }