public virtual bool TurnOver(DataRowCollection rows, int index) { if (!AnalysisCommon.CheckTrendPeriod(index, rows.Count, TrendPeriod)) { return(false); } AnalysisCommon.TrendDirection before = AnalysisCommon.TrendDirection.None; AnalysisCommon.TrendDirection after = AnalysisCommon.TrendDirection.None; try { before = AnalysisCommon.CheckBeforeTrendDirection(rows, index, TrendPeriod); after = AnalysisCommon.CheckAfterTrendDirection(rows, index, TrendPeriod); } catch (Exception ex) { if (ex is SMANULLException) { return(false); } } if ((before == AnalysisCommon.TrendDirection.Down && after == AnalysisCommon.TrendDirection.Up) || (before == AnalysisCommon.TrendDirection.Up && after == AnalysisCommon.TrendDirection.Down)) { return(true); } return(false); }
public override bool Valid(DataRowCollection rows, int index) { if (AnalysisCommon.CheckAfterTrendDirection(rows, index, AnalysisCommon.TrendPeriod.Short) != AnalysisCommon.TrendDirection.Up) { return(false); } return(true); }
public virtual async Task <bool> Analyze(DataTable dtPrices, DataTable rootTable) { var rows = dtPrices.Rows; if (rows.Count == 0) { return(false); } string symbolId = rows[0][Common.SymbolIdColumn].ToString(); var table = AnalysisCommon.MakeAnalysisResultsTable(); Console.WriteLine(string.Format("Analyzing Symbol {0} with method {1}", symbolId, Name)); for (int i = 0; i < rows.Count; i++) { bool isQualified = false; bool isValid = false; StockData currentPrice = TryGetPriceValues(rows, i); StockData beforePrice = TryGetPriceValues(rows, i - 1); StockData afterPrice = TryGetPriceValues(rows, i + 1); //if current date has no volume then skip it if (currentPrice != null && currentPrice.volume != null && currentPrice.volume == 0) { continue; } if (Qualified(rows, i, currentPrice, beforePrice, afterPrice)) { isQualified = true; isValid = Valid(rows, i); var newRow = table.NewRow(); newRow[Common.SymbolIdColumn] = symbolId; newRow[Common.MethodNameColumn] = Name; newRow[Common.DateColumn] = rows[i][Common.DateColumn].ToString(); newRow[Common.QualifiedColumn] = Convert.ToInt32(isQualified).ToString(); newRow[Common.ValidColumn] = Convert.ToInt32(isValid).ToString(); table.Rows.Add(newRow); } } if (table.Rows.Count > 0) { Console.WriteLine(string.Format("Write {0} rows to DB for symbol {1} and method {2}", table.Rows.Count, symbolId, Name)); var ret = await SqlExecutor.BulkCopy(table); } //AnalysisCommon.MergeAnalysisResultTable(rootTable, table); return(true); }
public virtual bool BeforeHasTrend(DataRowCollection rows, int index) { if (!AnalysisCommon.CheckTrendPeriod(index, rows.Count, TrendPeriod)) { return(false); } var trendDirect = AnalysisCommon.CheckBeforeTrendDirection(rows, index, TrendPeriod); if (trendDirect == AnalysisCommon.TrendDirection.None) { return(false); } return(true); }
public override bool Qualified(DataRowCollection rows, int index, StockData currentPrice, StockData beforePrice, StockData afterPrice) { if (currentPrice == null || beforePrice == null) { return(false); } if (!BeforeHasTrend(rows, index)) { return(false); } //Before trend must be Down if (AnalysisCommon.CheckBeforeTrendDirection(rows, index, _trendPeriod) != AnalysisCommon.TrendDirection.Down) { return(false); } //Previous day must be down if (beforePrice.open < beforePrice.close) { return(false); } //Current day must be up if (currentPrice.open > currentPrice.close) { return(false); } //Current Open must be less than previous close if (currentPrice.open > beforePrice.close) { return(false); } //Current close must be greater than previous close if (currentPrice.close < beforePrice.close) { return(false); } //Shadow line must be very short for previous if ((beforePrice.high - beforePrice.close) > (beforePrice.high - beforePrice.low) * multiplier) { return(false); } if ((beforePrice.open - beforePrice.low) > (beforePrice.high - beforePrice.low) * multiplier) { return(false); } //Shadow line must be very short for current if ((currentPrice.high - currentPrice.open) > (currentPrice.high - currentPrice.low) * multiplier) { return(false); } if ((currentPrice.close - currentPrice.low) > (currentPrice.high - currentPrice.low) * multiplier) { return(false); } //current close must be in body of previous bar for more than 60% if ((currentPrice.close - beforePrice.close) < (beforePrice.open - beforePrice.close) * multiplier2) { return(false); } return(true); }