Overall Statistics
using QuantConnect.Algorithm;
using QuantConnect.Orders;
using QuantConnect.Securities;
using System;

namespace QuantConnect
{
    public abstract class FixedSetHoldingsAlgorithm : QCAlgorithm
    {
        /// <summary>
        /// Alias for SetHoldings to avoid the M-decimal errors.
        /// </summary>
        /// <param name="symbol">string symbol we wish to hold</param>
        /// <param name="percentage">double percentage of holdings desired</param>
        /// <param name="liquidateExistingHoldings">liquidate existing holdings if neccessary to hold this stock</param>
        /// <seealso cref="MarketOrder"/>
        public void FixedSetHoldings(Symbol symbol, double percentage, bool liquidateExistingHoldings = false)
        {
            FixedSetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings);
        }

        /// <summary>
        /// Alias for SetHoldings to avoid the M-decimal errors.
        /// </summary>
        /// <param name="symbol">string symbol we wish to hold</param>
        /// <param name="percentage">float percentage of holdings desired</param>
        /// <param name="liquidateExistingHoldings">bool liquidate existing holdings if neccessary to hold this stock</param>
        /// <param name="tag">Tag the order with a short string.</param>
        /// <seealso cref="MarketOrder"/>
        public void FixedSetHoldings(Symbol symbol, float percentage, bool liquidateExistingHoldings = false, string tag = "")
        {
            FixedSetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag);
        }

        /// <summary>
        /// Alias for SetHoldings to avoid the M-decimal errors.
        /// </summary>
        /// <param name="symbol">string symbol we wish to hold</param>
        /// <param name="percentage">float percentage of holdings desired</param>
        /// <param name="liquidateExistingHoldings">bool liquidate existing holdings if neccessary to hold this stock</param>
        /// <param name="tag">Tag the order with a short string.</param>
        /// <seealso cref="MarketOrder"/>
        public void FixedSetHoldings(Symbol symbol, int percentage, bool liquidateExistingHoldings = false, string tag = "")
        {
            FixedSetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag);
        }

        /// <summary>
        /// Automatically place an order which will set the holdings to between 100% or -100% of *PORTFOLIO VALUE*.
        /// E.g. SetHoldings("AAPL", 0.1); SetHoldings("IBM", -0.2); -> Sets portfolio as long 10% APPL and short 20% IBM
        /// E.g. SetHoldings("AAPL", 2); -> Sets apple to 2x leveraged with all our cash.
        /// </summary>
        /// <param name="symbol">Symbol indexer</param>
        /// <param name="percentage">decimal fraction of portfolio to set stock</param>
        /// <param name="liquidateExistingHoldings">bool flag to clean all existing holdings before setting new faction.</param>
        /// <param name="tag">Tag the order with a short string.</param>
        /// <seealso cref="MarketOrder"/>
        public void FixedSetHoldings(Symbol symbol, decimal percentage, bool liquidateExistingHoldings = false, string tag = "")
        {
            //Initialize Requirements:
            Security security;
            if (!Securities.TryGetValue(symbol, out security))
            {
                Error(symbol.ToString() + " not found in portfolio. Request this data when initializing the algorithm.");
                return;
            }

            //If they triggered a liquidate
            if (liquidateExistingHoldings)
            {
                foreach (var kvp in Portfolio)
                {
                    var holdingSymbol = kvp.Key;
                    var holdings = kvp.Value;
                    if (holdingSymbol != symbol && holdings.AbsoluteQuantity > 0)
                    {
                        //Go through all existing holdings [synchronously], market order the inverse quantity:
                        Order(holdingSymbol, -holdings.Quantity, false, tag);
                    }
                }
            }

            //Only place trade if we've got > 1 share to order.
            var quantity = FixedCalculateOrderQuantity(symbol, percentage);
            if (Math.Abs(quantity) > 0)
            {
                MarketOrder(symbol, quantity, false, tag);
            }
        }

        private bool TryOrderQuantity(int orderQuantity, Security security, decimal marginRemaining, decimal targetOrderValue)
        {
            //note that margin requirements and order value + fees are assumed to be monotonic w.r.t. orderQuantity,
            //otherwise binary search would not work and an exhaustive search would be necessary

            var order = new MarketOrder(security.Symbol, orderQuantity, UtcTime);
            var orderValue = order.GetValue(security);
            var orderFees = security.FeeModel.GetOrderFee(security, order);

            // calculate the margin required for the order
            var marginRequired = security.MarginModel.GetInitialMarginRequiredForOrder(security, order);

            return marginRequired <= marginRemaining && orderValue + orderFees <= targetOrderValue;
        }

        /// <summary>
        /// Calculate the order quantity to achieve target-percent holdings.
        /// </summary>
        /// <param name="symbol">Security object we're asking for</param>
        /// <param name="target">Target percentag holdings, this is an unlevered value, so 
        /// if you have 2x leverage and request 100% holdings, it will utilize half of the 
        /// available margin</param>
        /// <returns>Order quantity to achieve this percentage</returns>
        public int FixedCalculateOrderQuantity(Symbol symbol, decimal target)
        {
            var security = Securities[symbol];
            return FixedCalculateOrderQuantity(symbol, target, (int)security.Holdings.Quantity);
        }

        public int FixedCalculateOrderQuantity(Symbol symbol, decimal target, int initialQuantity)
        {
            var security = Securities[symbol];
            var price = security.Price;
            if (price == 0)
                price = (security.BidPrice + security.AskPrice) / 2;

            // if targeting zero, simply return the negative of the quantity
            if (target == 0) return (int)-initialQuantity;

            // can't order it if we don't have data
            if (price == 0) return 0;

            // this is the value in dollars that we want our holdings to have
            var targetPortfolioValue = target * Portfolio.TotalPortfolioValue;
            var quantity = initialQuantity;
            var currentHoldingsValue = price * quantity;

            // remove directionality, we'll work in the land of absolutes
            var targetOrderValue = Math.Abs(targetPortfolioValue - currentHoldingsValue);
            var direction = targetPortfolioValue > currentHoldingsValue ? OrderDirection.Buy : OrderDirection.Sell;

            // determine the unit price in terms of the account currency
            var unitPrice = new MarketOrder(symbol, 1, UtcTime).GetValue(security);

            // calculate the total margin available
            var marginRemaining = Portfolio.GetMarginRemaining(symbol, direction);
            if (marginRemaining <= 0) return 0;

            // compute the initial order quantity
            int orderQuantity;
            int maxOrderQuantity = (int)(targetOrderValue / unitPrice); //upper bound
            int minOrderQuantity = 1; //lower bound

            if (TryOrderQuantity(maxOrderQuantity, security, marginRemaining, targetOrderValue))
            {
                orderQuantity = maxOrderQuantity;
            }
            else if (!TryOrderQuantity(minOrderQuantity, security, marginRemaining, targetOrderValue))
            {
                orderQuantity = 0;
            }
            else
            {
                //binary search
                for (;;)
                {
                    orderQuantity = (maxOrderQuantity + minOrderQuantity) / 2;
                    if (orderQuantity == minOrderQuantity)
                    {
                        orderQuantity = minOrderQuantity;
                        break;
                    }

                    if (TryOrderQuantity(orderQuantity, security, marginRemaining, targetOrderValue))
                    {
                        minOrderQuantity = orderQuantity;
                    }
                    else
                    {
                        maxOrderQuantity = orderQuantity;
                    }
                }
            }

            //Rounding off Order Quantity to the nearest multiple of Lot Size
            if (orderQuantity % Convert.ToInt32(security.SymbolProperties.LotSize) != 0)
            {
                orderQuantity = orderQuantity - (orderQuantity % Convert.ToInt32(security.SymbolProperties.LotSize));
            }

            // add directionality back in
            return (direction == OrderDirection.Sell ? -1 : 1) * orderQuantity;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QuantConnect.Algorithm.CSharp
{
    public static class XMath
    {
        public static bool IsPowerOfTwo(ulong x)
        {
            return (x & (x - 1)) == 0;
        }

        public static int Log2(int v)
        {
            int r = 0xFFFF - v >> 31 & 0x10;
            v >>= r;
            int shift = 0xFF - v >> 31 & 0x8;
            v >>= shift;
            r |= shift;
            shift = 0xF - v >> 31 & 0x4;
            v >>= shift;
            r |= shift;
            shift = 0x3 - v >> 31 & 0x2;
            v >>= shift;
            r |= shift;
            r |= (v >> 1);
            return r;
        }

        public static void Clamp<T>(ref T val, T min, T max) where T : IComparable
        {
            if (min.CompareTo(val) > 0)
                val = min;
            else if (max.CompareTo(val) < 0)
                val = max;
        }
    }
}
// Accord Machine Learning Library
// The Accord.NET Framework
// http://accord-framework.net
//
// Copyright © Alex Risman, 2016
// https://github.com/mthmn20
//
// Copyright © César Souza, 2009-2017
// cesarsouza at gmail.com
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

namespace QuantConnect.Algorithm.CSharp
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using System.Runtime.Serialization;
    using Accord.Math;
    using System.Threading;
    using Accord.MachineLearning;
    using Accord.MachineLearning.DecisionTrees;
    /// <summary>
    ///   Random Forest.
    /// </summary>
    /// 
    /// <remarks>
    /// <para>
    ///   Represents a random forest of <see cref="DecisionTree"/>s. For 
    ///   sample usage and example of learning, please see the documentation
    ///   page for <see cref="RandomForestLearning"/>.</para>
    /// </remarks>
    /// 
    /// <example>
    /// <para>
    ///   This example shows the simplest way to induce a decision tree with continuous variables.</para>
    /// <code source="Unit Tests\Accord.Tests.MachineLearning\DecisionTrees\RandomForestTest.cs" region="doc_iris" />
    /// <para>
    ///   The next example shows how to induce a decision tree with continuous variables using a 
    ///   <see cref="Accord.Statistics.Filters.Codification">codebook</see> to manage how input 
    ///   variables should be encoded.</para>
    /// <code source="Unit Tests\Accord.Tests.MachineLearning\DecisionTrees\RandomForestTest.cs" region="doc_nursery" />
    /// </example>
    /// 
    /// <seealso cref="DecisionTree"/>
    /// <seealso cref="RandomForestLearning"/>
    /// 
    [Serializable]
    public class DynamicForest : MulticlassClassifierBase, IParallel
    {
        [NonSerialized]
        private ParallelOptions parallelOptions;


        /// <summary>
        ///   Gets the trees in the random forest.
        /// </summary>
        /// 
        public readonly List<MulticlassClassifierBase<double[]>> Trees = new List<MulticlassClassifierBase<double[]>>();

        /// <summary>
        ///   Gets the number of classes that can be recognized
        ///   by this random forest.
        /// </summary>
        /// 
        [Obsolete("Please use NumberOfOutputs instead.")]
        public int Classes { get { return NumberOfOutputs; } }

        /// <summary>
        ///   Gets or sets the parallelization options for this algorithm.
        /// </summary>
        /// 
        public ParallelOptions ParallelOptions
        {
            get { return parallelOptions; }
            set { parallelOptions = value; }
        }

        /// <summary>
        /// Gets or sets a cancellation token that can be used
        /// to cancel the algorithm while it is running.
        /// </summary>
        /// 
        public CancellationToken Token
        {
            get { return ParallelOptions.CancellationToken; }
            set { ParallelOptions.CancellationToken = value; }
        }

        /// <summary>
        ///   Creates a new random forest.
        /// </summary>
        /// 
        /// <param name="trees">The number of trees in the forest.</param>
        /// <param name="classes">The number of classes in the classification problem.</param>
        /// 
        public DynamicForest(int classes)
        {
            this.NumberOfOutputs = classes;
            this.ParallelOptions = new ParallelOptions();
        }

        /// <summary>
        ///   Computes the decision output for a given input vector.
        /// </summary>
        /// 
        /// <param name="data">The input vector.</param>
        /// 
        /// <returns>The forest decision for the given vector.</returns>
        /// 
        [Obsolete("Please use Decide() instead.")]
        public int Compute(double[] data)
        {
            return Decide(data);
        }


        /// <summary>
        /// Computes a class-label decision for a given <paramref name="input" />.
        /// </summary>
        /// <param name="input">The input vector that should be classified into
        /// one of the <see cref="ITransform.NumberOfOutputs" /> possible classes.</param>
        /// <returns>A class-label that best described <paramref name="input" /> according
        /// to this classifier.</returns>
        public override int Decide(double[] input)
        {
            int[] responses = new int[NumberOfOutputs];
            Parallel.For(0, Trees.Count, ParallelOptions, i =>
            {
                int j = Trees[i].Decide(input);
                Interlocked.Increment(ref responses[j]);
            });

            return responses.ArgMax();
        }

        public int Decide(double[] input, Func<int, double> treeWeightFunc)
        {
            double[] responses = new double[NumberOfOutputs];
            Parallel.For(0, Trees.Count, ParallelOptions, i =>
            {
                try
                {
                    int j = Trees[i].Decide(input);
                    Add(ref responses[j], treeWeightFunc(i));
                }
                catch (Exception)
                {
                    //quick fix
                }
            });

            return responses.ArgMax();
        }

        private static double Add(ref double location1, double value)
        {
            double newCurrentValue = location1; // non-volatile read, so may be stale
            while (true)
            {
                double currentValue = newCurrentValue;
                double newValue = currentValue + value;
                newCurrentValue = Interlocked.CompareExchange(ref location1, newValue, currentValue);
                if (newCurrentValue == currentValue)
                    return newValue;
            }
        }

        /// <summary>
        ///   Called when the object is being deserialized.
        /// </summary>
        /// 
        [OnDeserializing]
        protected void OnDeserializingMethod(StreamingContext context)
        {
            this.parallelOptions = new ParallelOptions();
        }
    }
}
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

