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); }
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()); } }
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(); }
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); } }
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); }
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); }
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); }