예제 #1
0
        public List <decimal> maxDiffs   = new List <decimal>(); //The higher of high or low diff for each day

        public void Calculate()
        {
            foreach (SingleRangeResult srr in singleRangeResults)
            {
                highDiffs.Add(srr.startHighDiff);
                lowDiffs.Add(srr.startLowDiff);
                closeDiffs.Add(Math.Abs(srr.startCloseDiff));
                maxDiffs.Add(Math.Max(srr.startHighDiff, Math.Abs(srr.startLowDiff)));


                if (srr.startHighDiff > greatestHighDiff)
                {
                    greatestHighDiff = srr.startHighDiff;
                }
                if (srr.startLowDiff < greatestLowDiff)
                {
                    greatestLowDiff = srr.startLowDiff;
                }
                if (Math.Abs(srr.startCloseDiff) > Math.Abs(srr.startCloseDiff))
                {
                    greatestCloseDiff = srr.startCloseDiff;
                }
            }

            averageStartHighDiff  = TechnicalAnalysis.Average(highDiffs);
            averageStartLowDiff   = TechnicalAnalysis.Average(lowDiffs);
            averageStartCloseDiff = TechnicalAnalysis.Average(closeDiffs);
            averageMaxDiff        = TechnicalAnalysis.Average(maxDiffs);
        }
예제 #2
0
파일: Form1.cs 프로젝트: m-valen/backtester
        private void button5_Click(object sender, EventArgs e)
        {
            List <KeyValuePair <string, decimal> > ratios       = new List <KeyValuePair <string, decimal> >();
            Dictionary <string, decimal>           ratiosSorted = new Dictionary <string, decimal>();

            foreach (string symbol in symbols)
            {
                List <decimal>        dailyRanges = new List <decimal>();
                List <List <string> > candles     = new List <List <string> >();
                decimal ratio = 999999999999999;
                foreach (string date in dates)
                {
                    //decimal tradingRange = TechnicalAnalysis.TradingRange(symbol, date, DataHelper.GetMsOfDay("9:35:00:0:AM"), DataHelper.GetMsOfDay("4:00:00:0:PM"));
                    //dailyRanges.Add(tradingRange);

                    //Console.WriteLine(date + " - " + tradingRange.ToString());
                    //Find average true range of candles
                    candles = FileHelper.getCandles(symbol, date, 1);
                }
                decimal averageDailyRange = TechnicalAnalysis.Average(dailyRanges);
                decimal candleATR         = TechnicalAnalysis.ATR(candles);


                if (averageDailyRange > 0 && candleATR > 0)
                {
                    ratio = averageDailyRange / candleATR; // Lower the better

                    ratios.Insert(0, new KeyValuePair <string, decimal>(symbol, ratio));
                }

                //ratios2.Add(symbol, Convert.ToDouble(ratio));

                //Console.WriteLine(symbol + " - " + ratio)
                //Console.WriteLine(symbol + " - " + averageRange);
                Console.WriteLine(symbol + " - " + ratio.ToString("#.###") + ": Candle ATR - " + candleATR.ToString("#.###") + ", Average Daily Range - " + averageDailyRange.ToString("#.##"));
            }

            //var sort_by_value = from r in ratios2 orderby r.Value select r
            ratios.Sort(delegate(KeyValuePair <string, decimal> firstPair, KeyValuePair <string, decimal> secondPair)
            {
                return(firstPair.Value.CompareTo(secondPair.Value));
            });

            foreach (KeyValuePair <string, decimal> pair in ratios)
            {
                ratiosSorted.Add(pair.Key, pair.Value);
                Console.WriteLine(pair.Key + " - " + pair.Value.ToString());
            }
        }
예제 #3
0
        public void Run()
        {
            foreach (List <string> symbolParam in backtestSymbolParams)
            {
                SymbolRangeResult symbolRangeResult = new SymbolRangeResult();

                symbol = symbolParam[0];
                dates  = backtestSymbolDates[symbol];

                List <decimal> singleResult = new List <decimal>();

                int startMs = DataHelper.GetMsOfDay(symbolParam[1]);
                int endMs   = DataHelper.GetMsOfDay(symbolParam[2]);

                foreach (string date in dates)
                {
                    singleResult = TechnicalAnalysis.TradingRange(symbol, date, startMs, endMs);
                    SingleRangeResult srr = new SingleRangeResult();
                    srr.startTime = symbolParam[1];
                    srr.endTime   = symbolParam[2];

                    srr.startPrice = singleResult[0];
                    srr.endPrice   = singleResult[1];
                    srr.high       = singleResult[2];
                    srr.low        = singleResult[3];
                    srr.date       = date;

                    srr.Calculate();

                    symbolRangeResult.singleRangeResults.Add(srr);
                }
                symbolRangeResult.Calculate();
                symbolRangeResults.Add(symbolRangeResult);
            }

            GenerateExcel();
            symbolRangeResults.Clear();
        }
