Example #1
0
        /// <summary>
        /// Creates a new <see cref="OptionStrategyLegPredicate"/> from the specified predicate <paramref name="expression"/>
        /// </summary>
        public static OptionStrategyLegPredicate Create(
            Expression <Func <IReadOnlyList <OptionPosition>, OptionPosition, bool> > expression
            )
        {
            // expr must NOT include compound comparisons
            // expr is a lambda of one of the following forms:
            // (legs, position) => position.{target} {comparison} legs[i].{reference-target}
            // (legs, position) => legs[i].{reference-target} {comparison} position.{target}
            // (legs, position) => position.{target} {comparison} {literal-reference-target}
            // (legs, position) => {literal-reference-target} {comparison} position.{target}

            // we want to make the comparison of a common form, specifically:
            // position.{target} {comparison} {reference-target}
            // this is so when we invoke OptionPositionCollection we have the correct comparison type
            // for example, legs[0].Strike > position.Strike
            // needs to be inverted into position.Strike < legs[0].Strike
            // so we can call OptionPositionCollection.Slice(BinaryComparison.LessThan, legs[0].Strike);

            try
            {
                var legsParameter     = expression.Parameters[0];
                var positionParameter = expression.Parameters[1];
                var binary            = expression.OfType <BinaryExpression>().Single(e => e.NodeType.IsBinaryComparison());
                var comparison        = BinaryComparison.FromExpressionType(binary.NodeType);
                var leftReference     = CreateReferenceValue(legsParameter, positionParameter, binary.Left);
                var rightReference    = CreateReferenceValue(legsParameter, positionParameter, binary.Right);
                if (leftReference != null && rightReference != null)
                {
                    throw new ArgumentException($"The provided expression is not of the required form: {expression}");
                }

                // we want the left side to be null, indicating position.{target}
                // if not, then we need to flip the comparison operand
                var reference = rightReference;
                if (rightReference == null)
                {
                    reference  = leftReference;
                    comparison = comparison.FlipOperands();
                }

                return(new OptionStrategyLegPredicate(comparison, reference, expression.Compile(), expression));
            }
            catch
            {
                // we can still handle arbitrary predicates, they just require a full search of the positions
                // as we're unable to leverage any of the pre-build indexes via Slice methods.
                return(new OptionStrategyLegPredicate(null, null, expression.Compile(), expression));
            }
        }
Example #2
0
        public void EvaluatesFlippedOperandsComparison(ExpressionType type, bool expected1, bool expected2)
        {
            const int left1  = 1;
            const int right1 = 1;
            const int left2  = 2;
            const int right2 = 3;

            var comparison = BinaryComparison.FromExpressionType(type).FlipOperands();

            var actual1 = comparison.Evaluate(left1, right1);

            Assert.AreEqual(expected1, actual1);

            var actual2 = comparison.Evaluate(left2, right2);

            Assert.AreEqual(expected2, actual2);
        }