Beispiel #1
0
        void addBar(StatisticsCollector collector, IEnumerable <Position> positions, double close, double fxRate)
        {
            var weightedPositions = O.convert(positions, p => new WeightedPosition(p));

            collector.addBar(weightedPositions, O.dictionaryOne(symbol(), new Bar(close, close, close, close, currentDate)), O.dictionaryOne(symbol(), fxRate));
            currentDate = currentDate.AddDays(1);
        }
Beispiel #2
0
        static double expectancy(StatisticsCollector collector)
        {
            var expectedWin  = AVERAGE_WIN(collector) * WINNING_TRADES_PERCENT(collector);
            var expectedLoss = AVERAGE_LOSS(collector) * (1 - WINNING_TRADES_PERCENT(collector));

            return((expectedLoss + expectedWin) / Math.Abs(AVERAGE_LOSS(collector)));
        }
Beispiel #3
0
        public static double yearsInCollector(StatisticsCollector collector)
        {
            var firstDate = first(collector.dates());
            var lastDate  = last(collector.dates());

            return(lastDate.Subtract(firstDate).TotalDays / 365.25);
        }
Beispiel #4
0
        internal static List <Drawdown> allDrawdowns(StatisticsCollector collector)
        {
            var      equities       = cumulativeSum(collector.pnl());
            var      highWaterMarks = cumulativeMax(equities);
            Drawdown current        = null;
            var      drawdowns      = new List <Drawdown>();

            each(equities, highWaterMarks, (equity, highWaterMark) => {
                if (equity == highWaterMark)
                {
                    if (current != null)
                    {
                        current.closed();
                    }
                    current = null;
                    return;
                }
                if (current == null)
                {
                    current = new Drawdown();
                    drawdowns.Add(current);
                }
                current.add(equity, highWaterMark);
            });
            return(drawdowns);
        }
Beispiel #5
0
        static Position addTrade(Order order, StatisticsCollector collector, double fillPrice, double slippage, double fxRate)
        {
            var trade    = new Trade(order, fillPrice, order.size, slippage, fxRate);
            var position = order.fill(trade);

            collector.addOrder(new WeightedPosition(position), new WeightedTrade(trade));
            return(position);
        }
Beispiel #6
0
        public Dictionary <string, double> values(StatisticsCollector collector)
        {
            Bomb.when(collector.pnl().Count == 0, () => "must have at least one observation");
            collector.cacheAllDrawdowns(allDrawdowns(collector));
            var result = dictionary(calculators.Keys, name => calculators[name](collector));

            collector.cacheAllDrawdowns(null);
            return(result);
        }
Beispiel #7
0
        void addClosedPosition(StatisticsCollector collector, double pnl, int barsHeld)
        {
            var order    = symbol().buy("buy one", market(), 1, oneBar()).placed();
            var position = addTrade(order, collector, -0.015625, 0.015625, 1);

            O.zeroTo(barsHeld, i => position.newBar());
            var exit = position.exit("get out", market(), oneBar()).placed();

            addTrade(exit, collector, pnl + 0.015625, 0.015625, 1);
        }
Beispiel #8
0
        static double kappaRatio(StatisticsCollector collector, int moment)
        {
            var pnl = collector.pnl();

            if (all(pnl, p => p == 0))
            {
                return(0);
            }
            return(average(pnl) / Math.Pow(lowerPartialMoment(pnl, moment), 1.0 / moment));
        }
Beispiel #9
0
        static double averageDrawdownRecoveryTime(StatisticsCollector collector)
        {
            var drawdowns = closedDrawdowns(collector);

            if (drawdowns.Count == 0)
            {
                return(0);
            }
            return(drawdowns.Count == 0 ? 0 : average(convert(drawdowns, d => (double)d.recoveryTime())));
        }
Beispiel #10
0
        static double averageDrawdown(StatisticsCollector collector)
        {
            var drawdowns = collector.allDrawdowns();

            if (drawdowns.Count == 0)
            {
                return(0);
            }
            return(-average(convert(drawdowns, d => d.size())));
        }
Beispiel #11
0
        public void addOrder(StatisticsCollector collector, Position position, Trade trade)
        {
            if (!collects(position))
            {
                return;
            }
            var w = weight(position);

            collector.addOrder(new WeightedPosition(position, w), new WeightedTrade(trade, w));
        }
