Ejemplo n.º 1
0
        }                                                 //Highest close value in series up to date

        public Company(string symbol, List <HistoricalDataResponse> data, SymbolData sym = null)
        {
            Iterator                  = -1;
            Count                     = 0;
            date                      = new List <LocalDate>();
            open                      = new List <float>();
            high                      = new List <float>();
            low                       = new List <float>();
            close                     = new List <float>();
            volume                    = new List <int>();
            unadjustedVolume          = new List <int>();
            change                    = new List <float>();
            changePercent             = new List <float>();
            vwap                      = new List <float>();
            label                     = new List <string>();
            changeOverTime            = new List <float>();
            MovingAverageClose        = new List <float>();
            MovingAverageVolume       = new List <int>();
            RelativePriceVolume       = new List <float>();
            MovingRelativePriceVolume = new List <float>();
            CurrentCupHandle          = new CupHandle();
            EarningsQuarters          = new List <LocalDate>();
            EarningsData              = new List <float>();
            EarningsGrowth            = new List <float>();
            CloseHighToDate           = new List <float>();


            this.Symbol = symbol;
            if (sym != null)
            {
                Name = sym.name;
            }
            else
            {
                Name = "";
            }

            foreach (HistoricalDataResponse d in data)
            {
                string[]  dateSplit = d.date.Split('-');
                LocalDate localDate = new LocalDate(Int16.Parse(dateSplit[0]), Int16.Parse(dateSplit[1]), Int16.Parse(dateSplit[2]));
                date.Add(localDate);
                open.Add(d.open);
                high.Add(d.high);
                low.Add(d.low);
                close.Add(d.close);
                volume.Add(d.volume);
                unadjustedVolume.Add(d.unadjustedVolume);
                change.Add(d.change);
                changePercent.Add(d.changePercent);
                vwap.Add(d.vwap);
                label.Add(d.label);
                changeOverTime.Add(d.changeOverTime);
                Count++;
            }

            MinClose  = close.Min();
            MinVolume = close.Max();

            List <float> changeSpread = new List <float>();

            for (int i = 0; i < close.Count; i++)
            {
                float delta = high[i] - low[i];
                changeSpread.Add(delta / open[i]);
            }
            maxDayChangePerc = changeSpread.Max();

            MovingAverageClose  = MathHelpers.MovingAverage(close, 50);
            MovingAverageVolume = MathHelpers.MovingAverage(volume, 50);

            RelativePriceVolume.Add(0);
            for (int i = 1; i < close.Count; i++)
            {
                float y = (close[i] - close[i - 1]) / close[i - 1];
                RelativePriceVolume.Add(volume[i] * y);
            }
            MovingRelativePriceVolume = MathHelpers.MovingAverage(RelativePriceVolume, 50);
        }
