Hi all, I am trying to write a PSAR indicator for my automated trading program. My current results match freestockcharts.com and yahoo finance but do not match Interactive Brokers' PSAR at the trend reversal. I noticed that Interactive Brokers' PSAR can have PSARs within the bars (See Below image) Interactive Brokers list there calculation as: There looks like there is some debate over how to correctly calculate the PSAR and I would like to match IB's PSAR since I believe it is better and has fewer false signals. Here is the my PSAR class along with some recent SPY data for debugging: Code: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PSAR_Analyze { // PSAR Class public class PSAR { public PSAR() { this.m_high_prices_5 = new List<double>(); this.m_low_prices_5 = new List<double>(); this.m_ep = -9999; this.m_prev_ep = -9999; this.m_acc = 0.02; this.m_acc_upper = 0.2; this.m_init_psar = -9999; this.m_psar = -9999; this.m_psar_inter = -9999; this.m_trend_up = false; this.m_prev_trend_up = false; } public void CalculatePSAR(double p_open_price, double p_close_price, double p_high_price, double p_low_price) { if (this.m_ep == -9999) { this.m_ep = p_low_price; this.m_psar = p_high_price; this.m_trend_up = false; } this.m_high_prices_5.Add(p_high_price); // Keep only the latest close prices if (this.m_high_prices_5.Count == 6) { this.m_high_prices_5.RemoveAt(0); } this.m_low_prices_5.Add(p_low_price); // Keep only the latest close prices if (this.m_low_prices_5.Count == 6) { this.m_low_prices_5.RemoveAt(0); } this.m_psar_inter = (this.m_psar - this.m_ep) * this.m_acc; if (this.m_trend_up == false) { List<double> init_psar_list = new List<double>(); init_psar_list.Add(this.m_psar - this.m_psar_inter); if (this.m_high_prices_5.Count == 1) { init_psar_list.Add(m_high_prices_5[0]); } else { init_psar_list.Add(this.m_high_prices_5[this.m_high_prices_5.Count - 2]); init_psar_list.Add(this.m_high_prices_5.Last()); } this.m_init_psar = init_psar_list.Max(); } else { List<double> init_psar_list = new List<double>(); init_psar_list.Add(this.m_psar - this.m_psar_inter); if (this.m_low_prices_5.Count == 1) { init_psar_list.Add(m_low_prices_5[0]); } else { init_psar_list.Add(this.m_low_prices_5[this.m_low_prices_5.Count - 2]); init_psar_list.Add(this.m_low_prices_5.Last()); } this.m_init_psar = init_psar_list.Min(); } if (this.m_trend_up == false && this.m_high_prices_5.Last() < this.m_init_psar) { this.m_psar = this.m_init_psar; } if (this.m_trend_up == true && this.m_low_prices_5.Last() > this.m_init_psar) { this.m_psar = this.m_init_psar; } if (this.m_trend_up == false && this.m_high_prices_5.Last() >= this.m_init_psar) { this.m_psar = this.m_ep; } if (this.m_trend_up == true && this.m_low_prices_5.Last() <= this.m_init_psar) { this.m_psar = this.m_ep; } if (this.m_psar > p_close_price) { this.m_prev_trend_up = this.m_trend_up; this.m_trend_up = false; } else { this.m_prev_trend_up = this.m_trend_up; this.m_trend_up = true; } if (this.m_trend_up == false) { this.m_prev_ep = this.m_ep; this.m_ep = Math.Min(this.m_ep, p_low_price); } else { this.m_prev_ep = this.m_ep; this.m_ep = Math.Max(this.m_ep, p_high_price); } if (this.m_trend_up == this.m_prev_trend_up && this.m_ep != this.m_prev_ep && this.m_acc < this.m_acc_upper) { this.m_acc += 0.02; } if (this.m_trend_up != this.m_prev_trend_up) { this.m_acc = 0.02; } } public List<double> m_high_prices_5; public List<double> m_low_prices_5; public double m_ep { get; set; } public double m_prev_ep { get; set; } public double m_acc { get; set; } public double m_acc_upper { get; set; } public double m_init_psar { get; set; } public double m_psar_inter { get; set; } public double m_psar { get; set; } public bool m_trend_up { get; set; } public bool m_prev_trend_up { get; set; } } class Program { static void Main(string[] args) { PSAR psar = new PSAR(); psar.CalculatePSAR(249.419998, 249.080002, 249.699997, 248.809998); psar.CalculatePSAR(249.880005, 250.050003, 250.490005, 248.869995); psar.CalculatePSAR(249.729996, 250.350006, 250.440002, 249.630005); psar.CalculatePSAR(250.339996, 251.229996, 251.320007, 250.130005); psar.CalculatePSAR(251.490005, 252.320007, 252.320007, 251.289993); psar.CalculatePSAR(252.320007, 252.860001, 252.889999, 252.229996); psar.CalculatePSAR(252.690002, 253.160004, 253.440002, 252.559998); psar.CalculatePSAR(253.539993, 254.660004, 254.679993, 253.199997); psar.CalculatePSAR(254.149994, 254.369995, 254.699997, 253.850006); psar.CalculatePSAR(254.630005, 253.949997, 254.699997, 253.649994); psar.CalculatePSAR(254.600006, 254.619995, 255.050003, 253.979996); psar.CalculatePSAR(254.509995, 255.020004, 255.020004, 254.320007); psar.CalculatePSAR(254.660004, 254.639999, 255.059998, 254.369995); psar.CalculatePSAR(255.139999, 254.949997, 255.270004, 254.639999); psar.CalculatePSAR(255.210007, 255.289993, 255.509995, 254.820007); psar.CalculatePSAR(255.229996, 255.470001, 255.520004, 254.979996); psar.CalculatePSAR(255.899994, 255.720001, 255.949997, 255.5); psar.CalculatePSAR(254.830002, 255.789993, 255.830002, 254.350006); psar.CalculatePSAR(256.700012, 257.109985, 257.140015, 255.770004); psar.CalculatePSAR(257.480011, 256.109985, 257.51001, 256.019989); psar.CalculatePSAR(256.600006, 256.559998, 256.829987, 256.149994); psar.CalculatePSAR(256.179993, 255.289993, 256.309998, 254); psar.CalculatePSAR(255.990005, 255.619995, 256.299988, 255.479996); psar.CalculatePSAR(256.470001, 257.709991, 257.890015, 255.630005); psar.CalculatePSAR(256.470001, 256.75, 257.600006, 256.410004); psar.CalculatePSAR(257.179993, 257.149994, 257.440002, 256.809998); psar.CalculatePSAR(258.040009, 257.48999, 258.429993, 257.070007); psar.CalculatePSAR(257.410004, 257.589996, 257.75, 256.190002); psar.CalculatePSAR(257.769989, 258.450012, 258.5, 257.299988); DateTime cur_day = new DateTime(2017, 11, 3); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(258.299988, 258.850006, 259, 258.220001); cur_day = cur_day.AddDays(3); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(258.970001, 258.670013, 259.350006, 258.089996); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(258.470001, 259.109985, 259.220001, 258.149994); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(257.730011, 258.170013, 258.390015, 256.359985); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(257.730011, 258.089996, 258.290009, 257.369995); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(257.309998, 258.329987, 258.589996, 257.269989); cur_day = cur_day.AddDays(3); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(257.410004, 257.730011, 257.850006, 256.519989); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(256.619995, 256.440002, 257.220001, 255.630005); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(257.519989, 258.619995, 259.040009, 257.470001); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(258.220001, 257.859985, 258.589996, 257.769989); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(258.140015, 258.299988, 258.519989, 257.859985); cur_day = cur_day.AddDays(3); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(259.179993, 259.98999, 260.200012, 258.26001); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(260, 259.76001, 260.149994, 259.570007); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(260.320007, 260.359985, 260.480011, 260.160004); cur_day = cur_day.AddDays(2); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(260.410004, 260.230011, 260.75, 260); cur_day = cur_day.AddDays(3); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(260.76001, 262.869995, 262.899994, 260.649994); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(263.019989, 262.709991, 263.630005, 262.200012); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(263.76001, 265.01001, 266.049988, 263.670013); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(264.76001, 264.459991, 265.309998, 260.76001); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(266.309998, 264.140015, 266.799988, 264.079987); cur_day = cur_day.AddDays(3); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); psar.CalculatePSAR(263.190002, 263.190002, 265.149994, 263.040009); cur_day = cur_day.AddDays(1); Console.WriteLine(String.Format("DATE: {0}, PSAR: {1}, TREND_UP: {2}", cur_day.ToShortDateString(), Math.Round(psar.m_psar, 2), psar.m_trend_up)); Console.ReadLine(); } } } Thank you for any help
9:33 AM 106.87 107.74 106.87 107.61 9:36 AM 107.68 107.89 107.4 107.57 9:39 AM 107.565 107.94 107.52 107.91 9:42 AM 107.82 107.95 107.46 107.481 9:45 AM 107.54 107.54 107 107.17 9:48 AM 107.17 107.17 106.15 106.29 9:51 AM 106.3323 106.43 106.24 106.28 9:54 AM 106.28 106.3 106.15 106.21 9:57 AM 106.31 106.5 106.31 106.4 10:00 AM 106.46 107.095 106.41 106.82 10:03 AM 106.82 107.13 106.82 107.11 10:06 AM 107.115 107.47 107.115 107.1745 10:09 AM 107.1 107.17 107.05 107.12 10:12 AM 107.18 107.26 107.01 107.05 10:15 AM 106.9728 107.11 106.921 107.09 10:18 AM 107.13 107.13 106.79 106.86 10:21 AM 106.89 107.19 106.875 107.1659 10:24 AM 107.21 107.31 107.1 107.1 10:27 AM 107.14 107.19 106.9 106.91 10:30 AM 106.94 107.04 106.87 106.87 10:33 AM 106.88 106.9699 106.76 106.79 10:36 AM 106.77 106.86 106.68 106.695 10:39 AM 106.7 106.78 106.47 106.47 10:42 AM 106.485 106.64 106.47 106.48 10:45 AM 106.5 106.635 106.35 106.635 10:48 AM 106.63 106.63 106.41 106.5 10:51 AM 106.52 106.655 106.48 106.53 10:54 AM 106.49 106.72 106.32 106.66 10:57 AM 106.71 106.94 106.71 106.7784 11:00 AM 106.79 106.87 106.74 106.87 11:03 AM 106.895 107 106.85 106.85 11:06 AM 106.885 107.01 106.885 106.99 11:09 AM 106.99 107.19 106.97 107.12 11:12 AM 107.09 107.17 107.0681 107.085 11:15 AM 107.1 107.2 107.08 107.08 11:18 AM 107.15 107.21 107.12 107.18 11:21 AM 107.18 107.185 107.1 107.1 11:24 AM 107.0998 107.12 106.95 106.95 11:27 AM 106.964 106.964 106.71 106.77 11:30 AM 106.73 106.75 106.58 106.65 11:33 AM 106.62 106.82 106.59 106.8 11:36 AM 106.7969 106.83 106.64 106.72 11:39 AM 106.7 106.85 106.68 106.75 11:42 AM 106.75 106.75 106.63 106.71 11:45 AM 106.73 106.81 106.7 106.81 11:48 AM 106.82 106.97 106.79 106.97 11:51 AM 106.97 107.16 106.965 107.1408 11:54 AM 107.18 107.21 107.05 107.085 11:57 AM 107.06 107.11 107.03 107.06 12:00 PM 107.05 107.18 106.985 107.13 12:03 PM 107.16 107.19 107.08 107.1 12:06 PM 107.15 107.17 107.06 107.16 12:09 PM 107.17 107.25 107.04 107.079 12:12 PM 107.09 107.19 107.07 107.08 12:15 PM 107.09 107.24 107.08 107.235 12:18 PM 107.26 107.47 107.25 107.43 12:21 PM 107.435 107.55 107.415 107.44 12:24 PM 107.42 107.46 107.37 107.4431 12:27 PM 107.47 107.5499 107.41 107.5499 12:30 PM 107.54 107.65 107.54 107.554 12:33 PM 107.58 107.58 107.4901 107.57 12:36 PM 107.585 107.61 107.51 107.51 12:39 PM 107.51 107.54 107.34 107.47 12:42 PM 107.44 107.46 107.34 107.3901 12:45 PM 107.39 107.4 107.27 107.27 12:48 PM 107.311 107.34 107.21 107.3305 12:51 PM 107.325 107.35 107.21 107.2515 12:54 PM 107.23 107.23 107.1501 107.1501 12:57 PM 107.17 107.24 107.11 107.18 1:00 PM 107.16 107.18 107.1 107.18 1:03 PM 107.21 107.21 107.05 107.09 1:06 PM 107.08 107.09 106.97 107 1:09 PM 106.97 107.07 106.94 106.94 1:12 PM 106.94 106.98 106.81 106.94 1:15 PM 106.92 107 106.92 107 1:18 PM 106.985 107 106.87 106.87 1:21 PM 106.85 106.85 106.61 106.61 1:24 PM 106.6575 106.7 106.59 106.6 1:27 PM 106.59 106.695 106.54 106.56 1:30 PM 106.56 106.6 106.455 106.56 1:33 PM 106.62 106.876 106.62 106.76 1:36 PM 106.78 106.82 106.67 106.755 1:39 PM 106.765 106.803 106.62 106.62 1:42 PM 106.645 106.8 106.645 106.76 1:45 PM 106.71 106.75 106.58 106.75 1:48 PM 106.75 106.79 106.59 106.59 1:51 PM 106.62 106.682 106.53 106.535 1:54 PM 106.5462 106.63 106.525 106.5688 1:57 PM 106.59 106.6968 106.59 106.59 2:00 PM 106.57 106.59 106.43 106.44 2:03 PM 106.44 106.51 106.36 106.36 2:06 PM 106.34 106.4 106.29 106.35 2:09 PM 106.39 106.46 106.345 106.345 2:12 PM 106.38 106.44 106.33 106.4 2:15 PM 106.41 106.495 106.31 106.32 2:18 PM 106.32 106.32 106.18 106.28 2:21 PM 106.295 106.34 106.26 106.32 2:24 PM 106.31 106.32 106.21 106.24 2:27 PM 106.26 106.405 106.22 106.405 2:30 PM 106.42 106.48 106.39 106.44 2:33 PM 106.45 106.47 106.41 106.45 2:36 PM 106.465 106.58 106.45 106.45 2:39 PM 106.47 106.58 106.47 106.55 2:42 PM 106.55 106.55 106.4 106.4161 2:45 PM 106.43 106.52 106.43 106.52 2:48 PM 106.53 106.64 106.53 106.57 2:51 PM 106.59 106.67 106.57 106.62 2:54 PM 106.57 106.61 106.51 106.61 2:57 PM 106.64 106.68 106.59 106.65 3:00 PM 106.64 106.7 106.57 106.6822 3:03 PM 106.7 106.755 106.65 106.67 3:06 PM 106.689 106.745 106.61 106.63 3:09 PM 106.6 106.67 106.56 106.62 3:12 PM 106.61 106.615 106.47 106.52 3:15 PM 106.54 106.56 106.43 106.51 3:18 PM 106.51 106.51 106.36 106.4 3:21 PM 106.4 106.4 106.25 106.34 3:24 PM 106.31 106.32 106.25 106.29 3:27 PM 106.29 106.4 106.29 106.36 3:30 PM 106.35 106.45 106.32 106.45 3:33 PM 106.46 106.49 106.44 106.4631 3:36 PM 106.46 106.51 106.38 106.49 3:39 PM 106.5 106.545 106.46 106.47 3:42 PM 106.47 106.54 106.44 106.475 3:45 PM 106.47 106.505 106.44 106.48 3:48 PM 106.49 106.57 106.45 106.57 3:51 PM 106.55 106.74 106.54 106.71 3:54 PM 106.69 106.83 106.68 106.78 3:57 PM 106.79 106.84 106.76 106.825 4:00 PM 106.825 106.87 106.79 106.8