예제 #4
0
        public void CalculateTotals()
        {
            List <decimal> maxUnrealizeds = new List <decimal>();
            List <decimal> minUnrealizeds = new List <decimal>();
            List <decimal> wins           = new List <decimal>();
            List <decimal> losses         = new List <decimal>();
            List <decimal> _completeFills = new List <decimal>();


            foreach (SingleResult sr in SingleResults)
            {
                BuyFills += sr.BuyFills;
                _buyFills.Add(sr.BuyFills);
                SellFills += sr.SellFills;
                _sellFills.Add(sr.SellFills);
                IncrementPL += sr.IncrementPL;
                PriceMovePL += sr.PriceMovePL;
                TotalPL     += sr.TotalPL;
                maxUnrealizeds.Add(sr.maxUnrealized);
                minUnrealizeds.Add(sr.minUnrealized);
                if (sr.TotalPL > 0)
                {
                    wins.Add(sr.TotalPL);
                }
                else if (sr.TotalPL < 0)
                {
                    losses.Add(sr.TotalPL);
                }

                //Range stuff
                highDiffs.Add(sr.startHighDiff);
                lowDiffs.Add(sr.startLowDiff);
                closeDiffs.Add(Math.Abs(sr.startCloseDiff));
                decimal maxDiff = Math.Max(sr.startHighDiff, Math.Abs(sr.startLowDiff));
                maxDiffs.Add(maxDiff);

                if (maxDiff >= (IncrementPrice * 7))
                {
                    numPriceStops[0]++; numPriceStops[1]++; numPriceStops[2]++; numPriceStops[3]++;
                }
                else if (maxDiff >= (IncrementPrice * 6))
                {
                    numPriceStops[0]++; numPriceStops[1]++; numPriceStops[2]++;
                }
                else if (maxDiff >= (IncrementPrice * 5))
                {
                    numPriceStops[0]++; numPriceStops[1]++;
                }
                else if (maxDiff >= (IncrementPrice * 4))
                {
                    numPriceStops[0]++;
                }


                if (sr.startHighDiff > greatestHighDiff)
                {
                    greatestHighDiff = sr.startHighDiff;
                }
                if (sr.startLowDiff < greatestLowDiff)
                {
                    greatestLowDiff = sr.startLowDiff;
                }
                if (Math.Abs(sr.startCloseDiff) > Math.Abs(greatestCloseDiff))
                {
                    greatestCloseDiff = sr.startCloseDiff;
                }


                CompleteFills += sr.CompleteFills;

                highestUnrealizeds.Add(sr.maxUnrealized);
            }
            if (IncrementPL > 0)
            {
                ProfitMargin = (TotalPL / IncrementPL) * 100;
            }
            else
            {
                ProfitMargin = Convert.ToDecimal(-9999.99);
            }
            AvgMaxUnrealized = TechnicalAnalysis.Average(maxUnrealizeds);
            AvgMinUnrealized = TechnicalAnalysis.Average(minUnrealizeds);
            AvgWin           = TechnicalAnalysis.Average(wins);
            AvgLoss          = TechnicalAnalysis.Average(losses);
            NumWins          = wins.Count;
            NumLosses        = losses.Count;

            //Buying Power
            decimal buyingPower = 0;

            foreach (SingleResult sr in SingleResults)
            {
                if (sr.MaxBuyingPower > buyingPower)
                {
                    buyingPower = sr.MaxBuyingPower;
                }
            }
            BuyingPower = buyingPower;

            yield = (IncrementPL / buyingPower) * 100;

            averageStartHighDiff  = TechnicalAnalysis.Average(highDiffs);
            averageStartLowDiff   = TechnicalAnalysis.Average(lowDiffs);
            averageStartCloseDiff = TechnicalAnalysis.Average(closeDiffs);
            averageMaxDiff        = TechnicalAnalysis.Average(maxDiffs);
            averageMaxRangeSteps  = averageMaxDiff / IncrementPrice;

            averageBuyFills  = TechnicalAnalysis.Average(_buyFills);
            averageSellFills = TechnicalAnalysis.Average(_sellFills);

            averageCompleteFills = Convert.ToDecimal(CompleteFills) / Convert.ToDecimal(SingleResults.Count);

            stepFillRatio = averageCompleteFills / (((averageMaxRangeSteps * averageMaxRangeSteps) - averageMaxRangeSteps) / 2);

            //Medians

            medianMaxDiff       = TechnicalAnalysis.Median(maxDiffs);
            medianMaxRangeSteps = medianMaxDiff / IncrementPrice;
            if (medianMaxRangeSteps > 1)
            {
                medianStepFillRatio = averageCompleteFills / (((medianMaxRangeSteps * medianMaxRangeSteps) - medianMaxRangeSteps) / 2);
            }
            else
            {
                medianStepFillRatio = 0;
            }

            //Calculate variance

            decimal sumSquareds    = 0;
            decimal sumDiffsMean   = 0;
            decimal sumDiffsMedian = 0;
            decimal sumDiffsCapped = 0;

            foreach (SingleResult sr in SingleResults)
            {
                sumSquareds    += Convert.ToDecimal(Math.Pow(Convert.ToDouble(Math.Max(Math.Abs(sr.startHighDiff * 100), Math.Abs(sr.startLowDiff * 100)) - (averageMaxDiff * 100)), 2));
                sumDiffsMean   += Convert.ToDecimal(Math.Abs(Math.Max(Math.Abs(sr.startHighDiff), Math.Abs(sr.startLowDiff)) - averageMaxDiff));
                sumDiffsMedian += Convert.ToDecimal(Math.Abs(Math.Max(Math.Abs(sr.startHighDiff), Math.Abs(sr.startLowDiff)) - medianMaxDiff));
                sumDiffsCapped += Convert.ToDecimal(Math.Abs(Math.Min(Math.Abs(Math.Max(Math.Abs(sr.startHighDiff), Math.Abs(sr.startLowDiff))), (IncrementPrice * Convert.ToDecimal(7.1))) - medianMaxDiff));
            }

            if (SingleResults.Count > 1)
            {
                varianceSquares = sumSquareds / (SingleResults.Count - 1) / 100;
            }
            varianceSquaresNormalized = varianceSquares / (averageMaxDiff * 100 * averageMaxDiff / 100);

            variance = sumDiffsMean / SingleResults.Count;

            varianceNormalized = variance / medianMaxDiff;

            varianceStopCapped = sumDiffsCapped / SingleResults.Count;

            varianceStopCappedNormalized = varianceStopCapped / medianMaxDiff;

            medianVariance = sumDiffsMedian / SingleResults.Count;

            medianVarianceNormalized = medianVariance / medianMaxDiff;

            //Average/Median Win Module

            /*
             *  public decimal highestUnrealized;
             *  public int daysAboveAverageWin;
             *  public int daysGaveBackAverageWin;
             *  public decimal medianWin;
             *
             * */

            foreach (SingleResult sr in SingleResults)
            {
                if (sr.maxUnrealized > highestMaxUnrealized)
                {
                    highestMaxUnrealized = sr.maxUnrealized;
                }
                if (sr.TotalPL > AvgWin)
                {
                    daysAboveAverageWin++;
                }
                if (sr.maxUnrealized > AvgWin && sr.TotalPL < AvgWin)
                {
                    daysGaveBackAverageWin++;
                }
            }
            if (wins.Count >= 1)
            {
                medianWin = TechnicalAnalysis.Median(wins);
            }
            else
            {
                medianWin = 0;
            }
            if (maxUnrealizeds.Count >= 1)
            {
                medianMaxUnrealized = TechnicalAnalysis.Median(maxUnrealizeds);
            }
        }