Beispiel #12
0
        static IEnumerable <double> collapsedPnl(StatisticsCollector collector, Converter <DateTime, DateTime> toKey)
        {
            var bucketed = new Dictionary <DateTime, double>();

            each(collector.dates(), collector.pnl(), (barDate, pnl) => {
                var key = toKey(barDate);
                double total;
                bucketed.TryGetValue(key, out total);
                bucketed[key] = total + pnl;
            });
            return(convert(sort(bucketed.Keys), key => bucketed[key]));
        }
Beispiel #13
0
        public void testMaxDrawdown()
        {
            var collector = new StatisticsCollector(arguments());
            var position  = addOpenPosition(collector, 0.0, 1);

            oneBar(collector, position, 10, 10000, 0);
            oneBar(collector, position, 8, 8000, -2000);
            oneBar(collector, position, 11, 11000, -2000);
            oneBar(collector, position, 8, 8000, -3000);
            oneBar(collector, position, 6, 6000, -5000);
            oneBar(collector, position, 8, 8000, -5000);
            oneBar(collector, position, 12, 12000, -5000);
        }
Beispiel #14
0
        static double maxDrawdown(StatisticsCollector collector)
        {
            var pnl = collector.pnl();

            if (isEmpty(pnl))
            {
                return(0);
            }
            var equity        = cumulativeSum(pnl);
            var highWaterMark = cumulativeMax(equity);

            return(min(subtract(equity, highWaterMark)));
        }
Beispiel #15
0
        static List <Drawdown> closedDrawdowns(StatisticsCollector collector)
        {
            var drawdowns = copy(collector.allDrawdowns());

            if (isEmpty(drawdowns))
            {
                return(drawdowns);
            }
            if (last(drawdowns).isOpen())
            {
                drawdowns.RemoveAt(drawdowns.Count - 1);
            }
            return(drawdowns);
        }
Beispiel #16
0
        public void addBar(StatisticsCollector collector, System system, Dictionary <Symbol, Bar> bars, Dictionary <Symbol, double> fxRates)
        {
            var symbols = weights.Keys;
            var myBars  = dictionary(accept(bars, entry => weights.ContainsKey(entry.Key)));

            if (isEmpty(myBars))
            {
                return;
            }

            var ours     = collect(symbols, symbol => system.positions(symbol));
            var weighted = convert(ours, p => new WeightedPosition(p, weight(p)));

            collector.addBar(weighted, myBars, fxRates);
        }
Beispiel #17
0
        void doSomeTrades(StatisticsCollector collector)
        {
            var first = addTrade(symbol().buy("buy", market(), 3, oneBar()).placed(), collector, 100, 0, 1.05);

            addBar(collector, O.list(first), 99, 1);
            addBar(collector, O.list(first), 103, 1.2);
            addBar(collector, O.list(first), 97, 1.1);
            addTrade(first.exit("out", market(), oneBar()).placed(), collector, 101, 0, 1.1);
            var second = addTrade(symbol().sell("sell", market(), 7, oneBar()).placed(), collector, 102, 0, 1.1);

            addBar(collector, O.list(second), 100, 1.4);
            addBar(collector, O.list(second), 101, 1.3);
            addTrade(second.exit("out", market(), oneBar()).placed(), collector, 99, 0, 1.3);
            addBar(collector, 99, 0.9);
        }
Beispiel #18
0
        public void testForeignExchangeFXConversion()
        {
            symbol().setBigPointValue(5000);

            var collector = new StatisticsCollector(arguments());

            doSomeTrades(collector);

            O.each(O.list(-90000.0, 369000, -253500, -907000, 304500, 91000), collector.pnl(), (a, b) => AlmostEqual(a, b, 1e-8));
            var metrics = collector.metrics();

            AreEqual(1, metrics["QWinningTrades"]);
            AlmostEqual(91500, metrics["QAverageWin"], 1e-8);
            AlmostEqual(-577500, metrics["QAverageLoss"], 1e-8);
            AlmostEqual(-486000, metrics["QNetProfit"], 1e-8);
        }
