From d0d92e04046b2f00361fd4e8e75f116db9cacbeb Mon Sep 17 00:00:00 2001 From: "DESKTOP-1A3P75F\\lee" Date: Fri, 15 Apr 2022 15:14:08 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=B0=EA=B3=BC=EA=B0=92=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Million Prototype/Form1.cs | 160 +++++++++++++++++++--- Million/CommonProperty.cs | 8 ++ Million/Data/CandleData.cs | 1 + Million/Data/CandleDataList.cs | 4 +- Million/Data/IchimokData.cs | 25 +++- Million/Data/IndicatorData.cs | 2 +- Million/Data/SearchResult.cs | 36 +++++ Million/Manager/BuyLogicManager.cs | 1 + Million/Manager/SellLogicManager.cs | 41 +++++- Million/Manager/ValidationCheckManager.cs | 63 ++++++++- Million/Million Core.csproj | 1 + 11 files changed, 310 insertions(+), 32 deletions(-) create mode 100644 Million/Data/SearchResult.cs diff --git a/Million Prototype/Form1.cs b/Million Prototype/Form1.cs index 5b40704..0e2da57 100644 --- a/Million Prototype/Form1.cs +++ b/Million Prototype/Form1.cs @@ -54,9 +54,9 @@ namespace Million_Prototype var dateTime = DateTime.Now; //4시간 가져오기 - foreach(var krw in dataList) + foreach (var krw in dataList) { - krw.CandleDataLists_Im= UpbitApi.GetCandleStics(krw.ConGoodsData.CodeFullName, MCandleTimeType.H4, dateTime); + krw.CandleDataLists_Im = UpbitApi.GetCandleStics(krw.ConGoodsData.CodeFullName, MCandleTimeType.H4, dateTime); } /* @@ -87,7 +87,7 @@ namespace Million_Prototype foreach (var krw in krwList) { - + //candledataList.Add(uApi.GetCandleStics(krw.CodeFullName, Million.CommonProperty.MCandleTimeType.D1, DateTime.Now, 50)); } @@ -100,7 +100,7 @@ namespace Million_Prototype public void setCandleDataList(List dataList, List marketDataList) { - foreach(var marketData in marketDataList) + foreach (var marketData in marketDataList) { dataList.Add(new CandleDataList() { @@ -117,13 +117,13 @@ namespace Million_Prototype var tableList = CommonProperty.selectedMarketOfPlaceList; var selectTable = tableList.FirstOrDefault(t => t.CodeFullName == "KRW-BTC"); - if(selectTable != null) + if (selectTable != null) { var startDate = new DateTime(2000, 1, 1); var candleData = DbServiceFunctions.GetCandleData(selectTable, startDate, 100000, MCandleTimeType.M1); Bollinger_Bands.AddMovingAndBollingerBands(candleData.CandleDataLists_Im, 40, 2); - Bollinger_Bands.AddMovingAndBollingerBands(candleData.CandleDataLists_Im, 40, 1,false); + Bollinger_Bands.AddMovingAndBollingerBands(candleData.CandleDataLists_Im, 40, 1, false); Ichimoku_cloud.excute(candleData.CandleDataLists_Im); var resultdata = candleData.CandleDataLists_Im.FindAll(x => x.IndicatorDic["Bol401"].overStatus == OverStatus.Over); @@ -137,7 +137,7 @@ namespace Million_Prototype List list = null; DataSettingManager realTimeMsg = null; int firstFlag = 0; - for(; ; ) + for (; ; ) { if (firstFlag == 0) { @@ -149,14 +149,15 @@ namespace Million_Prototype } else { - if (firstFlag == 1) { + if (firstFlag == 1) + { firstFlag = 2; - realTimeMsg.EndRealTimeTicker(); + realTimeMsg.EndRealTimeTicker(); list = realTimeMsg.ProcessRecentlyCandleDatas(list, realTimeMsg.tickerList, MCandleTimeType.M1); realTimeMsg.StartGetRealTimeTicker(null); } - else if(firstFlag == 2) + else if (firstFlag == 2) { list = realTimeMsg.ProcessRecentlyCandleDatas(list, realTimeMsg.tickerList, MCandleTimeType.M1); // 1분 간격 @@ -175,17 +176,20 @@ namespace Million_Prototype { DbServiceFunctions.GetMarketTable_FromDB("Upbit"); var tableList = CommonProperty.selectedMarketOfPlaceList; - + var resultList = new List(); + var errorResultList = new List(); foreach (var marketData in tableList) - { - + { var buyCandleList = new List(); + var sellList = new List(); if (marketData != null) { + //사는 로직 + var candleDataH1 = new CandleDataList(); var candleDataM1 = new CandleDataList(); - var splitData = ValidationCheckManager.GetValidationCandleDatas(marketData, ref candleDataM1, new DateTime(2000,1,1), DateTime.Now); + var splitData = ValidationCheckManager.GetValidationCandleDatas(marketData, ref candleDataH1, ref candleDataM1, new DateTime(2020, 3, 1), DateTime.Now); var buyData = new CandleDataList(); buyData.ConGoodsData = marketData; @@ -193,20 +197,132 @@ namespace Million_Prototype foreach (var split in splitData) { - - var overData = split.FindAll(x => (int)x.IndicatorDic["Bol401"].overStatus > -2 && x.IndicatorDic["Bol401"].overStatus != OverStatus.None + var overData = split.FindAll(x => (int)x.IndicatorDic["Bol401"].overStatus >= -2 && x.IndicatorDic["Bol401"].overStatus != OverStatus.None && ((IchimokData)x.IndicatorDic["Ich"]).value < x.StartValue && ((IchimokData)x.IndicatorDic["Ich"]).value2 < x.StartValue); buyData = BuyLogicManager.GetBuyLogicByBol401Upper(overData, candleDataM1); + buyCandleList.Add(buyData); } - buyCandleList.Add(buyData); + + //파는 로직 + foreach (var item in splitData) + { + var sell1 = SellLogicManager.GetSellLogicOverUnderIch(item); + var sell2 = SellLogicManager.GetSellLogicOVerUnderBol(item, 40, 1); + var sell3 = SellLogicManager.GetSellLogicOVerUnderBol(item, 40, 2); + + sell1.AddRange(sell2); + sell1.AddRange(sell3); + + var dateTimeList = sell1.Select(t => t.DateTime).Distinct().ToList(); + + foreach (var date in dateTimeList) + { + sellList.Add(sell1.FirstOrDefault(t => t.DateTime == date)); + } + } + + //Result 계산 + foreach (var item in buyCandleList) + { + var result = new SearchResult(); + result.BuyList.ConGoodsData = marketData; + + if (item.CandleDataLists_Im.Count > 0) + { + var sellData = sellList.FirstOrDefault(t => t.DateTime > item.CandleDataLists_Im[0].DateTime); + foreach (var buy in item.CandleDataLists_Im) + { + + if (buy.DateTime < sellData.DateTime) + { + result.BuyList.CandleDataLists_Im.Add(buy); + + } + else + { + var sDate = result.BuyList.CandleDataLists_Im[0].DateTime; + var eDate = sellData.DateTime; + + //Result Data Setting + result.TermCandleDataList = candleDataM1.CandleDataLists_Im.Where(x => x.DateTime >= sDate && x.DateTime <= eDate).ToList(); + result.CodeFullName = result.BuyList.ConGoodsData.CodeFullName; + result.StartDate = sDate; + result.EndDate = eDate; + + var sellLogicKeys = result.SellData.SellLogicFlag.Keys; + + double sellValue = 0; + #region 파는 값 계산(파는 로직 중 제일 높은 값) + var key = Enum.GetName(typeof(CommonProperty.SellLogicKeyList), CommonProperty.SellLogicKeyList.IchMok); + if (result.SellData.SellLogicFlag.ContainsKey(key)) + { + if(sellValue < ((IchimokData) result.SellData.IndicatorDic["Ich"]).GetOverValue()) + { + sellValue = ((IchimokData)result.SellData.IndicatorDic["Ich"]).GetOverValue(); + } + } + + key = Enum.GetName(typeof(CommonProperty.SellLogicKeyList), CommonProperty.SellLogicKeyList.Bol) + "401"; + if (result.SellData.SellLogicFlag.ContainsKey(key)) + { + if (sellValue < result.SellData.IndicatorDic[key].overlapValue) + { + sellValue = result.SellData.IndicatorDic[key].overlapValue; + } + } + + key = Enum.GetName(typeof(CommonProperty.SellLogicKeyList), CommonProperty.SellLogicKeyList.Bol) + "402"; + if (result.SellData.SellLogicFlag.ContainsKey(key)) + { + if (sellValue < result.SellData.IndicatorDic[key].overlapValue) + { + sellValue = result.SellData.IndicatorDic[key].overlapValue; + } + } + result.SellValue = sellValue; + #endregion + + #region Rating 계산 + double totalVal = 0; + foreach (var x in result.BuyList.CandleDataLists_Im) + { + var dateTime = x.DateTime.AddMinutes(x.DateTime.Minute); + var hCandle = candleDataH1.CandleDataLists_Im.FirstOrDefault(t => t.DateTime == dateTime); + var buyValue = hCandle.IndicatorDic[Enum.GetName(typeof(CommonProperty.SellLogicKeyList), CommonProperty.SellLogicKeyList.Bol) + "401"].overlapValue; + var rate = ((sellValue - buyValue) / buyValue) * 100; + result.BuyEarningRate.Add(rate); + result.BuyValueList.Add(buyValue); + totalVal += rate; + } + result.TotalEarningRate = totalVal / result.BuyValueList.Count; + #endregion + + var errorList = ValidationCheckManager.ValidateCandleDataList(result.TermCandleDataList, "", MCandleTimeType.M1); + + if (errorList.Count == 0) + { + result.SellData = sellData; + resultList.Add(result); + } + else + { + result.SellData = sellData; + errorResultList.Add(result); + } + + result = new SearchResult(); + result.BuyList.CandleDataLists_Im.Add(buy); + sellData = sellList.FirstOrDefault(t => t.DateTime > buy.DateTime); + } + } + } + } + + sellList.ToString(); } - - var sellCandleList = new List(); - - - } + resultList.ToString(); } } } diff --git a/Million/CommonProperty.cs b/Million/CommonProperty.cs index 17cad31..901140a 100644 --- a/Million/CommonProperty.cs +++ b/Million/CommonProperty.cs @@ -174,5 +174,13 @@ namespace Million #endregion + #region Sell Logic Key List + public enum SellLogicKeyList + { + IchMok = 1, + Bol = 2 + } + #endregion + } } diff --git a/Million/Data/CandleData.cs b/Million/Data/CandleData.cs index 098ad3c..c7d2588 100644 --- a/Million/Data/CandleData.cs +++ b/Million/Data/CandleData.cs @@ -33,6 +33,7 @@ namespace Million.Data public Dictionary IndicatorDic = new Dictionary(); + public Dictionary SellLogicFlag = new Dictionary(); public CandleType CandleType { get; set; } = CandleType.None; diff --git a/Million/Data/CandleDataList.cs b/Million/Data/CandleDataList.cs index 1cfc998..cc49a83 100644 --- a/Million/Data/CandleDataList.cs +++ b/Million/Data/CandleDataList.cs @@ -5,8 +5,8 @@ namespace Million.Data public class CandleDataList { // 코인 종목 - public MarketData ConGoodsData { get; set; } + public MarketData ConGoodsData { get; set; } = new MarketData(); // 캔들 데이터 (1분) - public List CandleDataLists_Im { get; set; } + public List CandleDataLists_Im { get; set; } = new List(); } } diff --git a/Million/Data/IchimokData.cs b/Million/Data/IchimokData.cs index 40c0b7b..4c76f89 100644 --- a/Million/Data/IchimokData.cs +++ b/Million/Data/IchimokData.cs @@ -23,17 +23,36 @@ namespace Million.Data /// public OverStatus overStatus2 = OverStatus.None; + /// + /// 선행1,2중에 위의 값을 리턴함 + /// + /// + public Indicator_over GetOverIndicator() + { + if (value == 0 && value2 == 0) + return Indicator_over.None; + return value > value2 ? indicator_over : indicator_over2; + } + + public OverStatus GetOverStatus() + { + if (value == 0 && value2 == 0) + return OverStatus.None; + return value > value2 ? overStatus : overStatus2; + } + + /// /// 두 선행스팬 값중에 위의 값을 리턴함 /// /// /// - public static double GetOverValue(IchimokData data) + public double GetOverValue() { - if (data.value == 0 || data.value2 == 0) + if (value == 0 || value2 == 0) return 0; - return data.value > data.value2 ? data.value : data.value2; + return value > value2 ? value : value2; } } diff --git a/Million/Data/IndicatorData.cs b/Million/Data/IndicatorData.cs index e96dd16..1f6511b 100644 --- a/Million/Data/IndicatorData.cs +++ b/Million/Data/IndicatorData.cs @@ -193,6 +193,6 @@ namespace Million.Data Over = 1 } - + } diff --git a/Million/Data/SearchResult.cs b/Million/Data/SearchResult.cs new file mode 100644 index 0000000..4edaf1d --- /dev/null +++ b/Million/Data/SearchResult.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Million.Data +{ + /// + /// 검색기 결과 클래스 + /// + public class SearchResult + { + public CandleDataList BuyList { get; set; } = new CandleDataList(); + + public CandleData SellData { get; set; } = new CandleData(); + + public List TermCandleDataList { get; set; } = new List(); + + public string CodeFullName { get; set; } + + public DateTime StartDate { get; set; } + + public DateTime EndDate { get; set; } + + public List BuyEarningRate { get; set; } = new List(); + public List BuyValueList { get; set; } = new List(); + + public double SellValue; + + public double TotalEarningRate; + + + + } +} diff --git a/Million/Manager/BuyLogicManager.cs b/Million/Manager/BuyLogicManager.cs index f76507e..6c54170 100644 --- a/Million/Manager/BuyLogicManager.cs +++ b/Million/Manager/BuyLogicManager.cs @@ -16,6 +16,7 @@ namespace Million.Manager public static CandleDataList GetBuyLogicByBol401Upper(List overData, CandleDataList candleDataM1) { var returnData = new CandleDataList(); + foreach (var item in overData) { diff --git a/Million/Manager/SellLogicManager.cs b/Million/Manager/SellLogicManager.cs index 4f6a167..64324ab 100644 --- a/Million/Manager/SellLogicManager.cs +++ b/Million/Manager/SellLogicManager.cs @@ -1,4 +1,5 @@ -using System; +using Million.Data; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,5 +12,43 @@ namespace Million.Manager /// public static class SellLogicManager { + /// + /// 일목 하향돌파(선형1,2중 큰값) 판매 조건 계산 + /// + /// + /// + /// + public static List GetSellLogicOverUnderIch(List candleDataM) + { + var list = candleDataM.Where(t => t.IndicatorDic.ContainsKey("Ich") && + t.IndicatorDic["Ich"] != null && + ((IchimokData)t.IndicatorDic["Ich"]).GetOverStatus() <= OverStatus.UnderOver).ToList(); + foreach(var item in list) + { + item.SellLogicFlag[Enum.GetName(typeof(CommonProperty.SellLogicKeyList), CommonProperty.SellLogicKeyList.IchMok)] = true; + } + return list; + } + + /// + /// Bol 하향돌파 + /// + /// + /// + /// + public static List GetSellLogicOVerUnderBol(List candleDataM, int period, int factor) + { + var keyName = "Bol" + period.ToString() + factor.ToString(); + var list = candleDataM.Where(t => t.IndicatorDic.ContainsKey(keyName) && + t.IndicatorDic[keyName] != null && + t.IndicatorDic[keyName].overStatus <= OverStatus.UnderOver).ToList(); + + foreach (var item in list) + { + item.SellLogicFlag[keyName] = true; + } + return list; + } + } } diff --git a/Million/Manager/ValidationCheckManager.cs b/Million/Manager/ValidationCheckManager.cs index 1ea3475..17a24f9 100644 --- a/Million/Manager/ValidationCheckManager.cs +++ b/Million/Manager/ValidationCheckManager.cs @@ -78,6 +78,58 @@ namespace Million.Manager return returnData; } + public static List ValidateCandleDataList(List candleDatas,string codeFullName, MCandleTimeType type = MCandleTimeType.M1) + { + var returnData = new List(); + if (candleDatas == null) return returnData; + var datas = candleDatas; + + if (datas == null || datas.Count < 2) return returnData; + + for (var i = 1; i < datas.Count; i++) + { + var currentData = datas[i]; + var beforeData = datas[i - 1]; + + if (type == MCandleTimeType.M1) + { + var beforeDataM = beforeData.DateTime.Minute; + var currentDataM = currentData.DateTime.Minute; + + if (currentDataM == 0) currentDataM = 60; + + if (currentDataM - beforeDataM == 1) continue; + + var errorCandleData = new ErrorCandleData(); + errorCandleData.CodeFullName = codeFullName; + errorCandleData.ErrorEndData = currentData; + errorCandleData.ErrorEndDate = beforeData.DateTime; + errorCandleData.ErrorStartData = beforeData; + errorCandleData.ErrorStartDate = currentData.DateTime; + returnData.Add(errorCandleData); + } + else if (type == MCandleTimeType.H1) + { + var beforeDataH = beforeData.DateTime.Hour; + var currentDataH = currentData.DateTime.Hour; + + if (currentDataH == 0) currentDataH = 24; + + if (currentDataH - beforeDataH == 1) continue; + + var errorCandleData = new ErrorCandleData(); + errorCandleData.CodeFullName = codeFullName; + errorCandleData.ErrorEndData = currentData; + errorCandleData.ErrorEndDate = beforeData.DateTime; + errorCandleData.ErrorStartData = beforeData; + errorCandleData.ErrorStartDate = currentData.DateTime; + returnData.Add(errorCandleData); + } + } + + return returnData; + } + /// /// 가치 있는 데이터만 잘라서 넣는 데이터 /// @@ -148,7 +200,7 @@ namespace Million.Manager /// Candle Data 기준 사용가능한 Candle Data Return 해주는 함수 /// /// - public static List> GetValidationCandleDatas(MarketData marketData,ref CandleDataList candleDataM1, DateTime startDate, DateTime endDate) + public static List> GetValidationCandleDatas(MarketData marketData, ref CandleDataList candleDataH1, ref CandleDataList candleDataM1, DateTime startDate, DateTime endDate) { if(startDate == null) startDate = new DateTime(2000, 1, 1); @@ -156,13 +208,18 @@ namespace Million.Manager if (endDate == null) endDate = DateTime.Now; - var candleData = DbServiceFunctions.GetCandleData(marketData, startDate, DateTime.Now, MCandleTimeType.H1); + //1시간 + candleDataH1 = DbServiceFunctions.GetCandleData(marketData, startDate, DateTime.Now, MCandleTimeType.H1); + Bollinger_Bands.AddMovingAndBollingerBands(candleDataH1.CandleDataLists_Im, 40, 1); + Ichimoku_cloud.excute(candleDataH1.CandleDataLists_Im); + + //1분봉 candleDataM1 = DbServiceFunctions.GetCandleData(marketData, startDate, DateTime.Now, MCandleTimeType.M1); Bollinger_Bands.AddMovingAndBollingerBands(candleDataM1.CandleDataLists_Im, 40, 1); Bollinger_Bands.AddMovingAndBollingerBands(candleDataM1.CandleDataLists_Im, 40, 2, false); Ichimoku_cloud.excute(candleDataM1.CandleDataLists_Im); - return ValidationCheckManager.SplitValidationCandleDataList(candleData.CandleDataLists_Im, MCandleTimeType.H1); + return SplitValidationCandleDataList(candleDataH1.CandleDataLists_Im, MCandleTimeType.H1); } /// diff --git a/Million/Million Core.csproj b/Million/Million Core.csproj index 617add4..cfe0ccf 100644 --- a/Million/Million Core.csproj +++ b/Million/Million Core.csproj @@ -108,6 +108,7 @@ +