예제 #5
0
        public SingleResult RunSingle(string sym, string _date, decimal _incrementPrice, string _startTime, string _endTime, int _incrementSize, int _autoBalanceThreshold, int _hardStopPL)
        {
            Debug.WriteLine(_date + " - " + sym + "\n");
            //Backtest settings

            int startMs = 0;
            int endMs   = 0;

            //First, be sure file is available

            filePath = "./Data/Ticks/" + symbol + "/" + symbol + _date + ".csv";

            incrementPrice = _incrementPrice;
            incrementSize  = _incrementSize;

            startMs = GetMsOfDay(_startTime);
            endMs   = GetMsOfDay(_endTime);



            if (!File.Exists(filePath))
            {
                Console.WriteLine("No file found");
                return(null);
            }
            List <List <String> > ticks = new List <List <String> >();

            //Read in csv
            using (var fs = File.OpenRead(filePath))
                using (var reader = new StreamReader(fs))
                {
                    int count = 0;
                    while (!reader.EndOfStream)
                    {
                        var line   = reader.ReadLine();
                        var values = line.Split(',');
                        if (!(count == 0))
                        {
                            ticks.Add(new List <String> {
                                values[0], (values[1]), values[2], values[3], values[4]
                            });                                                                                  //MsOfDay, Time, Price, Size, Trade Condition   4:14:10.285, 62.27, 200
                        }
                        count = 1;
                    }
                }

            List <int> acceptableTradeConditions = new List <int> {
                0, 1, 9, 11, 51, 62, 66, 95, 115
            };

            int     buyFills       = 0;
            int     sellFills      = 0;
            int     symbolPosition = 0;
            decimal priceMovePL    = 0;
            decimal incrementPL    = 0;
            decimal totalPL        = 0;
            decimal maxUnrealized  = Convert.ToDecimal(-99999.99);
            decimal minUnrealized  = Convert.ToDecimal(99999.99);
            int     maxLong        = 0;
            int     maxShort       = 0;
            int     maxPosition    = 0;
            decimal currentBP      = 0;
            decimal maxBP          = 0; //(greatest of maxLong, maxShort) + 500 * price


            decimal highPrint = 0;
            decimal lowPrint  = Convert.ToDecimal(9999999.99);

            bool   isStopped = false;
            string stopTime  = "";

            decimal startingPrice = Convert.ToInt32(99999999.00);
            decimal previousPrint = Convert.ToInt32(99999999.00);

            decimal[] orderLevel1 = new decimal[2] {
                0, incrementSize
            };                                                           //level price, level size
            decimal[] orderLevel2 = new decimal[2] {
                0, incrementSize
            };
            decimal[][] closestOrders = new decimal[][] { orderLevel1, orderLevel2 };


            int sellFillVolume = 0;
            int buyFillVolume  = 0;

            int tickCount = 0;

            //Anomalous tick variables
            List <decimal> recentPriceChanges = new List <decimal>();  //Most recent 50 price changes
            //decimal previousTickPrice = 0;   is called previousprint
            decimal previousPriceChangeTick = 0;
            decimal priceChange;

            if (strategy == "Parabolic")
            {
                GL = new GradientLevels();

                GL.lastFillIndex     = GL.middleIndex;
                GL.furthestFillIndex = GL.middleIndex;
                GL.baseLot           = incrementSize;
                GL.zeroIndex         = GL.middleIndex;
                //fillIndex = GL.middleIndex;
                lastFillIndex = GL.middleIndex;
                fillIndex     = lastFillIndex;
            }

            foreach (List <String> tick in ticks)
            {
                //Skip manually selected ticks
                if (tick[0] == "*")
                {
                    continue;
                }
                //Time Constraint
                int tradeCondition = Convert.ToInt32(tick[4]);
                if (!(acceptableTradeConditions.Contains(tradeCondition)))
                {
                    continue;   //Don't process trade condition
                }


                int tickMs = Convert.ToInt32(tick[0]);
                if (tickMs >= startMs && tickMs <= endMs && !isStopped)
                {
                    tickCount++;
                    decimal tickPrice  = Convert.ToDecimal(tick[2]);
                    int     tickVolume = Convert.ToInt32(tick[3]);

                    if (_date == "20170421")
                    {
                        int a = 1;
                    }

                    if (tickCount == 1)
                    {
                        startingPrice = tickPrice;
                        if (hardStopType == "IncrementSteps")
                        {
                            setStops(startingPrice, incrementPrice, stopIncrements);
                        }

                        previousPrint           = startingPrice;
                        previousPriceChangeTick = startingPrice;

                        if (strategy == "Toggle")
                        {
                            closestOrders[0][0] = startingPrice - incrementPrice;
                            closestOrders[1][0] = startingPrice + incrementPrice;
                        }

                        else if (strategy == "Parabolic")
                        {
                            GL.Initialize(startingPrice, incrementPrice);

                            closestOrders[0][0] = Convert.ToDecimal(GL.Levels[GL.middleIndex - 1][0]);
                            closestOrders[1][0] = Convert.ToDecimal(GL.Levels[GL.middleIndex + 1][0]);
                        }
                    }



                    //Anomalous tick catcher + trade condition exclusion
                    priceChange = Math.Abs(tickPrice - previousPriceChangeTick);

                    if (priceChange >= Convert.ToDecimal(0.01)) //Valid price change
                    {
                        if (recentPriceChanges.Count < 10)      //Count first 10 price changes as valid
                        {
                            recentPriceChanges.Add(priceChange);
                            previousPriceChangeTick = tickPrice;
                        }
                        else if (priceChange > (TechnicalAnalysis.Average(recentPriceChanges) * 10) && priceChange > (tickPrice * Convert.ToDecimal(0.002))) //Anomalous Print
                        {
                            continue;                                                                                                                        //Don't process anomalous tick
                        }
                        //Trade condition catcher
                        else  //Valid price change
                        {
                            if (recentPriceChanges.Count >= 100)
                            {
                                recentPriceChanges.RemoveAt(0);
                            }
                            recentPriceChanges.Add(priceChange);
                            previousPriceChangeTick = tickPrice;
                        }
                    }


                    if (hardStopType == "IncrementSteps")
                    {
                        if (tickPrice >= highStop)
                        {
                            isStopped = true;
                            stopTime  = tick[1];
                        }
                        else if (tickPrice <= lowStop)
                        {
                            isStopped = true;
                            stopTime  = tick[1];
                        }
                    }


                    if (strategy == "Toggle")
                    {
                        while (tickPrice < closestOrders[0][0]) // Buy Fill
                        {
                            buyFillVolume += tickVolume;
                            if (buyFillVolume >= closestOrders[0][1]) //Complete fill
                            {
                                buyFills++;
                                closestOrders[0][0] -= incrementPrice;
                                closestOrders[1][0] -= incrementPrice;
                                tickVolume          -= Convert.ToInt32(closestOrders[0][1]);
                                sellFillVolume       = 0;
                                buyFillVolume        = 0;
                                if (symbolPosition > 0)
                                {
                                    priceMovePL -= symbolPosition * incrementPrice;
                                }
                                else if (symbolPosition < 0)
                                {
                                    priceMovePL -= (symbolPosition + incrementSize) * incrementPrice;
                                    incrementPL += incrementSize * incrementPrice;
                                }
                                symbolPosition += Convert.ToInt32(closestOrders[0][1]);
                                if (symbolPosition >= autoBalanceThreshold)   // too long
                                {
                                    closestOrders[1][1] = incrementSize * 2;
                                }
                                else if (symbolPosition <= -(autoBalanceThreshold))  //too short
                                {
                                    closestOrders[0][1] = incrementSize * 2;
                                }
                                else
                                {
                                    closestOrders[0][1] = incrementSize;
                                    closestOrders[1][1] = incrementSize;
                                }
                                if (symbolPosition >= maxShares)
                                {
                                    closestOrders[0][1] = 0;
                                }
                                else if (symbolPosition <= -(maxShares))
                                {
                                    closestOrders[1][1] = 0;
                                }
                            }
                            else
                            {
                                buyFillVolume += tickVolume;
                                break;
                            }
                        }
                        while (tickPrice > closestOrders[1][0])
                        {
                            sellFillVolume += tickVolume;
                            if (sellFillVolume >= closestOrders[1][1]) //Complete fill
                            {
                                sellFills++;
                                closestOrders[0][0] += incrementPrice;
                                closestOrders[1][0] += incrementPrice;
                                tickVolume          -= Convert.ToInt32(closestOrders[1][1]);
                                sellFillVolume       = 0;
                                buyFillVolume        = 0;
                                if (symbolPosition < 0)
                                {
                                    priceMovePL += symbolPosition * incrementPrice;
                                }
                                else if (symbolPosition > 0)
                                {
                                    priceMovePL += (symbolPosition - incrementSize) * incrementPrice;
                                    incrementPL += incrementSize * incrementPrice;
                                }
                                symbolPosition -= Convert.ToInt32(closestOrders[1][1]);

                                if (symbolPosition >= autoBalanceThreshold)
                                {
                                    closestOrders[1][1] = incrementSize * 2;
                                }
                                else if (symbolPosition <= -(autoBalanceThreshold))
                                {
                                    closestOrders[0][1] = incrementSize * 2;
                                }
                                else
                                {
                                    closestOrders[0][1] = incrementSize;
                                    closestOrders[1][1] = incrementSize;
                                }
                                if (symbolPosition >= maxShares)
                                {
                                    closestOrders[0][1] = 0;
                                }
                                else if (symbolPosition <= -(maxShares))
                                {
                                    closestOrders[1][1] = 0;
                                }
                            }
                            else
                            {
                                buyFillVolume += tickVolume;
                                break;
                            }
                        }

                        //update totalPL, and min/max unrealized values
                        totalPL = incrementPL + priceMovePL;
                    }

                    if (strategy == "Parabolic")
                    {
                        while (tickPrice < closestOrders[0][0]) // Buy Fill
                        {
                            buyFillVolume += tickVolume;
                            if (buyFillVolume >= closestOrders[0][1]) //Complete fill
                            {
                                buyFills++;
                                //Update metrics
                                if (symbolPosition > 0) //Long
                                {
                                    totalPL -= Math.Abs(symbolPosition) * incrementPrice;
                                }
                                else if (symbolPosition < 0)  //Short
                                {
                                    totalPL += Math.Abs(symbolPosition) * incrementPrice;
                                }

                                symbolPosition += Convert.ToInt32(closestOrders[0][1]);  //Update new symbol position



                                //Update order levels
                                if (fillIndex > 0)
                                {
                                    fillIndex = --lastFillIndex;
                                }

                                Console.WriteLine(symbolPosition + " shares at index " + fillIndex + " for Total PL: " + totalPL);
                                if (_date == "20170228")
                                {
                                    int a = 1;
                                }
                                int reCalc = GL.ReCalculate(fillIndex);

                                if (reCalc == 1)
                                {
                                    Debug.WriteLine("Fill Error");
                                }

                                tickVolume    -= Convert.ToInt32(closestOrders[0][1]);
                                sellFillVolume = 0;
                                buyFillVolume  = 0;

                                if (fillIndex != 0)
                                {
                                    closestOrders[0][0] = Convert.ToDecimal(GL.Levels[fillIndex - 1][0]);
                                    closestOrders[0][1] = Convert.ToDecimal(GL.Levels[fillIndex - 1][1]);
                                }
                                else
                                {
                                    closestOrders[0][0] = Convert.ToDecimal(0);
                                    closestOrders[0][1] = Convert.ToDecimal(0);
                                }
                                closestOrders[1][0] = Convert.ToDecimal(GL.Levels[fillIndex + 1][0]);
                                closestOrders[1][1] = Convert.ToDecimal(GL.Levels[fillIndex + 1][1]);


                                //Update last filled index

                                if (GL.isRezero)
                                {
                                    if (_date == "20170301")
                                    {
                                        int a = 1;
                                    }
                                    lastFillIndex = GL.middleIndex;
                                    fillIndex     = lastFillIndex;
                                    setStops(Convert.ToDecimal(GL.Levels[lastFillIndex][0]), incrementPrice, stopIncrements);
                                    closestOrders[0][0] = Convert.ToDecimal(GL.Levels[fillIndex - 1][0]);
                                    closestOrders[0][1] = Convert.ToDecimal(GL.Levels[fillIndex - 1][1]);
                                    closestOrders[1][0] = Convert.ToDecimal(GL.Levels[fillIndex + 1][0]);
                                    closestOrders[1][1] = Convert.ToDecimal(GL.Levels[fillIndex + 1][1]);
                                }
                                else
                                {
                                    lastFillIndex = fillIndex;
                                }
                            }
                            else
                            {
                                buyFillVolume += tickVolume;
                                break;
                            }
                        }
                        while (tickPrice > closestOrders[1][0])
                        {
                            sellFillVolume += tickVolume;
                            if (sellFillVolume >= closestOrders[1][1]) //Complete fill
                            {
                                sellFills++;

                                //Update metrics
                                if (symbolPosition > 0) //Long
                                {
                                    totalPL += Math.Abs(symbolPosition) * incrementPrice;
                                }
                                else if (symbolPosition < 0)  //Short
                                {
                                    totalPL -= Math.Abs(symbolPosition) * incrementPrice;
                                }

                                symbolPosition -= Convert.ToInt32(closestOrders[1][1]);  //Update symbol position

                                //Get new order levels

                                if (fillIndex < GL.middleIndex * 2)
                                {
                                    fillIndex = ++lastFillIndex;
                                }

                                Console.WriteLine(symbolPosition + " shares at index " + fillIndex + " for Total PL: " + totalPL);
                                if (_date == "20170228")
                                {
                                    int a = 1;
                                }
                                int reCalc = GL.ReCalculate(fillIndex);

                                if (reCalc == 1)
                                {
                                    Debug.WriteLine("Fill Error");
                                }

                                tickVolume    -= Convert.ToInt32(closestOrders[1][1]);
                                sellFillVolume = 0;
                                buyFillVolume  = 0;

                                closestOrders[0][0] = Convert.ToDecimal(GL.Levels[fillIndex - 1][0]);
                                closestOrders[0][1] = Convert.ToDecimal(GL.Levels[fillIndex - 1][1]);

                                if (fillIndex != GL.middleIndex * 2)
                                {
                                    closestOrders[1][0] = Convert.ToDecimal(GL.Levels[fillIndex + 1][0]);
                                    closestOrders[1][1] = Convert.ToDecimal(GL.Levels[fillIndex + 1][1]);
                                }
                                else
                                {
                                    closestOrders[1][0] = Convert.ToDecimal(99999);
                                    closestOrders[1][1] = Convert.ToDecimal(0);
                                }


                                //Update last filled index

                                if (GL.isRezero)
                                {
                                    lastFillIndex = GL.middleIndex;;
                                    fillIndex     = lastFillIndex;
                                    setStops(Convert.ToDecimal(GL.Levels[lastFillIndex][0]), incrementPrice, stopIncrements);
                                    closestOrders[0][0] = Convert.ToDecimal(GL.Levels[fillIndex - 1][0]);
                                    closestOrders[0][1] = Convert.ToDecimal(GL.Levels[fillIndex - 1][1]);
                                    closestOrders[1][0] = Convert.ToDecimal(GL.Levels[fillIndex + 1][0]);
                                    closestOrders[1][1] = Convert.ToDecimal(GL.Levels[fillIndex + 1][1]);
                                }
                                else
                                {
                                    lastFillIndex = fillIndex;
                                }
                            }
                            else
                            {
                                sellFillVolume += tickVolume;
                                break;
                            }
                        }
                    }



                    decimal tickAdjustedPL = 0;
                    decimal _lastFill      = Convert.ToDecimal(GL.Levels[lastFillIndex][0]);
                    decimal _difference    = tickPrice - _lastFill;

                    if (strategy == "Toggle")      //set tick adjusted PL as price move difference + increment PL
                    {
                        decimal tickAdjustedPriceMovePL = priceMovePL + (symbolPosition * _difference);
                        tickAdjustedPL = tickAdjustedPriceMovePL + incrementPL;
                    }

                    else if (strategy == "Parabolic")
                    {
                        tickAdjustedPL = totalPL + (symbolPosition * _difference);
                    }

                    //if (totalPL > maxUnrealized) maxUnrealized = totalPL;
                    //if (totalPL < minUnrealized) minUnrealized = totalPL;

                    if (tickAdjustedPL > maxUnrealized)
                    {
                        maxUnrealized = tickAdjustedPL;
                        if (_date == "20170228")
                        {
                            Console.WriteLine("Total PL: " + totalPL + ", " + "Max Unrealized: " + maxUnrealized);
                            Console.WriteLine("Tick Price: " + tickPrice + ", " + "Last Fill: " + _lastFill);
                            Console.WriteLine("High Stop: " + highStop + ", Low Stop: " + lowStop);
                        }
                    }
                    if (tickAdjustedPL < minUnrealized)
                    {
                        minUnrealized = tickAdjustedPL;
                        if (_date == "20170228")
                        {
                            Console.WriteLine("Total PL: " + totalPL + ", " + "Min Unrealized: " + minUnrealized);
                            Console.WriteLine("Tick Price: " + tickPrice + ", " + "Last Fill: " + _lastFill);
                            Console.WriteLine("High Stop: " + highStop + ", Low Stop: " + lowStop);
                        }
                    }

                    //check if high print
                    if (tickPrice > highPrint)
                    {
                        highPrint = tickPrice;
                    }
                    if (tickPrice < lowPrint)
                    {
                        lowPrint = tickPrice;
                    }

                    //Hard stop
                    //if (-(totalPL) > hardStopPL)
                    if (hardStopType == "PL" && -(tickAdjustedPL) > hardStopPL)
                    {
                        isStopped = true;
                        stopTime  = tick[1];
                    }

                    //Maxshort, long, BP

                    if (symbolPosition > maxLong)
                    {
                        maxLong = symbolPosition;
                    }
                    if (symbolPosition < maxShort)
                    {
                        maxShort = symbolPosition;
                    }

                    if (maxLong > Math.Abs(maxShort))
                    {
                        maxPosition = maxLong;
                    }
                    else
                    {
                        maxPosition = Math.Abs(maxShort);
                    }

                    currentBP = (Math.Abs(symbolPosition) + 500) * tickPrice;

                    if (currentBP > maxBP)
                    {
                        maxBP = currentBP;
                    }

                    tickCount++;

                    previousPrint = tickPrice;
                }
            }  // End of tick processing

            //Adjust priceMovePL for difference between final print and last fill

            decimal lastFill = 0;

            if (strategy == "Toggle")
            {
                lastFill = closestOrders[0][0] + incrementPrice;
            }
            else if (strategy == "Parabolic")
            {
                lastFill = Convert.ToDecimal(GL.Levels[lastFillIndex][0]);
            }
            decimal finalPrint = previousPrint;
            decimal difference = finalPrint - lastFill;

            SingleResult singleResult = new SingleResult();

            if (strategy == "Toggle")
            {
                priceMovePL += symbolPosition * difference;
                totalPL      = priceMovePL + incrementPL;

                singleResult.Date           = _date;
                singleResult.StartingPrice  = startingPrice;
                singleResult.FinalPrint     = finalPrint;
                singleResult.BuyFills       = buyFills;
                singleResult.SellFills      = sellFills;
                singleResult.Position       = symbolPosition;
                singleResult.PriceMovePL    = priceMovePL;
                singleResult.IncrementPL    = incrementPL;
                singleResult.TotalPL        = totalPL;
                singleResult.maxUnrealized  = maxUnrealized;
                singleResult.minUnrealized  = minUnrealized;
                singleResult.HighPrint      = highPrint;
                singleResult.LowPrint       = lowPrint;
                singleResult.MaxLong        = maxLong;
                singleResult.MaxShort       = maxShort;
                singleResult.MaxBuyingPower = maxBP;

                if (isStopped)
                {
                    singleResult.StopTime = stopTime;
                }



                symbolBuyFills    += buyFills;
                symbolSellFills   += sellFills;
                symbolIncrementPL += incrementPL;
                symbolPriceMovePL += priceMovePL;
                symbolTotalPL     += totalPL;



                totalBuyFills    += buyFills;
                totalSellFills   += sellFills;
                totalIncrementPL += incrementPL;
                totalPriceMovePL += priceMovePL;
                totalTotalPL     += totalPL;
            }

            else if (strategy == "Parabolic")
            {
                totalPL = totalPL + symbolPosition * difference;

                singleResult.Date           = _date;
                singleResult.StartingPrice  = startingPrice;
                singleResult.FinalPrint     = finalPrint;
                singleResult.BuyFills       = buyFills;
                singleResult.SellFills      = sellFills;
                singleResult.Position       = symbolPosition;
                singleResult.PriceMovePL    = 0;
                singleResult.IncrementPL    = 0;
                singleResult.TotalPL        = totalPL;
                singleResult.maxUnrealized  = maxUnrealized;
                singleResult.minUnrealized  = minUnrealized;
                singleResult.HighPrint      = highPrint;
                singleResult.LowPrint       = lowPrint;
                singleResult.MaxLong        = maxLong;
                singleResult.MaxShort       = maxShort;
                singleResult.MaxBuyingPower = maxBP;

                if (isStopped)
                {
                    singleResult.StopTime = stopTime;
                }



                symbolBuyFills    += buyFills;
                symbolSellFills   += sellFills;
                symbolIncrementPL += 0;
                symbolPriceMovePL += 0;
                symbolTotalPL     += totalPL;



                totalBuyFills    += buyFills;
                totalSellFills   += sellFills;
                totalIncrementPL += 0;
                totalPriceMovePL += 0;
                totalTotalPL     += totalPL;
            }

            if (isStopped)
            {
                Console.WriteLine("Stopped Out at {0}", stopTime);
                singleResult.StopTime = stopTime;
            }

            /*Console.WriteLine("Start Price: " + startingPrice);
             * Console.WriteLine("Final Price " + finalPrint);
             * Console.WriteLine("Buy fills: " + buyFills);
             * Console.WriteLine("Sell fills: " + sellFills);
             * Console.WriteLine("Final position: " + symbolPosition);
             * Console.WriteLine("Price Move PL: " + priceMovePL);
             * Console.WriteLine("Increment PL: " + incrementPL);
             * Console.WriteLine("Total PL: " + totalPL);*/


            singleResult.Calculate();
            return(singleResult);
        }
