Interactive Brokers' PSAR

Discussion in 'Programming' started by OneTwoThree, Dec 6, 2017.

  1. 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)
    [​IMG]

    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
     
  2. 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

    [​IMG]