using System;
using QuantConnect.Data.Market;
using QuantConnect.Securities;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders;
using QuantConnect.Data;
using System.Linq;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// Represents the default fill model used to simulate order fills
    /// but with the following modification for limit orders:
    /// Trade volumes do not allow a fill unless they are >= VolumeThreshold.
    /// Limitation: Quotes are not used.
    /// </summary>
    public class ImmediateWhenVolumeFillModel : ImmediateFillModel
    {
        private readonly QCAlgorithm _algo;

        public ImmediateWhenVolumeFillModel(QCAlgorithm algo)
        {
            _algo = algo;

            VolumeThreshold = 1;
            OrderDelay = TimeSpan.FromSeconds(0);
        }

        /// <summary>
        /// Threshold below which orders do not fill. Defaults to 1.
        /// </summary>
        public long VolumeThreshold { get; set; }

        /// <summary>
        /// Uniform delay to orders in backtest simulation.
        /// Note, has a different meaning in FillOnNextAvailableTick.
        /// </summary>
        public TimeSpan OrderDelay { get; set; }

        /// <summary>
        /// Optional tick fill source.
        /// </summary>
        public TickFillSource TickFillSource { get; set; }

        /// <summary>
        /// For best effort HFT simulation with second precision tick data.
        /// If this is used, OrderDelay instead works as a barrier beyond which
        /// last price is used instead.
        /// </summary>
        public bool FillOnNextAvailableTick { get; set; }

        /// <summary>
        /// Treat asset as if a fill will always be possible at same price as last tick.
        /// </summary>
        public bool HighlyLiquidAsset { get; set; }

        /// <summary>
        /// Default limit order fill model in the base security class.
        /// </summary>
        /// <param name="asset">Security asset we're filling</param>
        /// <param name="order">Order packet to model</param>
        /// <returns>Order fill information detailing the average price and quantity filled.</returns>
        /// <seealso cref="StopMarketFill(Security, StopMarketOrder)"/>
        /// <seealso cref="MarketFill(Security, MarketOrder)"/>
        public override OrderEvent LimitFill(Security asset, LimitOrder order)
        {
            if (FillOnNextAvailableTick)
                throw new NotSupportedException("FillOnNextAvailableTick");

            //Initialise;
            var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone);
            var fill = new OrderEvent(order, utcTime, 0);
            fill.Status = order.Status; //necessary, engine will process fill if quantity filled != 0 or status differs

            //If its cancelled don't need anymore checks:
            if (order.Status == OrderStatus.Canceled) return fill;

            //Get the range of prices in the last bar:
            var prices = GetPrices(asset, order);
            if (prices == null) return fill;

            if (prices.Volume < VolumeThreshold) return fill;

            if (prices.Time < order.Time + OrderDelay) return fill;

            //-> Valid Live/Model Order: 
            switch (order.Direction)
            {
                case OrderDirection.Buy:
                    //Buy limit seeks lowest price
                    if (prices.Low < order.LimitPrice)
                    {
                        //Set order fill:
                        fill.Status = OrderStatus.Filled;

                        //TODO: include option to fill "current bar" order was created in with below price, which was default QC code (unfortunately, leads to highly unrealistic fills with waiting limit orders)
                        //fill.FillPrice = Math.Min(prices.High, order.LimitPrice);
                        fill.FillPrice = order.LimitPrice;
                    }
                    break;
                case OrderDirection.Sell:
                    //Sell limit seeks highest price possible
                    if (prices.High > order.LimitPrice)
                    {
                        fill.Status = OrderStatus.Filled;

                        //TODO: include option to fill "current bar" order was created in with below price, which was default QC code (unfortunately, leads to highly unrealistic fills with waiting limit orders)
                        //fill.FillPrice = Math.Max(prices.Low, order.LimitPrice);
                        fill.FillPrice = order.LimitPrice;
                    }
                    break;
            }

            // assume the order completely filled
            if (fill.Status == OrderStatus.Filled)
            {
                fill.FillQuantity = order.Quantity;
                fill.OrderFee = asset.FeeModel.GetOrderFee(asset, order);
            }

            fill.UtcTime = prices.Time;

            return fill;
        }

        /// <summary>
        /// Default market fill model for the base security class. Fills at the last traded price.
        /// </summary>
        /// <param name="asset">Security asset we're filling</param>
        /// <param name="order">Order packet to model</param>
        /// <returns>Order fill information detailing the average price and quantity filled.</returns>
        /// <seealso cref="SecurityTransactionModel.StopMarketFill"/>
        /// <seealso cref="SecurityTransactionModel.LimitFill"/>
        public override OrderEvent MarketFill(Security asset, MarketOrder order)
        {
            //Default order event to return.
            var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone);
            var fill = new OrderEvent(order, utcTime, 0);
            fill.Status = order.Status; //necessary, engine will process fill if quantity filled != 0 or status differs

            if (order.Status == OrderStatus.Canceled) return fill;

            // make sure the exchange is open before filling
            if (!IsExchangeOpen(asset)) return fill;

            var prices = GetPrices(asset, order);
            if (prices == null) return fill;

            if (!HighlyLiquidAsset && prices.Volume < VolumeThreshold) return fill;

            var maxTime = prices.Time;
            if (HighlyLiquidAsset && TickFillSource == null && _algo.UtcTime > maxTime)
                maxTime = _algo.UtcTime;

            var orderTime = order.Time;
            if (!FillOnNextAvailableTick)
                orderTime += OrderDelay;

            if (maxTime <= orderTime) return fill;

            //Order [fill]price for a market order model is the current security price
            fill.FillPrice = prices.Current;
            fill.Status = OrderStatus.Filled;

            //Calculate the model slippage: e.g. 0.01c
            var slip = asset.SlippageModel.GetSlippageApproximation(asset, order);

            //Apply slippage
            switch (order.Direction)
            {
                case OrderDirection.Buy:
                    fill.FillPrice += slip;
                    break;
                case OrderDirection.Sell:
                    fill.FillPrice -= slip;
                    break;
            }

            // assume the order completely filled
            if (fill.Status == OrderStatus.Filled)
            {
                fill.FillQuantity = order.Quantity;
                fill.OrderFee = asset.FeeModel.GetOrderFee(asset, order);
            }

            fill.UtcTime = prices.Time;

            return fill;
        }

        /// <summary>
        /// Get the minimum and maximum price for this security in the last bar:
        /// </summary>
        /// <param name="asset">Security asset we're checking</param>
        /// <param name="direction">The order direction, decides whether to pick bid or ask</param>
        private Prices GetPrices(Security asset, Order order)
        {
            var direction = order.Direction;
            var low = asset.Low;
            var high = asset.High;
            var open = asset.Open;
            var close = asset.Close;
            var current = asset.Price;
            var volume = 0;
            var time = asset.LocalTime;

            if (direction == OrderDirection.Hold)
            {
                return new Prices(current, open, high, low, close, volume, time, asset.Exchange.TimeZone);
            }

            if (TickFillSource != null)
            {
                var closestTick = asset.Cache.GetData<Tick>();
                var orderTime = order.Time;
                if (!FillOnNextAvailableTick)
                    orderTime += OrderDelay;

                foreach (var t in TickFillSource.Ticks)
                {
                    if (t.TickType != TickType.Trade)
                        continue;

                    if (t.Quantity < VolumeThreshold)
                        continue;

                    var tickTime = t.Time.ConvertToUtc(asset.Exchange.TimeZone);
                    if (tickTime > orderTime)
                    {
                        var fillTime = orderTime;
                        if (FillOnNextAvailableTick)
                            fillTime = tickTime;

                        if (HighlyLiquidAsset && !FillOnNextAvailableTick)
                        {
                            var closestTickTime = closestTick.Time.ConvertToUtc(asset.Exchange.TimeZone);

                            //allow using last price despite being from past
                            if (Math.Abs((tickTime - orderTime).TotalSeconds) < Math.Abs((closestTickTime - orderTime).TotalSeconds))
                            {
                                closestTick = t;
                                //_algo.Debug("before order: " + (closestTickTime - orderTime).TotalSeconds);
                            }
                            else
                            {
                                //_algo.Debug("before order: " + (closestTickTime - orderTime).TotalSeconds);
                            } 

                            if (closestTickTime > fillTime)
                                fillTime = closestTickTime;
                        }
                        else
                        {
                            closestTick = t;
                        }

                        return new Prices(closestTick.Price, open, high, low, close, closestTick.Quantity, fillTime);
                    }
                    else
                    {
                        closestTick = t;
                    }
                }

                return null;
            }

            var tick = asset.Cache.GetData<Tick>();
            if (tick != null)
            {
                return new Prices(tick.Price, open, high, low, close, tick.Quantity, tick.Time, asset.Exchange.TimeZone);
            }

            var tradeBar = asset.Cache.GetData<TradeBar>();
            if (tradeBar != null)
            {
                return new Prices(tradeBar, asset.Exchange.TimeZone);
            }

            var lastData = asset.GetLastData();
            var lastBar = lastData as TradeBar;
            if (lastBar != null)
            {
                return new Prices(lastBar, asset.Exchange.TimeZone);
            }

            return new Prices(current, open, high, low, close, volume, time, asset.Exchange.TimeZone);
        }

        /// <summary>
        /// Determines if the exchange is open using the current time of the asset
        /// </summary>
        private static bool IsExchangeOpen(Security asset)
        {
            if (!asset.Exchange.DateTimeIsOpen(asset.LocalTime))
            {
                // if we're not open at the current time exactly, check the bar size, this handle large sized bars (hours/days)
                var currentBar = asset.GetLastData();
                if (asset.LocalTime.Date != currentBar.EndTime.Date || !asset.Exchange.IsOpenDuringBar(currentBar.Time, currentBar.EndTime, false))
                {
                    return false;
                }
            }
            return true;
        }

        private class Prices
        {
            public readonly decimal Current;
            public readonly decimal Open;
            public readonly decimal High;
            public readonly decimal Low;
            public readonly decimal Close;
            public readonly decimal Volume;
            public readonly DateTime Time;

            public Prices(TradeBar bar, NodaTime.DateTimeZone timeZone)
                : this(bar.Close, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume, bar.Time, timeZone)
            {
            }

            public Prices(decimal current, decimal open, decimal high, decimal low, decimal close, decimal volume, DateTime time, NodaTime.DateTimeZone timeZone)
            {
                Current = current;
                Open = open == 0 ? current : open;
                High = high == 0 ? current : high;
                Low = low == 0 ? current : low;
                Close = close == 0 ? current : close;
                Volume = volume;
                Time = time.ConvertToUtc(timeZone);
            }

            public Prices(decimal current, decimal open, decimal high, decimal low, decimal close, decimal volume, DateTime utcTime)
            {
                Current = current;
                Open = open == 0 ? current : open;
                High = high == 0 ? current : high;
                Low = low == 0 ? current : low;
                Close = close == 0 ? current : close;
                Volume = volume;
                Time = utcTime;
            }
        }
    }
}
using QuantConnect.Data.Market;
using QuantConnect.Securities;
using System;
using System.Collections.Generic;
using QuantConnect.Orders;
using QuantConnect.Orders.Slippage;
using QuantConnect.Indicators;
using QuantConnect.Data;
using System.Collections.Concurrent;
using QuantConnect.Securities.Interfaces;