Beispiel #19
0
        // conditional: average one to n.alpha instead of n.alppha alone
        static double percentileDrawdown(StatisticsCollector collector, double percentile, bool isConditional)
        {
            var drawdowns = collector.allDrawdowns();
            var notEnough = percentile == 0.1 ? drawdowns.Count < 10 : drawdowns.Count < 5;

            if (notEnough)
            {
                return(0);
            }
            var nAlpha = (int)Math.Floor(drawdowns.Count * percentile) - 1;

            if (isConditional)
            {
                return(-average(convert(sort(drawdowns).GetRange(0, nAlpha + 1), dd => dd.size())));
            }
            return(-sort(drawdowns)[nAlpha].size());
        }
Beispiel #20
0
        static double kRatio(StatisticsCollector collector)
        {
            var pnl = collector.pnl();

            if (all(pnl, p => p == 0))
            {
                return(0);
            }

            var equity     = cumulativeSum(pnl);
            var regression = new SimpleRegression();

            eachIt(equity, (i, p) => regression.addData(i + 1, p));
            var b1       = regression.getSlope();
            var stdError = regression.getSlopeStdErr();

            return(b1 / (stdError * Math.Sqrt(pnl.Count)));
        }
Beispiel #21
0
        public void testForeignExchangeFXConversionCanBeTurnedOff()
        {
            symbol().setBigPointValue(5000);

            var args = arguments();

            args.runInNativeCurrency = true;
            var collector = new StatisticsCollector(args);

            doSomeTrades(collector);

            O.each(O.list(-15000.0, 60000, -90000, 130000, -35000, 70000), collector.pnl(), (a, b) => AlmostEqual(a, b, 1e-8));
            var metrics = collector.metrics();

            AreEqual(2, metrics["QWinningTrades"]);
            AlmostEqual(60000, metrics["QAverageWin"], 1e-8);
            AlmostEqual(0, metrics["QAverageLoss"], 1e-8);
            AlmostEqual(120000, metrics["QNetProfit"], 1e-8);
        }
Beispiel #22
0
 static double losingTradesPercent(StatisticsCollector collector)
 {
     return(safeDivide(0, LOSING_TRADES(collector), TOTAL_FINISHED_TRADES(collector)));
 }
