private static void calculateKDValue(List <StockChartData> result, int idx, StockChartData chartDataToday) { if (idx >= 9) { List <StockChartData> charts = GetNDaysChart(result, idx, 9).ToList(); decimal max = charts.Select(x => x.PriceToday.High).Max(); decimal min = charts.Select(x => x.PriceToday.Low).Min(); if (max == min) { chartDataToday.RSV = 50; } else { chartDataToday.RSV = ((chartDataToday.PriceToday.Close - min) / (max - min)) * 100; } chartDataToday.KValue = (result.Where(x => x.ChartIdx == idx - 1).Single().KValue * 2 / 3) + (chartDataToday.RSV / 3); chartDataToday.DValue = (result.Where(x => x.ChartIdx == idx - 1).Single().DValue * 2 / 3) + (chartDataToday.KValue / 3); } else { chartDataToday.RSV = 50; chartDataToday.KValue = 50; chartDataToday.DValue = 50; } }
/// <summary> /// 取得基本分析指標資料 /// </summary> /// <param name="source"></param> /// <returns></returns> public static List <StockChartData> StockPriceDataToChart(List <StockPrice> source) { List <StockChartData> result = new List <StockChartData>(); int idx = 0; StockPrice priceYesterday = new StockPrice(); foreach (StockPrice priceData in source.OrderBy(s => s.Date)) { ++idx; StockChartData chartDataToday = new StockChartData(); chartDataToday.PriceToday = priceData; if (idx > 1) { chartDataToday.PriceYesterday = priceYesterday; } chartDataToday.ChartIdx = idx; result.Add(chartDataToday); processTechnicalAnalysisIndicators(result, idx, chartDataToday); priceYesterday = chartDataToday.PriceToday; } return(result); }
private static void calculateBBand(List <StockChartData> result, int idx, StockChartData chartDataToday) { if (idx >= 20) { decimal stdavg = MathHelper.CaculateStdAvg(GetNDaysChart(result, idx, 20).Select(x => x.PriceToday.Close).ToArray()); chartDataToday.BBUB = chartDataToday.MA20 + stdavg * 2; chartDataToday.BBLB = chartDataToday.MA20 - stdavg * 2; } }
private static void calculateMovingAverage(List <StockChartData> result, int idx, StockChartData chartDataToday) { if (idx >= 5) { chartDataToday.MA5 = GetNDaysChart(result, idx, 5).Select(x => x.PriceToday.Close).Average(); chartDataToday.VMA5 = GetNDaysChart(result, idx, 5).Select(x => Convert.ToDecimal(x.PriceToday.Amount)).Average(); } if (idx >= 10) { chartDataToday.MA10 = GetNDaysChart(result, idx, 10).Select(x => x.PriceToday.Close).Average(); chartDataToday.VMA10 = GetNDaysChart(result, idx, 10).Select(x => Convert.ToDecimal(x.PriceToday.Amount)).Average(); } if (idx >= 20) { chartDataToday.MA20 = GetNDaysChart(result, idx, 20).Select(x => x.PriceToday.Close).Average(); chartDataToday.VMA20 = GetNDaysChart(result, idx, 20).Select(x => Convert.ToDecimal(x.PriceToday.Amount)).Average(); } if (idx >= 60) { chartDataToday.MA60 = GetNDaysChart(result, idx, 60).Select(x => x.PriceToday.Close).Average(); } if (idx >= 120) { chartDataToday.MA120 = GetNDaysChart(result, idx, 120).Select(x => x.PriceToday.Close).Average(); } }
private static void processTechnicalAnalysisIndicators(List <StockChartData> result, int idx, StockChartData chartDataToday) { calculateMovingAverage(result, idx, chartDataToday); calculateKDValue(result, idx, chartDataToday); calculateBBand(result, idx, chartDataToday); }
public async Task <Response <StockChartData> > GetStockChartDataAsync(string id) { var fnResult = new Response <StockChartData> { StatusCode = (int)HttpStatusCode.BadRequest }; try { var uri = _yahooFinanceApiSettings.BaseClient + string.Format(_yahooFinanceApiSettings.GetStockChartUri, id); var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, uri)); if (response.StatusCode != HttpStatusCode.OK) { return(fnResult); } var content = await response.Content.ReadAsStringAsync(); var requestBody = JObject.Parse(content); var timestampList = requestBody.SelectToken($"chart.result[0].timestamp").Values <long>().ToList(); var priceJToken = requestBody.SelectToken($"chart.result[0].indicators.quote[0].close"); var priceList = new List <double>(); foreach (var price in priceJToken) { var priceString = price.ToString(); if (string.IsNullOrWhiteSpace(priceString)) { priceList.Add(0); } else { priceList.Add((double)price); } } var stockChartData = new StockChartData(); for (int i = 0; i < timestampList.Count; i++) { var start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); start = start.AddSeconds(timestampList[i]).ToLocalTime(); stockChartData.ChartDataList.Add(new ChartData { price = priceList[i], timestampLong = timestampList[i], time = start.ToString("g") }); } fnResult.StatusCode = (int)HttpStatusCode.OK; fnResult.Data = stockChartData; return(fnResult); } catch (Exception e) { fnResult.StatusCode = (int)HttpStatusCode.InternalServerError; fnResult.Message = e.Message; return(fnResult); } }
public List <StockSelectionResult> GetSelectionResult(List <StockChartData> stockPriceList, DateTime checkBgn, DateTime checkEnd) { List <StockSelectionResult> result = new List <StockSelectionResult>(); for (DateTime date = checkBgn; date <= checkEnd; date = date.AddDays(1)) { // 該日期沒股價資訊則跳過 if (stockPriceList.Where(x => x.PriceToday.Date == date.Date).Count() == 0) { continue; } StockChartData currentDatePrice = stockPriceList.Where(x => x.PriceToday.Date == date).First(); if (currentDatePrice.ChartIdx < 30) { continue; } // 量必須為5日均量的1.5倍以上為爆量 if (currentDatePrice.PriceToday.Amount < currentDatePrice.VMA5 * 1.5m) { continue; } // 漲幅必須大於3% if ((currentDatePrice.PriceToday.Close - currentDatePrice.PriceYesterday.Close) / currentDatePrice.PriceYesterday.Close <= 0.03m) { continue; } // 漲停買不到,跳過 if (currentDatePrice.IsLimitUp) { continue; } List <StockChartData> stock10Days = StockAnalysisHelper.GetNDaysChart(stockPriceList, currentDatePrice.ChartIdx - 1, 10).ToList(); // 10日內最高點 if (currentDatePrice.PriceToday.Close > stock10Days.Select(x => x.PriceToday.Close).Max()) { // 10日內布林上下緣在7%以內 bool chk = true; foreach (StockChartData data in stock10Days) { if (((data.BBUB - data.BBLB) / data.BBLB) > 0.07m) { chk = false; } } if (chk) { StockChartData nextDayData = StockAnalysisHelper.GetNextNDaysChart(stockPriceList, currentDatePrice.ChartIdx, 1); result.Add(new StockSelectionResult() { Date = currentDatePrice.PriceToday.Date, Memo = String.Format("布林拳; 布林平均: {0}%;漲幅: {1}%;爆量: {2}倍; 今日收盤: {3}; 明日開盤: {4}", (stock10Days.Select(x => (x.BBUB - x.BBLB) / x.BBLB).Average() * 100m).ToString("0.00"), (((currentDatePrice.PriceToday.Close - currentDatePrice.PriceYesterday.Close) / currentDatePrice.PriceYesterday.Close) * 100m).ToString("0.00"), (currentDatePrice.PriceToday.Amount / currentDatePrice.VMA5).ToString("0.00"), currentDatePrice.PriceToday.Close.ToString("0.00"), nextDayData == null ? "0.00": nextDayData.PriceToday.Open.ToString("0.00") ) }); } } } return(result); }