private void UpdatePlot(DurationEnum duration) { Plots.Clear(); if (Ticks == null || !Ticks.Any()) { return; } var candles = CreatePlot(Name, CreateCandleStickSeries(Name + " " + duration, Ticks)); var dateValues = Ticks.ToDateValuePoints(x => x.Close).ToList(); var ema = MovingAverage.CalculateEma(Ticks, 22); var channels = MovingAverage.CalculateEmaChannels(Ticks, 22, 60); var lowerChannel = channels.Select(x => new DateValue { Date = x.Date, Value = x.LowerValue }).ToList(); var upperChannel = channels.Select(x => new DateValue { Date = x.Date, Value = x.UpperValue }).ToList(); var plotChannels = CreatePlot("Channels", CreateLineSeries("Close Price", OxyColor.FromUInt32(0xCCF0A30A), dateValues), CreateLineSeries("EMA 22", OxyColor.FromUInt32(0xCCFA6800), ema), CreateLineSeries("Lower Channel", OxyColor.FromUInt32(0xCCA4C400), lowerChannel), CreateLineSeries("Upper Channel", OxyColor.FromUInt32(0xCC60A917), upperChannel)); var plotMa = CreatePlot("Moving Average", CreateLineSeries("Close Price", OxyColor.FromUInt32(0xCCF0A30A), dateValues), CreateLineSeries("MA 10", OxyColor.FromUInt32(0xCCA4C400), BasicAnalysis.CalculateMovingAverage(Ticks, 10)), CreateLineSeries("MA 100", OxyColor.FromUInt32(0xCC60A917), BasicAnalysis.CalculateMovingAverage(Ticks, 100))); var plotMinMax = CreatePlot("Min max", CreateLineSeries("Close Price", OxyColor.FromUInt32(0xCCF0A30A), dateValues), CreateLineSeries("Max 50", OxyColor.FromUInt32(0xCCA4C400), BasicAnalysis.CalculateMax(Ticks, 50)), CreateLineSeries("Min 50", OxyColor.FromUInt32(0xCC60A917), BasicAnalysis.CalculateMin(Ticks, 50))); var returns = CreatePlot("Returns", "P4", CreateTwoColorLineSeries("Annualized Returns", OxyColor.FromUInt32(0xCC60A917), OxyColor.FromUInt32(0xCCFA6800), CalculateReturns(dateValues))); Plots.Add(new PlotViewModel(candles)); Plots.Add(new PlotViewModel(plotChannels)); Plots.Add(new PlotViewModel(plotMa)); Plots.Add(new PlotViewModel(plotMinMax)); Plots.Add(new PlotViewModel(returns)); //analysisPlotModel.Series.Add(closePrices); //analysisPlotModel.Series.Add(CreateLineSeries("MA 10", OxyColor.FromUInt32(0xCCA4C400), BasicAnalysis.CalculateMovingAverage(Ticks, 10))); //analysisPlotModel.Series.Add(CreateLineSeries("MA 100", OxyColor.FromUInt32(0xCC60A917), BasicAnalysis.CalculateMovingAverage(Ticks, 100))); //analysisPlotModel.Series.Add(CreateLineSeries("Max 10", OxyColor.FromUInt32(0xCC911A0E), BasicAnalysis.CalculateMax(Ticks, 10))); //analysisPlotModel.Series.Add(CreateLineSeries("Max 100", OxyColor.FromUInt32(0xCC1569CE), BasicAnalysis.CalculateMax(Ticks, 100))); //if (dateValues.Count > 30) //{ // var anno1 = new TextAnnotation(); // anno1.Text = "sdkjfhsdjkfhsd"; // anno1.TextPosition = DateTimeAxis.CreateDataPoint(dateValues[10].Date, dateValues[10].Value); // analysisPlotModel.Annotations.Add(anno1); // var anno2 = new ArrowAnnotation(); // anno2.Text = "bla blas bla"; // anno2.EndPoint = DateTimeAxis.CreateDataPoint(dateValues[30].Date, dateValues[30].Value); // anno2.ArrowDirection = new ScreenVector(50, anno2.EndPoint.Y * 0.3); // analysisPlotModel.Annotations.Add(anno2); //} //Plots.Add(new PlotViewModel(analysisPlotModel)); var clenow = new SimpleClenow(Ticks); }
public SimpleClenow(IList <TickData> ticks) { var ma50Line = BasicAnalysis.CalculateMovingAverage(ticks, 50); var ma100Line = BasicAnalysis.CalculateMovingAverage(ticks, 100); var max50Line = BasicAnalysis.CalculateMax(ticks, 50); var min50Line = BasicAnalysis.CalculateMin(ticks, 50); var atrLine = BasicAnalysis.CalculateAtr(ticks, 100); var data = (from ma50 in ma50Line join ma100 in ma100Line on ma50.Date equals ma100.Date join max50 in max50Line on ma50.Date equals max50.Date join min50 in min50Line on ma50.Date equals min50.Date join atr in atrLine on ma50.Date equals atr.Date join tick in ticks on ma50.Date equals tick.Time select new { Tick = tick, Ma50 = ma50.Value, Ma100 = ma100.Value, Max50 = max50.Value, Min50 = min50.Value, Atr = atr.Value, LongAllowed = ma50.Value > ma100.Value, ShortAllowed = ma50.Value < ma100.Value, BuySignal = tick.Close >= max50.Value, SellSignal = tick.Close <= min50.Value, }) .ToList(); var decisions = new List <Tuple <int, Signal> >(); for (int i = 0; i < data.Count - 1; i++) { var lastDecision = decisions.LastOrDefault(); var lastDecisionType = lastDecision != null ? lastDecision.Item2.DecisionType : DecisionType.StayAway; var currentPoint = data[i]; var closePrice = currentPoint.Tick.Close; var entryPrice = data[i + 1].Tick.Open; if (currentPoint.BuySignal && currentPoint.LongAllowed) { if (lastDecisionType == DecisionType.Buy) { continue; } decisions.Add(new Tuple <int, Signal>(i, new Signal(currentPoint.Tick.Time, DecisionType.Buy, entryPrice))); continue; } if (currentPoint.SellSignal && currentPoint.ShortAllowed) { if (lastDecisionType == DecisionType.Sell) { continue; } decisions.Add(new Tuple <int, Signal>(i, new Signal(currentPoint.Tick.Time, DecisionType.Sell, entryPrice))); continue; } if (!currentPoint.LongAllowed && lastDecisionType == DecisionType.Buy) { decisions.Add(new Tuple <int, Signal>(i, new Signal(currentPoint.Tick.Time, DecisionType.Close, entryPrice))); continue; } if (!currentPoint.ShortAllowed && lastDecisionType == DecisionType.Sell) { decisions.Add(new Tuple <int, Signal>(i, new Signal(currentPoint.Tick.Time, DecisionType.Close, entryPrice))); continue; } if (lastDecision != null) { //stop loss var ticksRange = data .Skip(lastDecision.Item1) .Take(i - lastDecision.Item1) .ToList(); if (lastDecisionType == DecisionType.Buy) { var highestClose = ticksRange.Max(x => x.Tick.Close); highestClose -= 3 * currentPoint.Atr; if (closePrice < highestClose) { decisions.Add(new Tuple <int, Signal>(i, new Signal(currentPoint.Tick.Time, DecisionType.Close, entryPrice))); continue; } } if (lastDecisionType == DecisionType.Sell) { var lowestClose = ticksRange.Min(x => x.Tick.Close); lowestClose += 3 * currentPoint.Atr; if (closePrice > lowestClose) { decisions.Add(new Tuple <int, Signal>(i, new Signal(currentPoint.Tick.Time, DecisionType.Close, entryPrice))); continue; } } } } var temp = decisions.Select(x => x.Item2).ToList(); IndexLine.Clear(); var dataAndDecisions = (from d in data join dec in decisions on d.Tick.Time equals dec.Item2.Date into joined from jn in joined.DefaultIfEmpty() select new { Tick = d.Tick, Decision = jn != null ? jn.Item2 : null }) .ToList(); Signal lastDec = null; for (int i = 0; i < dataAndDecisions.Count; i++) { var currentPoint = dataAndDecisions[i]; var previousPoint = i == 0 ? currentPoint : dataAndDecisions[i - 1]; var lastIndexPoint = IndexLine.LastOrDefault(); var lastIndexValue = lastIndexPoint != null ? lastIndexPoint.Value : 100; if (lastDec == null) { IndexLine.Add(new DateValue { Date = currentPoint.Tick.Time, Value = lastIndexValue }); } else { var perf = currentPoint.Tick.Close / previousPoint.Tick.Close; if (lastDec.DecisionType == DecisionType.Buy) { IndexLine.Add(new DateValue { Date = currentPoint.Tick.Time, Value = lastIndexValue * perf }); } if (lastDec.DecisionType == DecisionType.Sell) { IndexLine.Add(new DateValue { Date = currentPoint.Tick.Time, Value = lastIndexValue * (2 - perf) }); } } if (currentPoint.Decision != null) { if (currentPoint.Decision.DecisionType == DecisionType.Close) { lastDec = null; continue; } lastDec = currentPoint.Decision; } } }