Ejemplo n.º 2
0
        public void Run(List <Company> list = null, IProgress <Result> progress = null)
        {
            if (list == null)
            {
                list = List;
            }
            Stopwatch sw = new Stopwatch();

            sw.Start();

            Dates            = new List <LocalDate>();
            Values           = new List <float>();
            Portfolio.Cash   = Portfolio.StartCash;
            Portfolio.Assets = new List <Asset>();

            //initialize dynamic Company members
            foreach (Company c in list)
            {
                c.SetEarningsGrowthSeries(MinNumPrevQuarters);
                c.CurrentCupHandle = new CupHandle();
                c.Iterator         = -1; //reset iterator
            }

            int runDays = Period.Between(StartDay, EndDay, PeriodUnits.Days).Days;
            List <CupHandle> cupHandles = new List <CupHandle>();
            List <string>    chSymbols  = new List <string>();

            string cupDbFile = Path.Combine(Path.GetDirectoryName(Dbfile), Path.GetFileNameWithoutExtension(Dbfile) + "_ch.db");

            if (File.Exists(cupDbFile))
            {
                File.Delete(cupDbFile);
            }

            int cupHandleId = 1;

            using (LiteDatabase chDb = new LiteDatabase(cupDbFile))
            {
                Trading.Debug.Nlog("Starting simulation");
                var colch = chDb.GetCollection <CupHandle>("CupHandle");
                for (int i = 0; i < runDays; i++)
                {
                    LocalDate thisDay = StartDay.PlusDays(i);
                    Dates.Add(thisDay);
                    foreach (Company c in list)
                    {
                        //if (c.Iterator >= c.date.Count) //Check if day is > data
                        //    continue;

                        int thisDayInd = -1;

                        //if (c.Iterator < 0)
                        //{
                        //    if (thisDay.CompareTo(c.date[0]) == 0)
                        //    {
                        //        c.Iterator = 0; //Initialize for first day of data
                        //    }
                        //}

                        thisDayInd = c.date.BinarySearch(thisDay);
                        //bool found = c.FindIndexByDate(thisDay, out thisDayInd);
                        if (thisDayInd >= 0)
                        {
                            //Start day
                            //thisDayInd = c.Iterator;
                            //thisDay = c.date[c.Iterator];

                            //float epsGrowth = c.ComputeEarningsGrowth(thisDay, MinNumPrevQuarters);
                            float epsGrowth = c.EarningsGrowth[thisDayInd];
                            if (epsGrowth == float.NaN || epsGrowth < MinEpsGrowth)
                            {
                                continue;
                            }

                            CupHandle ch = new CupHandle();
                            //Check if cuphandle is established
                            if (c.CurrentCupHandle.D.Index > 0)
                            {
                                int endBuySearch = c.CurrentCupHandle.D.Index + (int)(Chp.BuyWait * (c.CurrentCupHandle.C.Index - c.CurrentCupHandle.A.Index));
                                if (c.CurrentCupHandle.D.Index + 1 >= c.close.Count)
                                {
                                    break;
                                }
                                if (endBuySearch >= c.close.Count)
                                {
                                    endBuySearch = c.close.Count - 1;
                                }
                                for (int j = c.CurrentCupHandle.D.Index + 1; j < endBuySearch; j++)
                                {
                                    if (c.close.Count > j) //check that this day in the for loop is valid for data known
                                    {
                                        float close = c.close[j];
                                        if (close > c.CurrentCupHandle.C.Close)
                                        {
                                            LocalDate dDate = c.date[j];
                                            c.CurrentCupHandle.Buy        = c.GetPoint(j);
                                            c.CurrentCupHandle.BuyTrigger = true;
                                            // Debug.Nlog(c.Symbol + " Rank " + c.CurrentCupHandles.GetRank().ToString());
                                            c.CurrentCupHandle.Symbol = c.Symbol;
                                            //c.CurrentCupHandle.Id = ObjectId.NewObjectId();
                                            //colch.Insert(c.CurrentCupHandle);
                                            colch.Insert(cupHandleId, c.CurrentCupHandle);
                                            cupHandleId++;

                                            //Buy Triggered
                                            if (Portfolio.Cash > Portfolio.BuyAmount)
                                            {
                                                Trading.Debug.Nlog("Bought " + c.Symbol);
                                                Portfolio.Buy(new Asset(c.Symbol, c.CurrentCupHandle.Buy.Close, Portfolio.BuyAmount, thisDay));
                                                ReportProgress(progress, thisDay, i, runDays);
                                            }
                                            c.CurrentCupHandle = new CupHandle(); //restart cuphandle
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }


                            if (c.IsHighToDate(thisDayInd)) //Search for A
                            {
                                //Debug.Nlog(c.Symbol + ", New A found");
                                c.CurrentCupHandle = new CupHandle();            //reset cuphandle
                                c.CurrentCupHandle.SetA(c.GetPoint(thisDayInd)); //Set new A
                            }
                            else if (c.CurrentCupHandle.A != null)
                            {
                                int lastA = thisDayInd - c.CurrentCupHandle.A.Index;

                                if (Chp.AC.ContainsValue(lastA)) //Last A in correct Range, search for C
                                {
                                    Point possibleC = c.GetPoint(thisDayInd);
                                    if (Chp.PivotRatio.ContainsValue(possibleC.Close / c.CurrentCupHandle.A.Close))
                                    {
                                        // Pc/Pa is now verified to be within the pivot ratio range
                                        if (c.EnsurePointJ(possibleC, ch)) //Now check that no Pj exceeds line connection Pc and Pa
                                        {
                                            c.CurrentCupHandle.SetC(possibleC);
                                            //Now searching for handle
                                            //Debug.Nlog(c.Symbol + ", found C");

                                            //Use URPV3 to find B???
                                            //BC range, or Frame 3 span, or RightCup
                                            int          rangeBC      = Chp.CupRight.Maximum - Chp.CupRight.Minimum;
                                            int          startBsearch = c.CurrentCupHandle.C.Index - rangeBC;
                                            float        urpvSum      = 0;
                                            float        drpvSum      = 0;
                                            int          urpvCnt      = 0;
                                            int          drpvCnt      = 0;
                                            List <float> urpv3Arr     = new List <float>();
                                            List <float> R1arr        = new List <float>();
                                            List <float> R3arr        = new List <float>();
                                            for (int j = startBsearch; j < c.CurrentCupHandle.C.Index; j++)
                                            {
                                                if (c.close[j] > c.close[j - 1])
                                                {
                                                    //Up day
                                                    urpvSum += c.RelativePriceVolume[j];
                                                    urpvCnt++;
                                                }
                                                else
                                                {
                                                    //down day
                                                    drpvSum += c.RelativePriceVolume[j];
                                                    drpvCnt++;
                                                }

                                                if (c.MovingRelativePriceVolume[j] == 0)
                                                {
                                                    //this is bad
                                                    bool stop = true;
                                                }

                                                //Check RPV values
                                                float urpv = urpvSum / urpvCnt;
                                                urpv3Arr.Add(urpv);
                                                float drpv = drpvSum / drpvCnt;

                                                float R1;
                                                if (drpv == 0)
                                                {
                                                    R1 = (float)Math.Log10(urpv / drpv);
                                                }
                                                else
                                                {
                                                    R1 = (float)Math.Log10(urpv / c.MovingRelativePriceVolume[j]);
                                                }

                                                R1arr.Add(R1);
                                                float R3 = (float)Math.Log10(urpv / c.MovingRelativePriceVolume[j]);
                                                R3arr.Add(R3);
                                            }

                                            List <float> R1R3sum = new List <float>();
                                            //Now with data find the best PointB based on R1 and R2
                                            for (int j = 0; j < R1arr.Count; j++)
                                            {
                                                R1R3sum.Add(R1arr[j] + R3arr[j]);
                                            }

                                            float bestR1R3      = R1R3sum.Max();
                                            int   ind           = R1R3sum.IndexOf(bestR1R3);
                                            int   bestR1R3Index = startBsearch + ind;
                                            float urpv3         = urpv3Arr[ind];
                                            if (bestR1R3 > 0)
                                            {
                                                //B Found!!!
                                                //Debug.Nlog("B found!!!");
                                                c.CurrentCupHandle.R1 = R1arr[ind];
                                                c.CurrentCupHandle.R3 = R3arr[ind];
                                                LocalDate bDate = c.date[bestR1R3Index];
                                                c.CurrentCupHandle.SetB(c.GetPoint(bestR1R3Index));

                                                //Now continue and find PointD the handle
                                                int rangeCD      = Chp.Handle.Maximum - Chp.Handle.Minimum;
                                                int startDsearch = c.CurrentCupHandle.C.Index + Chp.CupRight.Minimum;
                                                int endDsearch   = startDsearch + rangeCD;
                                                if (startDsearch >= c.close.Count)
                                                {
                                                    break;
                                                }
                                                if (endDsearch >= c.close.Count)
                                                {
                                                    endDsearch = c.close.Count - 1;
                                                }
                                                List <float> R2arr = new List <float>();
                                                urpvSum = 0;
                                                drpvSum = 0;
                                                urpvCnt = 0;
                                                drpvCnt = 0;
                                                for (int j = startDsearch; j < endDsearch; j++)
                                                {
                                                    if (c.close[j] > c.close[j - 1])
                                                    {
                                                        //Up day
                                                        urpvSum += c.RelativePriceVolume[j];
                                                        urpvCnt++;
                                                    }
                                                    else
                                                    {
                                                        //down day
                                                        drpvSum += c.RelativePriceVolume[j];
                                                        drpvCnt++;
                                                    }

                                                    if (c.MovingRelativePriceVolume[j] == 0)
                                                    {
                                                        //this is bad
                                                        bool stop = true;
                                                    }

                                                    float urpv = urpvSum / urpvCnt;
                                                    float drpv = drpvSum / drpvCnt;
                                                    float R2;
                                                    if (drpv == 0)
                                                    {
                                                        R2 = (float)Math.Log10(urpv3 / drpv);
                                                    }
                                                    else
                                                    {
                                                        R2 = (float)Math.Log10(urpv3 / c.MovingRelativePriceVolume[j]);
                                                    }
                                                    R2arr.Add(R2);
                                                }

                                                //Enforce D requirements
                                                List <float> newR2arr = new List <float>();
                                                for (int cnt = 0; cnt < R2arr.Count; cnt++)
                                                {
                                                    ind = startDsearch + cnt;
                                                    LocalDate dDate  = c.date[ind];
                                                    float     dClose = c.close[ind];
                                                    float     CBdiff = c.CurrentCupHandle.C.Close - c.CurrentCupHandle.B.Close;
                                                    if (CBdiff > 0)
                                                    {
                                                        float CDdiff = c.CurrentCupHandle.C.Close - dClose;
                                                        if (dClose < c.CurrentCupHandle.C.Close)
                                                        {
                                                            if (dClose > (c.CurrentCupHandle.B.Close + CBdiff * Chp.CBdiffMin))
                                                            {
                                                                newR2arr.Add(R2arr[cnt]);
                                                            }
                                                        }
                                                    }
                                                }

                                                if (newR2arr.Count > 0)
                                                {
                                                    R2arr = newR2arr;
                                                    float bestR2 = R2arr.Max();
                                                    ind = R2arr.IndexOf(bestR2);
                                                    int bestR2Index = startDsearch + ind;

                                                    if (bestR2 > 0)
                                                    {
                                                        //D found !!!
                                                        //Debug.Nlog("D found!!!");
                                                        c.CurrentCupHandle.R2 = R2arr[ind];
                                                        if (c.CurrentCupHandle.GetRank() > Chp.MinRank && c.CurrentCupHandle.GetMinimumRank() > Chp.MinSingleRank)
                                                        {
                                                            LocalDate dDate = c.date[bestR2Index];
                                                            c.CurrentCupHandle.D = c.GetPoint(bestR2Index);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            int index = Portfolio.Assets.FindIndex(x => x.Symbol.Equals(c.Symbol));
                            if (index >= 0)
                            {
                                float perShare = c.close[thisDayInd];
                                Asset a        = Portfolio.Assets[index];
                                a.SetCurrentValue(perShare);
                                float change = perShare / a.PerShareInitial;

                                if (change > (Portfolio.StopGain))
                                {
                                    Trading.Debug.Nlog("Sold " + a.Symbol + " for gain");
                                    Portfolio.Sell(a, perShare); //Set asset for gain
                                    ReportProgress(progress, thisDay, i, runDays);
                                }
                                if (change < Portfolio.StopLoss)
                                {
                                    Trading.Debug.Nlog("Sold " + a.Symbol + " for loss");
                                    Portfolio.Sell(a, perShare); //sell asset for loss
                                    ReportProgress(progress, thisDay, i, runDays);
                                }
                            }
                        }
                        c.Iterator++;
                        //End of company loop
                    }
                    float endOfDayValue = Portfolio.GetTotalValue();
                    float slope;
                    float rSquared;
                    MathHelpers.LinearRegression(Values.ToArray(), out rSquared, out slope);
                    string mess = thisDay.ToString() + ", " + endOfDayValue.ToString() + ", Total Assets: " + Portfolio.Assets.Count.ToString();
                    Trading.Debug.Nlog(mess);
                    Trading.Debug.Nlog(Portfolio.AllAssetsToString());
                    //end of trading day loop
                }
            }
            Trading.Debug.Nlog("Found " + (cupHandleId + 1).ToString() + " handles");
            sw.Stop();
            Trading.Debug.Nlog("Total sim time, " + sw.Elapsed.TotalMinutes.ToString() + " minutes");
            Trading.Debug.Nlog("Finished");
            //Console.ReadKey();
        }