namespace QuantConnect.Algorithm.CSharp
{
	//QC adaption of QT algorithm from https://www.quantopian.com/posts/yavols-yet-another-volatility-strategy-xiv-sniper-using-rsi2
	//credit to Kory Hoang and Cesar Alvarez for original version
	//apologies for messy code, copied some bits from other project when starting out and I don't want
	//to spend a lot of time cleaning it
    public sealed partial class VixRsiAlgorithm : FixedSetHoldingsAlgorithm
    {
        private const string _algoID = "vixrsi";
        private const decimal _securityLeverage = 2; //set per Security, in this case equal to IB intraday limits
        private const Resolution _resolution = Resolution.Minute;
        private const bool _disableRealisticFills = true;

 		//you will notice when you tune this up that the algo doesn't look that great,
 		//on the other hand slippage for TLT might be exaggerated,
 		//you might be able to achieve better results by using limit orders in reality
        private const decimal SLIPPAGE = 0.00m / 100m;

        public override void Initialize()
        {
            SetCash(100000);

            SetStartDate(2011, 1, 1);
            //SetEndDate(2017, 1, 1);
            //SetEndDate(2016, 1, 10);
            //SetStartDate(2005, 11, 1);
            //SetEndDate(2016, 10, 01);

            try
            {
                ActualInitialization();
            }
            catch (Exception e)
            {
                ReportException(e, this);
                throw;
            }
        }