예제 #6
0
        public static string GenerateCandlesFromTicks(int Period, List <List <string> > Ticks)
        {
            string candleCSV = "Start Time, Open, High, Low, Close, Volume";

            string startTime = "9:30:00:0:AM";
            string endTime   = "4:00:00:0:PM";
            int    startMs   = GetMsOfDay(startTime);
            int    endMs     = GetMsOfDay(endTime) - 1;

            int periodInMs = Period * 60000;

            int periodStart = startMs;
            int periodEnd   = startMs + periodInMs - 1;

            decimal candleOpen   = 0;
            decimal candleHigh   = 0;
            decimal candleLow    = 0;
            decimal candleClose  = 0;
            decimal candleVolume = 0;
            int     tickCount    = 0;

            //Anomalous tick variables
            List <decimal> recentPriceChanges      = new List <decimal>(); //Most recent 50 price changes
            decimal        previousTickPrice       = 0;
            decimal        previousPriceChangeTick = 0;
            decimal        priceChange;

            int     tickMs     = 0;
            decimal tickPrice  = 0;
            int     tickVolume = 0;

            foreach (List <string> tick in Ticks)
            {
                if (tick[0] == "*")
                {
                    continue;
                }
                tickMs     = Convert.ToInt32(tick[0]);
                tickPrice  = Convert.ToDecimal(tick[2]);
                tickVolume = Convert.ToInt32(tick[3]);

                if (tickMs >= periodStart && tickMs <= periodEnd)   //tick in period
                {
                    if (tickCount == 0)
                    {
                        candleOpen = tickPrice;
                        candleHigh = tickPrice;
                        candleLow  = tickPrice;

                        previousTickPrice       = tickPrice;
                        previousPriceChangeTick = tickPrice;
                    }
                    else
                    {
                        //Anomalous tick catcher
                        priceChange = Math.Abs(tickPrice - previousPriceChangeTick);
                        if (priceChange >= Convert.ToDecimal(0.01)) //Valid price change
                        {
                            if (recentPriceChanges.Count < 10)      //Count first 10 price changes as valid
                            {
                                recentPriceChanges.Add(priceChange);
                                previousPriceChangeTick = tickPrice;
                            }
                            if (priceChange > (TechnicalAnalysis.Average(recentPriceChanges) * 10) && priceChange > (tickPrice * Convert.ToDecimal(0.008))) //Anomalous Print
                            {
                                continue;                                                                                                                   //Don't process anomalous tick
                            }
                            else  //Valid price change
                            {
                                if (recentPriceChanges.Count >= 100)
                                {
                                    recentPriceChanges.RemoveAt(0);
                                }
                                recentPriceChanges.Add(priceChange);
                                previousPriceChangeTick = tickPrice;
                            }
                        }


                        if (tickPrice > candleHigh)
                        {
                            candleHigh = tickPrice;
                        }
                        else if (tickPrice < candleLow)
                        {
                            candleLow = tickPrice;
                        }
                    }
                    candleVolume += tickVolume;
                    candleClose   = tickPrice;
                    tickCount++;
                }
                else if (tickMs > periodStart && tickMs > periodEnd) //first tick above period
                {
                    //add previous candle to csv
                    candleCSV += periodStart.ToString() + "," + candleOpen.ToString() + "," + candleHigh.ToString() + "," + candleLow.ToString() + "," +
                                 candleClose.ToString() + "," + candleVolume.ToString() + "\n";

                    //set new period
                    periodStart += periodInMs;
                    periodEnd   += periodInMs;
                    if (periodStart > endMs)
                    {
                        break;
                    }
                    while (tickMs > periodEnd) // no ticks occured in this period
                    {
                        candleCSV   += "*,*,*,*,*,*\n";
                        periodStart += periodInMs;
                        periodEnd   += periodInMs;
                        if (periodStart > endMs)
                        {
                            break;
                        }
                    }
                    //tick in period, is first tick
                    candleOpen   = tickPrice;
                    candleHigh   = tickPrice;
                    candleLow    = tickPrice;
                    candleClose  = tickPrice;
                    candleVolume = tickVolume;
                    tickCount    = 1;
                }


                tickPrice  = Convert.ToDecimal(tick[2]);
                tickVolume = Convert.ToInt32(tick[3]);
            }


            return(candleCSV);
        }
