From bea301ffd75f8f07254239d438109a6a065568d2 Mon Sep 17 00:00:00 2001 From: kyh <1329522@naver.com> Date: Thu, 11 Jul 2024 11:27:14 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BitgetApi/MainForm.cs | 28 +- BitgetApi/WebService/WebConnection.cs | 368 +++++++++++++------------- 2 files changed, 202 insertions(+), 194 deletions(-) diff --git a/BitgetApi/MainForm.cs b/BitgetApi/MainForm.cs index 16f1374..7b720f4 100644 --- a/BitgetApi/MainForm.cs +++ b/BitgetApi/MainForm.cs @@ -40,7 +40,7 @@ namespace BitgetAPI Thread th_MarketInfoList_WebService = null; // 웹소켓 스레드 Thread th_ticker_Websocket = null; - + Thread dataCalculateThread = null; WebConnection webConnection = new WebConnection(); // 스레드 종료 플래그 bool Is_th_th_MarketInfoList_WebService = false; @@ -172,9 +172,17 @@ namespace BitgetAPI /// private void DataCalculateThread(BitgetWebSocketType type) { + var flag = true; + while (webConnection.Is_th_webSocketThread) { webConnection.CalculateDataList(type); + if (flag) + { + th_SignalInfo = new Thread(new ThreadStart(Signalnfo)); + th_SignalInfo.Start(); + } + flag = false; } } @@ -287,13 +295,11 @@ namespace BitgetAPI progressBarControl_data.EditValue = progressCnt; progressBarControl_data.PerformStep(); progressBarControl_data.Update(); - })); - } - - // 웹서비스 호출 완료 되면 시작 - // 신호검색 스레드 - th_SignalInfo = new Thread(new ThreadStart(Signalnfo)); - th_SignalInfo.Start(); + })); + + } + dataCalculateThread = new Thread(() => DataCalculateThread(BitgetWebSocketType.현황정보_전체종목)); + dataCalculateThread.Start(); } // 거래소 콤보박스 클릭 시 이벤트 처리 @@ -522,10 +528,6 @@ namespace BitgetAPI commonProperty.webConnection = webConnection; webConnection.Is_th_webSocketThread = true; webConnection.BitGetWebSocektStart(BitgetWebSocketType.현황정보_전체종목, dic); - - Thread dataCalculateThread = new Thread(() => DataCalculateThread(BitgetWebSocketType.현황정보_전체종목)); - dataCalculateThread.Start(); - //th_webSocketThread = new Thread(() => TheadWebSocketRecieve(BitgetWebSocketType.현황정보_전체종목, dic)); //th_webSocketThread.Start(); @@ -539,7 +541,7 @@ namespace BitgetAPI // 트리 현황판 업데이트 th_treeListMarketInfoListUpdateTimer = new Thread(new ThreadStart(TreeListMarketInfoListUpdate)); - th_treeListMarketInfoListUpdateTimer.Start(); + th_treeListMarketInfoListUpdateTimer.Start(); } } } diff --git a/BitgetApi/WebService/WebConnection.cs b/BitgetApi/WebService/WebConnection.cs index 0444056..f2ce046 100644 --- a/BitgetApi/WebService/WebConnection.cs +++ b/BitgetApi/WebService/WebConnection.cs @@ -697,196 +697,70 @@ namespace BitgetAPI.WebService } } - foreach (var datalist in cloneList) + + var dataList = cloneList.Where(t => t.ContainsKey("data")).Select(t => t["data"]); + var list = JsonConvert.DeserializeObject>>(JsonConvert.SerializeObject(dataList)); + + list = list.OrderBy(t => t[0].ts).ToList(); + + + switch (bitgetWebSocketType) { - if (datalist.ContainsKey("data")) - { - switch (bitgetWebSocketType) + case CommonProperty.BitgetWebSocketType.현황정보_전체종목: { - case CommonProperty.BitgetWebSocketType.현황정보_전체종목: + foreach (var datalist in list) + { + var candleInfo = datalist; + var tickerList = candleInfo[0]; + + DateTime dt = new DateTime(1970, 01, 01); + tickerList.reciveTime = dt.AddMilliseconds(Convert.ToDouble(tickerList.ts)).ToLocalTime(); + + // 웹소켓 티커 리스트에 추가 (사용 안함) + /* + var searchIndex = commonProperty.webSocketCandles.IndexOf(i => i.instId == tickerList.instId); + if (searchIndex < 0) + commonProperty.webSocketCandles.Add(tickerList); + else { - var candleInfo = JsonConvert.DeserializeObject>(datalist["data"]?.ToString()); - var tickerList = candleInfo[0]; - - DateTime dt = new DateTime(1970, 01, 01); - tickerList.reciveTime = dt.AddMilliseconds(Convert.ToDouble(tickerList.ts)).ToLocalTime(); - - // 웹소켓 티커 리스트에 추가 (사용 안함) - /* - var searchIndex = commonProperty.webSocketCandles.IndexOf(i => i.instId == tickerList.instId); - if (searchIndex < 0) - commonProperty.webSocketCandles.Add(tickerList); - else - { - commonProperty.webSocketCandles[searchIndex] = tickerList; - } - */ - - // 캔들 리스트에서 해당 데이터 찾기 - var searchIndex_c = commonProperty.candleDataLists.IndexOf(i => i.ConGoodsData.MarketName == tickerList.instId); - - // 캔들 리스트에 업데이트 (전체 시간별) - foreach (CommonProperty.MCandleTimeType interval in Enum.GetValues(typeof(CommonProperty.MCandleTimeType))) - { - var candleDataList = commonProperty.candleDataLists[searchIndex_c].candleDataList[interval]; - - // 캔들 리스트에 추가 - var candleData = new CandleData(); - candleData.Argument = tickerList.reciveTime; - candleData.Close = tickerList.lastPr; - - // 캔들 리스트가 없으면 추가 - if (candleDataList.Count == 0) - candleDataList.Add(candleData); - else - { - var lastCandleData_Edit = candleDataList.ToList(); - - // 마지막 시간 데이터 가져오기 - var lastCandleData = lastCandleData_Edit.Find(j => j.Argument == lastCandleData_Edit.Max(i => i.Argument)); - if (lastCandleData == null) return; - - // 업데이트 or 추가 - bool updateFlag = true; - - switch (interval) - { - case CommonProperty.MCandleTimeType.M1: - // 같은 분이면 무조건 업데이트 - if (lastCandleData.Argument.Minute != candleData.Argument.Minute) - updateFlag = false; - break; - case CommonProperty.MCandleTimeType.M3: - // 같은 분이면 무조건 업데이트 - if (lastCandleData.Argument.Minute != candleData.Argument.Minute && - candleData.Argument.Minute % 3 == 1) updateFlag = false; - break; - case CommonProperty.MCandleTimeType.M5: - if (lastCandleData.Argument.Minute != candleData.Argument.Minute && - candleData.Argument.Minute % 5 == 1) updateFlag = false; - break; - case CommonProperty.MCandleTimeType.M15: - if (lastCandleData.Argument.Minute != candleData.Argument.Minute && - candleData.Argument.Minute % 15 == 1) updateFlag = false; - break; - case CommonProperty.MCandleTimeType.M30: - if (lastCandleData.Argument.Minute != candleData.Argument.Minute && - candleData.Argument.Minute % 30 == 1) updateFlag = false; - break; - case CommonProperty.MCandleTimeType.H1: - if (lastCandleData.Argument.Hour != candleData.Argument.Hour) - updateFlag = false; - break; - case CommonProperty.MCandleTimeType.H4: - if (lastCandleData.Argument.Hour != candleData.Argument.Hour && - candleData.Argument.Hour % 4 == 1) updateFlag = false; - break; - case CommonProperty.MCandleTimeType.H6: - if (lastCandleData.Argument.Hour != candleData.Argument.Hour && - candleData.Argument.Hour % 6 == 1) updateFlag = false; - break; - case CommonProperty.MCandleTimeType.H12: - if (lastCandleData.Argument.Hour != candleData.Argument.Hour && - candleData.Argument.Hour % 12 == 1) updateFlag = false; - break; - } - - // 이미 등록된 시간 캔들이 있는 경우 변경 - if (updateFlag) - { - // 시간 업데이트 - lastCandleData.Argument = candleData.Argument; - // 종가 수정 - lastCandleData.Close = candleData.Close; - // 저가 등록 - if (lastCandleData.Low == 0 || lastCandleData.Low > candleData.Close) lastCandleData.Low = candleData.Close; - // 고가 등록 - if (lastCandleData.High == 0 || lastCandleData.High < candleData.Close) lastCandleData.High = candleData.Close; - - lastCandleData.WebSocketUpdate = true; - } - // 없는 경우 추가 - else - { - if (candleData.Open == 0) { } - // 1분 이상 Ticker가 없는 겨우는 Open 가만 가격이 등록됨 - candleData.Open = candleData.Close; - - candleData.WebSocketUpdate = true; - - // 새 데이터 등록 - candleDataList.Add(candleData); - - // 기존 데이터 삭제 - if (candleDataList.Count > 250) - { - // 가장 오래된 데이터 삭제 - candleDataList.Remove(j => j.Argument == candleDataList.Min(i => i.Argument)); - } - } - } - - } - + commonProperty.webSocketCandles[searchIndex] = tickerList; } - break; - case CommonProperty.BitgetWebSocketType.캔들정보: - #region 캔들 웹소켓 : 종목 50, 캔들 1 개만 해도 뒤지려고 함 !! (일딴 패스) + */ + + // 캔들 리스트에서 해당 데이터 찾기 + var searchIndex_c = commonProperty.candleDataLists.IndexOf(i => i.ConGoodsData.MarketName == tickerList.instId); + + // 캔들 리스트에 업데이트 (전체 시간별) + foreach (CommonProperty.MCandleTimeType interval in Enum.GetValues(typeof(CommonProperty.MCandleTimeType))) { - var argList = JsonConvert.DeserializeObject>(datalist["arg"]?.ToString()); + var candleDataList = commonProperty.candleDataLists[searchIndex_c].candleDataList[interval]; - var candleInfos = JsonConvert.DeserializeObject>>(datalist["data"]?.ToString()); - var candleInfo = candleInfos[0]; - - DateTime dt = new DateTime(1970, 01, 01); - var candleData = new CandleData( - dt.AddMilliseconds(Convert.ToDouble(candleInfo[0])).ToLocalTime(), - Convert.ToDouble(candleInfo[1]), - Convert.ToDouble(candleInfo[2]), - Convert.ToDouble(candleInfo[3]), - Convert.ToDouble(candleInfo[4]), - Convert.ToDouble(candleInfo[5]), - Convert.ToDouble(candleInfo[6]), - Convert.ToDouble(candleInfo[7]) - ); - - // Websocket 캔들 정보 구분 하기 (1분, 1시간 등) - CommonProperty.MCandleTimeType mCandleTimeType = CommonProperty.MCandleTimeType.H1; - foreach (var interval in Enum.GetValues(typeof(CommonProperty.MCandleTimeType))) - { - // Description - var description = Utils.Convertor.GetEnumDescription((Enum)interval); - if (argList["channel"].ToString().Contains(description)) - mCandleTimeType = (CommonProperty.MCandleTimeType)interval; - break; - } - - // 캔들 리스트에서 해당 데이터 찾기 - var searchIndex = commonProperty.candleDataLists.IndexOf(i => i.ConGoodsData.MarketName == argList["instId"].ToString()); - - var candleDataList = commonProperty.candleDataLists[searchIndex].candleDataList[mCandleTimeType]; - - // 마지막 데이터 (최신데이터) 가져오기 - CandleData lastCandleData = null; + // 캔들 리스트에 추가 + var candleData = new CandleData(); + candleData.Argument = tickerList.reciveTime; + candleData.Close = tickerList.lastPr; + // 캔들 리스트가 없으면 추가 if (candleDataList.Count == 0) candleDataList.Add(candleData); else { - lastCandleData = commonProperty.candleDataLists[searchIndex].candleDataList[mCandleTimeType].Last(); + var lastCandleData_Edit = candleDataList.ToList(); - // 최신데이터와 비교하여 교체/등록하기 + // 마지막 시간 데이터 가져오기 + var lastCandleData = lastCandleData_Edit.Find(j => j.Argument == lastCandleData_Edit.Max(i => i.Argument)); + if (lastCandleData == null || lastCandleData.Argument > candleData.Argument) return; // 업데이트 or 추가 bool updateFlag = false; - switch (mCandleTimeType) + switch (interval) { case CommonProperty.MCandleTimeType.M1: if (lastCandleData.Argument.Minute == candleData.Argument.Minute) updateFlag = true; break; - case CommonProperty.MCandleTimeType.M3: + case CommonProperty.MCandleTimeType.M3: if (candleData.Argument.Minute % 3 != 0 || (candleData.Argument.Minute % 3 == 0 && candleData.Argument.Minute == lastCandleData.Argument.Minute)) updateFlag = true; break; @@ -923,34 +797,166 @@ namespace BitgetAPI.WebService // 이미 등록된 시간 캔들이 있는 경우 변경 if (updateFlag) { - lastCandleData = candleData; + // 시간 업데이트 + lastCandleData.Argument = candleData.Argument; + // 종가 수정 + lastCandleData.Close = candleData.Close; + // 저가 등록 + if (lastCandleData.Low == 0 || lastCandleData.Low > candleData.Close) lastCandleData.Low = candleData.Close; + // 고가 등록 + if (lastCandleData.High == 0 || lastCandleData.High < candleData.Close) lastCandleData.High = candleData.Close; + + lastCandleData.WebSocketUpdate = true; } // 없는 경우 추가 else { - lastCandleData.Close = candleData.Open; + if (candleData.Open == 0) { } + // 1분 이상 Ticker가 없는 겨우는 Open 가만 가격이 등록됨 + candleData.Open = candleData.Close; + + candleData.WebSocketUpdate = true; + // 새 데이터 등록 candleDataList.Add(candleData); + // 기존 데이터 삭제 if (candleDataList.Count > 250) { + // 가장 오래된 데이터 삭제 + candleDataList.Remove(j => j.Argument == candleDataList.Min(i => i.Argument)); + } + } + } - var minData = candleDataList.Min(t => t.Argument); - var minCandle = candleDataList.FirstOrDefault(t => t.Argument == minData); - if (minCandle != null) - { - candleDataList.Remove(minCandle); - } + } + + } + } + break; + case CommonProperty.BitgetWebSocketType.캔들정보: + #region 캔들 웹소켓 : 종목 50, 캔들 1 개만 해도 뒤지려고 함 !! (일딴 패스) + { + foreach (var datalist in cloneList) + { + var argList = JsonConvert.DeserializeObject>(datalist["arg"]?.ToString()); + + var candleInfos = JsonConvert.DeserializeObject>>(datalist["data"]?.ToString()); + var candleInfo = candleInfos[0]; + + DateTime dt = new DateTime(1970, 01, 01); + var candleData = new CandleData( + dt.AddMilliseconds(Convert.ToDouble(candleInfo[0])).ToLocalTime(), + Convert.ToDouble(candleInfo[1]), + Convert.ToDouble(candleInfo[2]), + Convert.ToDouble(candleInfo[3]), + Convert.ToDouble(candleInfo[4]), + Convert.ToDouble(candleInfo[5]), + Convert.ToDouble(candleInfo[6]), + Convert.ToDouble(candleInfo[7]) + ); + + // Websocket 캔들 정보 구분 하기 (1분, 1시간 등) + CommonProperty.MCandleTimeType mCandleTimeType = CommonProperty.MCandleTimeType.H1; + foreach (var interval in Enum.GetValues(typeof(CommonProperty.MCandleTimeType))) + { + // Description + var description = Utils.Convertor.GetEnumDescription((Enum)interval); + if (argList["channel"].ToString().Contains(description)) + mCandleTimeType = (CommonProperty.MCandleTimeType)interval; + break; + } + + // 캔들 리스트에서 해당 데이터 찾기 + var searchIndex = commonProperty.candleDataLists.IndexOf(i => i.ConGoodsData.MarketName == argList["instId"].ToString()); + + var candleDataList = commonProperty.candleDataLists[searchIndex].candleDataList[mCandleTimeType]; + + // 마지막 데이터 (최신데이터) 가져오기 + CandleData lastCandleData = null; + + if (candleDataList.Count == 0) + candleDataList.Add(candleData); + else + { + lastCandleData = commonProperty.candleDataLists[searchIndex].candleDataList[mCandleTimeType].Last(); + + // 최신데이터와 비교하여 교체/등록하기 + + // 업데이트 or 추가 + bool updateFlag = false; + + switch (mCandleTimeType) + { + case CommonProperty.MCandleTimeType.M1: + if (lastCandleData.Argument.Minute == candleData.Argument.Minute) + updateFlag = true; + break; + case CommonProperty.MCandleTimeType.M3: + if (candleData.Argument.Minute % 3 != 0 || (candleData.Argument.Minute % 3 == 0 && candleData.Argument.Minute == lastCandleData.Argument.Minute)) + updateFlag = true; + break; + case CommonProperty.MCandleTimeType.M5: + if (candleData.Argument.Minute % 5 != 0 || (candleData.Argument.Minute % 5 == 0 && candleData.Argument.Minute == lastCandleData.Argument.Minute)) + updateFlag = true; + break; + case CommonProperty.MCandleTimeType.M15: + if (candleData.Argument.Minute % 15 != 0 || (candleData.Argument.Minute % 15 == 0 && candleData.Argument.Minute == lastCandleData.Argument.Minute)) + updateFlag = true; + break; + case CommonProperty.MCandleTimeType.M30: + if (candleData.Argument.Minute % 30 != 0 || (candleData.Argument.Minute % 30 == 0 && candleData.Argument.Minute == lastCandleData.Argument.Minute)) + updateFlag = true; + break; + case CommonProperty.MCandleTimeType.H1: + if (candleData.Argument.Hour == candleData.Argument.Hour) + updateFlag = true; + break; + case CommonProperty.MCandleTimeType.H4: + if (candleData.Argument.Hour % 4 != 0 || (candleData.Argument.Hour % 4 == 0 && candleData.Argument.Hour == lastCandleData.Argument.Hour)) + updateFlag = true; + break; + case CommonProperty.MCandleTimeType.H6: + if (candleData.Argument.Hour % 6 != 0 || (candleData.Argument.Hour % 6 == 0 && candleData.Argument.Hour == lastCandleData.Argument.Hour)) + updateFlag = true; + break; + case CommonProperty.MCandleTimeType.H12: + if (candleData.Argument.Hour % 12 != 0 || (candleData.Argument.Hour % 12 == 0 && candleData.Argument.Hour == lastCandleData.Argument.Hour)) + updateFlag = true; + break; + } + + // 이미 등록된 시간 캔들이 있는 경우 변경 + if (updateFlag) + { + lastCandleData = candleData; + } + // 없는 경우 추가 + else + { + lastCandleData.Close = candleData.Open; + // 새 데이터 등록 + candleDataList.Add(candleData); + // 기존 데이터 삭제 + if (candleDataList.Count > 250) + { + + var minData = candleDataList.Min(t => t.Argument); + var minCandle = candleDataList.FirstOrDefault(t => t.Argument == minData); + if (minCandle != null) + { + candleDataList.Remove(minCandle); } } } } - #endregion - break; + } } - } + #endregion + break; } - } catch(Exception e) + } + catch (Exception e) { }