        public static void ReportException(Exception e, QCAlgorithm algo)
        {
            algo.Error(algo.Time + ": " + e.Message + "\n" + e.StackTrace);
            algo.Log(algo.Time + ": " + e.Message + "\n" + e.StackTrace);
        }

        private readonly List<Tradable> _tradables = new List<Tradable>();

        private void ActualInitialization()
        {

            Schedule.On(Schedule.DateRules.EveryDay(), Schedule.TimeRules.At(0, 0, 0), AtMidnight);

            SetBrokerageModel(Brokerages.BrokerageName.InteractiveBrokersBrokerage);

            _tradables.Add(new Tradable(this, "XIV", "TLT"));

            Schedule.On(DateRules.EveryDay(_tradables[0].Symbol), TimeRules.AfterMarketOpen(_tradables[0].Symbol, -1), BeforeOpen);
            Schedule.On(DateRules.EveryDay(_tradables[0].Symbol), TimeRules.BeforeMarketClose(_tradables[0].Symbol, 0.92), RebalanceBeforeClose);

            SetBenchmark(_tradables[0].Symbol);

            if (LiveMode)
            {
                Schedule.On(DateRules.EveryDay(), TimeRules.Every(TimeSpan.FromMinutes(1)), CheckOrderEvents);
            }  
        }