예제 #7
0
        public static List <decimal> TradingRange(string symbol, string date, int startMs, int endMs)
        {
            List <decimal> result = new List <decimal>();

            List <int> acceptableTradeConditions = new List <int> {
                0, 1, 9, 11, 51, 62, 66, 95, 115
            };

            bool firstTick = true;

            decimal startPrice    = 0;
            decimal endPrice      = 0;
            decimal lastValidTick = 0;

            decimal tradingRange = 0;
            decimal high         = 0;
            int     highMs       = 0;
            decimal low          = Convert.ToDecimal(999999999999999.99);
            int     lowMs        = 0;



            // get ticks
            string filePath = "./Data/Ticks/" + symbol + "/" + symbol + date + ".csv";

            List <List <string> > ticks = FileHelper.getTicks(symbol, date);

            List <decimal> recentPriceChanges      = new List <decimal>(); //Most recent 50 price changes
            decimal        previousTickPrice       = 0;
            decimal        previousPriceChangeTick = 0;
            decimal        priceChange;

            if (ticks != null)
            {
                foreach (List <string> tick in ticks)
                {
                    if (tick[0] == "*")  //Exclude manually excluded ticks
                    {
                        continue;
                    }
                    int     tickMs     = 0;
                    decimal tickPrice  = 0;
                    int     tickVolume = 0;

                    tickMs    = Convert.ToInt32(tick[0]);
                    tickPrice = Convert.ToDecimal(tick[2]);

                    //Anomalous tick catcher
                    if (!(previousTickPrice == 0) && previousPriceChangeTick != 0)
                    {
                        priceChange = Math.Abs(tickPrice - previousPriceChangeTick);
                        if (priceChange >= Convert.ToDecimal(0.01))  //Valid price change
                        {
                            if (!(acceptableTradeConditions.Contains(Convert.ToInt32(tick[4]))))
                            {
                                continue;                      //Don't process trade condition
                            }
                            if (recentPriceChanges.Count < 10) //Count first 10 price changes as valid
                            {
                                recentPriceChanges.Add(priceChange);
                                previousPriceChangeTick = tickPrice;
                            }
                            if (priceChange > (TechnicalAnalysis.Average(recentPriceChanges) * 10) && priceChange > (tickPrice * Convert.ToDecimal(0.008))) //Anomalous Print
                            {
                                continue;                                                                                                                   //Don't process anomalous tick
                            }
                            else  //Valid price change
                            {
                                if (recentPriceChanges.Count >= 100)
                                {
                                    recentPriceChanges.RemoveAt(0);
                                }
                                recentPriceChanges.Add(priceChange);
                                previousPriceChangeTick = tickPrice;
                            }
                        }
                    }
                    else
                    {
                        previousPriceChangeTick = tickPrice;
                    }

                    if (tickMs >= startMs && tickMs <= endMs)
                    {
                        if (firstTick)
                        {
                            startPrice = tickPrice;
                            firstTick  = false;
                        }
                        if (tickPrice > high)
                        {
                            high   = tickPrice;
                            highMs = tickMs;
                        }
                        if (tickPrice < low)
                        {
                            low   = tickPrice;
                            lowMs = tickMs;
                        }
                        lastValidTick = tickPrice;
                    }
                    previousTickPrice = tickPrice;
                }

                endPrice = lastValidTick;

                tradingRange = high - low;
                Console.WriteLine("High: " + high + " - " + highMs + "..." + "Low : " + low + " - " + lowMs);
            }
            else
            {
                Console.WriteLine("Failed to retrieve ticks for - Symbol: " + symbol + ", Date: " + date);
            }

            result.Add(startPrice);
            result.Add(endPrice);
            result.Add(high);
            result.Add(low);

            return(result);
        }