Beispiel #23
0
        public void testMetricCalcs()
        {
            var collector = new StatisticsCollector(arguments());

            addClosedPosition(collector, 100.0, 1);
            addClosedPosition(collector, 90.0, 2);
            addClosedPosition(collector, -90.25, 3);
            addClosedPosition(collector, 0, 4);
            addClosedPosition(collector, -98.25, 5);

            var position = addOpenPosition(collector, 95.0, 10);

            addBar(collector, position, 96, 1);
            AreEqual(11.50 * symbol().bigPointValue, collector.netProfit());

            addBar(collector, position, 97, 1);
            AreEqual(21.50 * symbol().bigPointValue, collector.netProfit());
            addBar(collector, position, 92, 1);
            addBar(collector, position, 97, 1);

            var expectedMetrics = new Dictionary <string, double> {
                { "QDownsideDeviation", 50000 },
                { "QStandardDeviation", 41298.4563876182 },
                { "QStandardDeviationWeekly", 0 },
                { "QStandardDeviationMonthly", 0 },
                { "QSharpeRatio", 3.99276123210182 },
                { "QSharpeRatioWeekly", 0 },
                { "QSharpeRatioMonthly", 0 },
                { "QNetProfitPerMaxDrawdown", 21500 / 50000.0 },
                { "QLargestLossPerAverageLoss", 98250 / 94250.0 },
                { "QLargestLossPerGrossLoss", 98250 / 188500.0 },
                { "QLargestWinPerAverageWin", 100000 / 95000.0 },
                { "QLargestWinPerGrossProfit", 100000 / 190000.0 },
                { "QLargestWinPerNetProfit", 100000 / 21500.0 },
                { "QWinLossRatio", 1.00795755968170 },
                { "QAverageTrade", 21500 / 6.0 },
                { "QExpectancy", -0.196816976127321 },
                { "QTradesPerBar", 1.5 },
                { "QExpectancyScore", -0.295225464190981 },
                { "QLargestWinningTrade", 100000 },
                { "QLargestLosingTrade", -98250 },
                { "QAverageLoss", -94250 },
                { "QAverageWin", 95000 },
                { "QRealizedNetProfit", 1500 },
                { "QRealizedGrossLoss", -188500 },
                { "QRealizedGrossProfit", 190000 },
                { "QAverageProfit", 300 },
                { "QNetProfit", 21500 },
                { "QUnrealizedNetProfit", 20000 },
                { "QWinningTradesPct", 0.40 },
                { "QLosingTradesPct", 0.40 },
                { "QNeutralTrades", 1 },
                { "QWinningTrades", 2 },
                { "QLosingTrades", 2 },
                { "QLongWinningTrades", 2 },
                { "QLongLosingTrades", 2 },
                { "QShortWinningTrades", 0 },
                { "QShortLosingTrades", 0 },
                { "QMaxConsecutiveWinningTrades", 2 },
                { "QMaxConsecutiveLosingTrades", 1 },
                { "QTotalFinishedTrades", 5 },
                { "QTotalTrades", 6 },
                { "QAverageLosingBarsHeld", 4 },
                { "QAverageWinningBarsHeld", 1.5 },
                { "QAverageBarsHeld", 3 },
                { "QWinningBarsHeld", 3 },
                { "QLosingBarsHeld", 8 },
                { "QTotalBarsHeld", 15 },
                { "QMaxDrawdown", -50000 },
                { "QKRatio", -0.077151674981046 },
                { "QAnnualizedNetProfit", 2617625 },
                { "QCalmarRatio", 52.3525 },
                { "QConditionalTenPercentileCalmarRatio", 0 },
                { "QConditionalTwentyPercentileCalmarRatio", 0 },
                { "QAverageDrawdown", -50000 },
                { "QAverageDrawdownTime", 2 },
                { "QAverageDrawdownRecoveryTime", 1 },
                { "QTenPercentileDrawdown", 0 },
                { "QConditionalTenPercentileDrawdown", 0 },
                { "QTwentyPercentileDrawdown", 0 },
                { "QConditionalTwentyPercentileDrawdown", 0 },
                { "QSortinoRatio", 4.74463644550349 },
                { "QOmegaRatio", 1.43 },
                { "QUpsidePotentialRatio", 0.476666666666667 },
                { "QTotalSlippage", 156.25 },
                { "QAverageSlippagePerWinningTrade", 31.25 },
                { "QAverageSlippagePerLosingTrade", 31.25 }
            };

            var metrics = collector.metrics();

            O.each(expectedMetrics, (name, value) => AlmostEqual(value, Bomb.missing(metrics, name), 1e-10));
            AreEqual(expectedMetrics.Count, metrics.Count);
        }
Beispiel #24
0
 static double annualizedNetProfit(StatisticsCollector collector)
 {
     return(NET_PROFIT(collector) / yearsInCollector(collector));
 }
Beispiel #25
0
 void oneBar(StatisticsCollector collector, Position position, double close, double expectedProfit, double expectedDrawdown)
 {
     addBar(collector, position, close, 1);
     AreEqual(expectedProfit, collector.netProfit());
     AreEqual(expectedDrawdown, Metrics.MAX_DRAWDOWN(collector));
 }
Beispiel #26
0
 void addBar(StatisticsCollector collector, Position position, double close, double fxRate)
 {
     addBar(collector, O.list(position), close, fxRate);
 }
Beispiel #27
0
 static double annualizationFactor(StatisticsCollector collector)
 {
     return(Math.Sqrt(count(collector.pnl()) / yearsInCollector(collector)));
 }
Beispiel #28
0
        static double upsidePotentialRatio(StatisticsCollector collector)
        {
            var pnl = collector.pnl();

            return(semiDeviation(pnl, 1, true) / semiDeviation(pnl, 2, false));
        }
Beispiel #29
0
 void addBar(StatisticsCollector collector, double close, double fxRate)
 {
     addBar(collector, new List <Position>(), close, fxRate);
 }
Beispiel #30
0
        Position addOpenPosition(StatisticsCollector collector, double price, int size)
        {
            var order = symbol().buy("buy one", market(), size, oneBar()).placed();

            return(addTrade(order, collector, price - 0.015625, 0.015625, 1));
        }