        public override void OnEndOfAlgorithm()
        {
            CheckOrderEvents();

            //_paramSetPollingThread.Cancel();
            //_paramSetPollingThread.Join();
        }

        private void AtMidnight()
        {
            //Xtend.DiscardScheduledEvents();
        }

        private void BeforeOpen()
        {
            foreach (var tradable in _tradables)
            {
                tradable.BeforeOpen();
            }
        }

        public void OnWarmupData(Slice slice)
        {
            //OnData(slice);
        }

        private void RebalanceBeforeClose()
        {
            foreach (var tradable in _tradables)
            {
                tradable.RebalanceBeforeClose();
            }
        }

        public override void OnData(Slice slice)
        {
            CheckOrderEvents();

            foreach (var kv in slice.Bars)
            {
                var tradable = _tradables.Find(x => x.Symbol == kv.Key);
                if (tradable != null)
                {
                    tradable.OnData(kv.Value);
                }
            }
        }

        private readonly ConcurrentQueue<OrderEvent> _orderEvents = new ConcurrentQueue<OrderEvent>();

        public override void OnOrderEvent(OrderEvent ev)
        {
            _orderEvents.Enqueue(ev.Clone()); 
        }

        private void CheckOrderEvents()
        {
            for (;;)
            {
                OrderEvent ev;
                if (!_orderEvents.TryDequeue(out ev))
                    break;

                var tradable = _tradables.Find(x => x.Symbol == ev.Symbol);
                if (tradable != null)
                {
                    tradable.OnOrderEvent(ev);
                }
            }
        }

        private sealed class Tradable
        {
            private readonly VixRsiAlgorithm _algo;
            public readonly Security Security;
            public readonly Security SafeSecurity;

            private readonly TickFillSource _tickFillSource;

            private readonly SimpleMovingAverage _averageSlippage = new SimpleMovingAverage(200);
            private readonly SimpleMovingAverage _averageOrderLatency = new SimpleMovingAverage(200);
            private readonly Maximum _maxOrderLatency = new Maximum(200);

            private readonly RelativeStrengthIndex _rsi7 = new RelativeStrengthIndex(7);
            private readonly RelativeStrengthIndex _rsi2 = new RelativeStrengthIndex(2);

            private decimal _oldRsi7;
            private decimal _oldRsi2;

            private bool _nextDayBuy;
            private bool _nextDaySell;

            private decimal _takeProfitPrice;
            private decimal _takeLossPrice;

            public Symbol Symbol
            {
                get { return Security.Symbol; }
            }

            public Tradable(VixRsiAlgorithm algo, string symbol, string invSymbol)
            {
                _algo = algo;
                Security = algo.AddSecurity(SecurityType.Equity, symbol, _resolution, true, _securityLeverage, false);
                if (invSymbol != null)
                    SafeSecurity = algo.AddSecurity(SecurityType.Equity, invSymbol, _resolution, true, _securityLeverage, false);
                else
                    SafeSecurity = null;
                if (_disableRealisticFills)
                    Security.SlippageModel = new ConstantSlippageModel(SLIPPAGE);
                _tickFillSource = new TickFillSource(Symbol);

                if (!_disableRealisticFills)
                {
                    var fillModel = new ImmediateWhenVolumeFillModel(algo);
                    //fillModel.TickFillSource = _tickFillSource;
                    fillModel.HighlyLiquidAsset = true;
                    fillModel.OrderDelay = TimeSpan.FromSeconds(1);
                    Security.FillModel = fillModel;
                }

                Security.DataFilter = new CustomDataFilter();
            }

            private class CustomDataFilter : ISecurityDataFilter
            {
                public bool Filter(Security vehicle, BaseData data)
                {
                    if (data.DataType == MarketDataType.Tick)
                    {
                        var tick = (Tick)data;
                        if (tick.Suspicious)
                            return false;
                    }

                    return true;
                }
            }

            private bool CanBeInMarket(DateTime now)
            {
                return true;
            }

            public void OnData(TradeBar bar)
            {
                if (Security.HoldStock)
                {
                    if (Security.Price > _takeProfitPrice || Security.Price <_takeLossPrice)
                    {
                        _nextDaySell = false;
                        Exit();
                    }
                }
            }

            public void RebalanceBeforeClose()
            {
                _rsi2.Update(_algo.Time, Security.Price);
                _rsi7.Update(_algo.Time, Security.Price);

                const decimal trigger1 = 25;
                const decimal trigger2 = 75;

                if (_rsi7 > trigger1 && _oldRsi7 < trigger1 && !Security.HoldStock)
                {
                    Enter();
                }
                else if (_rsi2 > trigger2 && _oldRsi2 < trigger2 && !Security.HoldStock)
                {
                    _nextDayBuy = true;
                }
                else if (Security.HoldStock && _rsi2 < trigger2 && _oldRsi2 > trigger2)
                {
                    _nextDaySell = true;
                }

                _oldRsi2 = _rsi2;
                _oldRsi7 = _rsi7;
            }

            private void Enter()
            {
                //auto converted to market on open if outside market hours

                _takeLossPrice = Security.Price * 0.98m;
                _takeProfitPrice = Security.Price * 1.05m;
                _algo.Liquidate(SafeSecurity.Symbol);
                _algo.FixedSetHoldings(Security.Symbol, 1);
            }

            private void Exit()
            {
                //auto converted to market on open if outside market hours

                _algo.Liquidate(Security.Symbol);
                _algo.FixedSetHoldings(SafeSecurity.Symbol, 1);
            }

            public void BeforeOpen()
            {
                if (!_algo.LiveMode)
                    UpdateOrderStats();

                if (_nextDayBuy)
                {
                    _nextDayBuy = false;
                    if (!Security.HoldStock)
                        Enter();
                }

                if (_nextDaySell)
                {
                    _nextDaySell = false;
                    if (Security.HoldStock)
                        Exit();
                }
            }

            private decimal GetExpectedOrderLatency()
            {
                if (_averageOrderLatency.Samples != 0)
                    return _averageOrderLatency;
                return 1;
            }

            private void UpdateOrderStats()
            {
                var negativeSlippage = -_averageSlippage.Current.Value;
                _algo.SetRuntimeStatistic("Slippage", negativeSlippage.ToString("P3"));
                _algo.SetRuntimeStatistic("Latency", _averageOrderLatency.Current.Value.ToString("F2"));
                _algo.SetRuntimeStatistic("LatencyMax", _maxOrderLatency.Current.Value.ToString("F2"));
            }

            private void HandleOrderFilled(OrderEvent ev)
            {
            }

            public void OnOrderEvent(OrderEvent ev)
            {
                switch (ev.Status)
                {
                    case OrderStatus.Invalid:
                        _algo.Debug("Order error: " + ev.Message);
                        _algo.Debug("Order error for " + Symbol.ToString() + ": " + ev.Status);
                        break; //TODO: handle error in some way, maybe retry after a while?
                    case OrderStatus.Filled:
                        HandleOrderFilled(ev);
                        break;
                }
            }
        }
    }
}
using QuantConnect.Orders.Slippage;
using System;
using QuantConnect.Orders;
using QuantConnect.Securities;

namespace QuantConnect.Algorithm.CSharp
{
    class OrderTypeDependentSlippageModel : ISlippageModel
    {
        public ISlippageModel LimitOrderSlippage { get; set; }
        public ISlippageModel MarketOrderSlippage { get; set; }
        public ISlippageModel MarketOnCloseOrderSlippage { get; set; }
        public ISlippageModel MarketOnOpenOrderSlippage { get; set; }
        public ISlippageModel StopLimitOrderSlippage { get; set; }
        public ISlippageModel StopMarketOrderSlippage { get; set; }

        public OrderTypeDependentSlippageModel(ISlippageModel defaultModel)
        {
            LimitOrderSlippage = defaultModel;
            MarketOrderSlippage = defaultModel;
            MarketOnCloseOrderSlippage = defaultModel;
            MarketOnOpenOrderSlippage = defaultModel;
            StopLimitOrderSlippage = defaultModel;
            StopMarketOrderSlippage = defaultModel;
        }

        public void SetMarketSlippageModel(ISlippageModel model)
        {
            MarketOrderSlippage = model;
            MarketOnCloseOrderSlippage = model;
            MarketOnOpenOrderSlippage = model;
            StopMarketOrderSlippage = model;
        }

        public void SetLimitSlippageModel(ISlippageModel model)
        {
            LimitOrderSlippage = model;
            StopLimitOrderSlippage = model;
        }

        public decimal GetSlippageApproximation(Security asset, Order order)
        {
            switch (order.Type)
            {
                case OrderType.Limit:
                    return LimitOrderSlippage.GetSlippageApproximation(asset, order);
                case OrderType.Market:
                    return MarketOrderSlippage.GetSlippageApproximation(asset, order);
                case OrderType.MarketOnClose:
                    return MarketOnCloseOrderSlippage.GetSlippageApproximation(asset, order);
                case OrderType.MarketOnOpen:
                    return MarketOnOpenOrderSlippage.GetSlippageApproximation(asset, order);
                case OrderType.StopLimit:
                    return StopLimitOrderSlippage.GetSlippageApproximation(asset, order);
                case OrderType.StopMarket:
                    return StopMarketOrderSlippage.GetSlippageApproximation(asset, order);
                default:
                    throw new NotImplementedException("Slippage specialization not implemented for order type " + order.Type.ToString());
            }
        }
    }
}
using System;
using System.Threading;

namespace QuantConnect.Algorithm.CSharp
{
    sealed class PollingThread
    {
        private readonly Thread _thread;
        private readonly CancellationTokenSource _cancellation;
        private readonly Action _action;
        private readonly bool _startWithWait;

        public double PollingInterval { get; set; }

        public PollingThread(bool startWithWait, Action action)
        {
            _startWithWait = startWithWait;
            _action = action;
            _cancellation = new CancellationTokenSource();
            _thread = new Thread(ThreadFunc);
        }

        public void Start()
        {
            _thread.Start();
        }

        private void ThreadFunc()
        {
            var token = _cancellation.Token;

            if (_startWithWait)
                Wait();

            while (!token.IsCancellationRequested)
            {
                _action();
                Wait();
            }
        }

        private void Wait()
        {
            var endTime = DateTime.Now + TimeSpan.FromSeconds(PollingInterval);

            while (DateTime.Now <= endTime)
            {
                var timeUntilEnd = endTime - DateTime.Now;
                Thread.Sleep(Math.Min(100, timeUntilEnd.Milliseconds));
            }
        }

        public void Cancel()
        {
            _cancellation.Cancel();
        }

        public void Join()
        {
            _thread.Join();
        }
    }
}
using System;
using System.Collections.Generic;

//found and copied from random site on Internetz
namespace QuantConnect.Algorithm.CSharp
{
    public sealed class PriorityQueue<T> where T : IComparable<T>
    {
        private readonly List<T> _data = new List<T>();

        public PriorityQueue()
        {
            _data = new List<T>();
        }

        public void Enqueue(T item)
        {
            _data.Add(item);
            int ci = _data.Count - 1; // child index; start at end
            while (ci > 0)
            {
                int pi = (ci - 1) / 2; // parent index
                if (_data[ci].CompareTo(_data[pi]) >= 0) break; // child item is larger than (or equal) parent so we're done
                T tmp = _data[ci]; _data[ci] = _data[pi]; _data[pi] = tmp;
                ci = pi;
            }
        }

        public T Dequeue()
        {
            // assumes pq is not empty; up to calling code
            int li = _data.Count - 1; // last index (before removal)
            T frontItem = _data[0];   // fetch the front
            _data[0] = _data[li];
            _data.RemoveAt(li);

            --li; // last index (after removal)
            int pi = 0; // parent index. start at front of pq
            while (true)
            {
                int ci = pi * 2 + 1; // left child index of parent
                if (ci > li) break;  // no children so done
                int rc = ci + 1;     // right child
                if (rc <= li && _data[rc].CompareTo(_data[ci]) < 0) // if there is a rc (ci + 1), and it is smaller than left child, use the rc instead
                    ci = rc;
                if (_data[pi].CompareTo(_data[ci]) <= 0) break; // parent is smaller than (or equal to) smallest child so done
                T tmp = _data[pi]; _data[pi] = _data[ci]; _data[ci] = tmp; // swap parent and child
                pi = ci;
            }
            return frontItem;
        }

        public T Peek()
        {
            T frontItem = _data[0];
            return frontItem;
        }

        public int Count
        {
            get { return _data.Count; }
        }

        public override string ToString()
        {
            string s = "";
            for (int i = 0; i < _data.Count; ++i)
                s += _data[i].ToString() + " ";
            s += "count = " + _data.Count;
            return s;
        }

        internal bool IsConsistent()
        {
            // is the heap property true for all data?
            if (_data.Count == 0) return true;
            int li = _data.Count - 1; // last index
            for (int pi = 0; pi < _data.Count; ++pi) // each parent index
            {
                int lci = 2 * pi + 1; // left child index
                int rci = 2 * pi + 2; // right child index

                if (lci <= li && _data[pi].CompareTo(_data[lci]) > 0) return false; // if lc exists and it's greater than parent then bad.
                if (rci <= li && _data[pi].CompareTo(_data[rci]) > 0) return false; // check the right child too.
            }
            return true; // passed all checks
        }
    }
}
using QuantConnect.Interfaces;
using QuantConnect.Securities;
using System;
using System.Linq;
using System.Reflection;

namespace QuantConnect.Algorithm.CSharp
{
    public static class PrivateAPI
    {
        private static IBrokerage _brokerage;

        public static IBrokerage GetBrokerage(QCAlgorithm algo)
        {
            if (_brokerage != null)
                return _brokerage;

            var orderProcessor = (IOrderProcessor)GetPrivateFieldValue(algo.Transactions, "_orderProcessor");
            if (orderProcessor == null)
                throw new Exception("Cannot find _orderProcessor in SecurityTransactionManager");

            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            var allTypes = assemblies.SelectMany(a => a.GetTypes());
            var choices = allTypes.Where(t => t.FullName.EndsWith(".BrokerageTransactionHandler")).ToArray();
            if (choices.Length > 1)
            {
                throw new Exception("More than one: " + string.Join(" ", choices.Select(x => x.FullName).ToArray()));
            }
            var brokerageTransactionHandlerType = choices.Single();
            _brokerage = (IBrokerage)GetPrivateFieldValue(brokerageTransactionHandlerType, orderProcessor, "_brokerage");

            if (_brokerage == null)
                throw new Exception("Brokerage cannot be accessed via reflection");
            return _brokerage;
        }

        private static FieldInfo GetPrivateField(Type type, string name)
        {
            return type.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
        }

        private static FieldInfo GetPrivateField<MyType>(MyType dummy, string name)
        {
            return GetPrivateField(typeof(MyType), name);
        }

        private static object GetPrivateFieldValue(Type type, object instance, string name)
        {
            var fieldInfo = GetPrivateField(type, name);
            return fieldInfo.GetValue(instance);
        }

        private static object GetPrivateFieldValue<MyType>(MyType instance, string name)
        {
            return GetPrivateFieldValue(typeof(MyType), instance, name);
        }
    }
}
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

using QuantConnect.Indicators;
using System;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// This indicator computes the n-period population standard deviation.
    /// </summary>
    public class StandardDeviationOverflowSafe : Variance
    {
        /// <summary>
        /// Initializes a new instance of the StandardDeviation class with the specified period.
        /// 
        /// Evaluates the standard deviation of samples in the lookback period. 
        /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
        /// </summary>
        /// <param name="period">The sample size of the standard deviation</param>
        public StandardDeviationOverflowSafe(int period)
            : this("STD" + period, period)
        {
        }

        /// <summary>
        /// Initializes a new instance of the StandardDeviation class with the specified name and period.
        /// 
        /// Evaluates the standard deviation of samples in the lookback period. 
        /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
        /// </summary>
        /// <param name="name">The name of this indicator</param>
        /// <param name="period">The sample size of the standard deviation</param>
        public StandardDeviationOverflowSafe(string name, int period)
            : base(name, period)
        {
        }

        /// <summary>
        /// Gets a flag indicating when this indicator is ready and fully initialized
        /// </summary>
        public override bool IsReady
        {
            get { return Samples >= Period; }
        }

        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <param name="window">The window for the input history</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint input)
        {
            double val = Math.Sqrt((double)base.ComputeNextValue(window, input));
            return (decimal)val.Clamp(_min, _max);
        }

        private static readonly double _max = (double)decimal.MaxValue * 0.99999999;
        private static readonly double _min = (double)decimal.MinValue * 0.99999999;
    }
}
using QuantConnect.Data.Market;
using QuantConnect.Orders;
using System.Collections.Generic;
using System.Linq;

namespace QuantConnect.Algorithm.CSharp
{
    public sealed class TickFillSource
    {
        private readonly Symbol _symbol; //just to check for validity
        private List<Tick> _ticksToFill = new List<Tick>();

        public IEnumerable<Tick> Ticks { get; private set; }

        //public int DataVersion { get; private set; } //needed so we can't fill new order with ticks given at same iteration

        public TickFillSource(Symbol symbol)
        {
            _symbol = symbol;
        }

        public void SetTicks(IEnumerable<Tick> ticks)
        {
            Ticks = ticks.ToArray();
            //DataVersion += 1;
            _ticksToFill.Clear();
            //Reverse() because we want to remove newest at tail a lot of the time
            var range = ticks.Reverse().Where(x => x.TickType == TickType.Trade && x.Symbol == _symbol);
            //_ticksToFill.AddRange(range);
            _ticksToFill = range.ToList(); //AddRange having problem with enumerator...
        }

        public int GetFirstTickIndex()
        {
            return _ticksToFill.Count - 1;
        }

        public int GetPreviousTickIndex(int index)
        {
            return index + 1;
        }

        private Tick PeekOrDequeueTickIfAny(ref int index, bool remove, decimal limit, OrderDirection direction)
        {
            //a more accurate model that takes into account volume is most likely not needed
            //thus this (more) simple and fast implementation

            while (index >= 0)
            {
                var tick = _ticksToFill[index];
                bool match = false;
                if (direction == OrderDirection.Buy)
                {
                    if (tick.Price < limit)
                        match = true;
                }
                else if (direction == OrderDirection.Sell)
                {
                    if (tick.Price > limit)
                        match = true;
                }

                if (remove)
                    _ticksToFill.RemoveAt(index);

                index -= 1;

                if (match)
                    return tick;
            }

            return null;
        }

        public Tick DequeueNextTickIfAny(ref int index, decimal limit, OrderDirection direction)
        {
            return PeekOrDequeueTickIfAny(ref index, true, limit, direction);
        }

        public Tick PeekNextTickIfAny(ref int index, decimal limit, OrderDirection direction)
        {
            return PeekOrDequeueTickIfAny(ref index, false, limit, direction);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Reflection;

namespace QuantConnect.Algorithm.CSharp
{
    public static class Xtend
    {
        public static FieldInfo GetPrivateField(Type type, string name)
        {
            return type.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
        }

        public static FieldInfo GetPrivateField<MyType>(this MyType dummy, string name)
        {
            return GetPrivateField(typeof(MyType), name);
        }

        public static object GetPrivateFieldValue(Type type, object instance, string name)
        {
            var fieldInfo = GetPrivateField(type, name);
            if (fieldInfo == null)
                throw new InvalidOperationException("Unable to find field with name " + name);
            return fieldInfo.GetValue(instance);
        }

        public static object GetPrivateFieldValue<MyType>(this MyType instance, string name)
        {
            return GetPrivateFieldValue(typeof(MyType), instance, name);
        }

        public static T Clamp<T>(this T val, T min, T max) where T : IComparable
        {
            XMath.Clamp(ref val, min, max);
            return val;
        }

        public static void Shuffle<T>(this IList<T> list, Random rng)
        {
            int n = list.Count;
            while (n > 1)
            {
                n--;
                int k = rng.Next(n + 1);
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }

        public static int Argmax(this IList<int> list)
        {
            int maxIndex = list.Count - 1;
            var max = list[maxIndex];
            for (int index = list.Count - 2; index >= 0; --index)
            {
                var x = list[index];
                if (x > max)
                {
                    maxIndex = index;
                    max = x;
                }
            }

            return maxIndex;
        }

        public static int Argmin(this IList<int> list)
        {
            int minIndex = list.Count - 1;
            var min = list[minIndex];
            for (int index = list.Count - 2; index >= 0; --index)
            {
                var x = list[index];
                if (x < min)
                {
                    minIndex = index;
                    min = x;
                }
            }

            return minIndex;
        }

        public static int Argmax(this IList<double> list)
        {
            int maxIndex = list.Count - 1;
            var max = list[maxIndex];
            for (int index = list.Count - 2; index >= 0; --index)
            {
                var x = list[index];
                if (x > max)
                {
                    maxIndex = index;
                    max = x;
                }
            }

            return maxIndex;
        }

        public static int Argmin(this IList<double> list)
        {
            int minIndex = list.Count - 1;
            var min = list[minIndex];
            for (int index = list.Count - 2; index >= 0; --index)
            {
                var x = list[index];
                if (x < min)
                {
                    minIndex = index;
                    min = x;
                }
            }

            return minIndex;
        }
    }
}