From ef6eaeb89acaa949c349dc4669c60fea5c7fd2fa Mon Sep 17 00:00:00 2001 From: kyh <1329522@naver.com> Date: Wed, 10 Jul 2024 11:46:59 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9E=84=EC=8B=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BitgetApi/MainForm.cs | 22 +- BitgetApi/WebService/WebConnection.cs | 529 ++++++++++++++++++++------ 2 files changed, 434 insertions(+), 117 deletions(-) diff --git a/BitgetApi/MainForm.cs b/BitgetApi/MainForm.cs index 2a4db9a..16f1374 100644 --- a/BitgetApi/MainForm.cs +++ b/BitgetApi/MainForm.cs @@ -15,6 +15,7 @@ using System.Drawing; using System.Linq; using System.Net.WebSockets; using System.Reflection; +using System.Security; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -39,8 +40,8 @@ namespace BitgetAPI Thread th_MarketInfoList_WebService = null; // 웹소켓 스레드 Thread th_ticker_Websocket = null; - + WebConnection webConnection = new WebConnection(); // 스레드 종료 플래그 bool Is_th_th_MarketInfoList_WebService = false; bool Is_th_treeListUpdate = false; @@ -165,6 +166,18 @@ namespace BitgetAPI } } + /// + /// Data 처리 관련 Thread + /// + /// + private void DataCalculateThread(BitgetWebSocketType type) + { + while (webConnection.Is_th_webSocketThread) + { + webConnection.CalculateDataList(type); + } + } + // 신호검색 Thread 함수 private void Signalnfo() { @@ -505,11 +518,14 @@ namespace BitgetAPI // 웹소켓으로 캔들 쌓기 // WebSocket 생성 - WebConnection webConnection = new WebConnection(); + 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(); diff --git a/BitgetApi/WebService/WebConnection.cs b/BitgetApi/WebService/WebConnection.cs index 35201b5..0444056 100644 --- a/BitgetApi/WebService/WebConnection.cs +++ b/BitgetApi/WebService/WebConnection.cs @@ -17,18 +17,23 @@ using Newtonsoft.Json.Linq; using DevExpress.Utils.Extensions; using static BitgetAPI.CommonProperty; using DateTime = System.DateTime; +using DevExpress.Xpo.Logger; namespace BitgetAPI.WebService { public class WebConnection { - public Thread th_PingTimer {get; set;} = null; + public Thread th_PingTimer { get; set; } = null; // 웹소켓 스레드 시작/종료 플래그 public bool Is_th_webSocketThread { get; set; } = false; public ClientWebSocket webSocket { get; set; } = null; + private object obj = new object(); + public List> webSocketDataList = new List>(); - public static object SendWebServer(CommonProperty.ExchangeWebReqType exchangeWebReqType, string url = "", + CommonProperty commonProperty = CommonProperty.Instance; + + public static object SendWebServer(CommonProperty.ExchangeWebReqType exchangeWebReqType, string url = "", MarketCandleDataList marketCandleDataList = null, CommonProperty.MCandleTimeType interval = MCandleTimeType.M1, string postData = "", string subUri = "") { @@ -49,7 +54,7 @@ namespace BitgetAPI.WebService // 1. WebRequest 객체 형성 및 HttpWebRequest 로 형변환 // 2. 거래소에 따른 헤더 파일 처리(POST 일 경우만 지정함) - if(string.IsNullOrEmpty(url)) + if (string.IsNullOrEmpty(url)) { switch (exchangeWebReqType) { @@ -76,7 +81,7 @@ namespace BitgetAPI.WebService #endregion } } - else wReq= (HttpWebRequest)WebRequest.Create(new Uri(url)); + else wReq = (HttpWebRequest)WebRequest.Create(new Uri(url)); // GET, POST 구분 @@ -104,14 +109,14 @@ namespace BitgetAPI.WebService { #region Bitget case CommonProperty.ExchangeWebReqType.BitgetMarket_Spot: - { + { var datalist = JsonConvert.DeserializeObject>(resResult); var marketInfo = JsonConvert.DeserializeObject>>(datalist["data"]?.ToString()); var data = marketInfo.FindAll(x => x["coin"].ToString().Contains("USDT")); - } - break; + } + break; case CommonProperty.ExchangeWebReqType.BitgetMarket_Future: - { + { var datalist = JsonConvert.DeserializeObject>(resResult); var marketInfos = JsonConvert.DeserializeObject>>(datalist["data"]?.ToString()); @@ -133,13 +138,13 @@ namespace BitgetAPI.WebService } return commonProperty.marketInfoList; - } - break; + } + break; case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Coin: - { + { - } - break; + } + break; case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Future: { var datalist = JsonConvert.DeserializeObject>(resResult); @@ -149,7 +154,7 @@ namespace BitgetAPI.WebService var candleDataList = marketCandleDataList.candleDataList[interval]; - foreach(var item in datas) + foreach (var item in datas) { CandleData candleData = new CandleData(); @@ -163,9 +168,9 @@ namespace BitgetAPI.WebService // 같은 시간이 존재하면 업데이트 : 1개밖에 없음 // 마지막 시간 데이터는 불완전 > 웹소켓 데이터와 합체 - if(item == datas.Last()) + if (item == datas.Last()) { - var timespan_add = new System.TimeSpan(0,0,0); + var timespan_add = new System.TimeSpan(0, 0, 0); switch (interval) { @@ -203,7 +208,7 @@ namespace BitgetAPI.WebService var sameCandleData_WebService = candleDataList.Find(i => candleData.Argument <= i.Argument && i.Argument < (candleData.Argument + timespan_add) && i.WebSocketUpdate == true); - if(sameCandleData_WebService != null) + if (sameCandleData_WebService != null) { // 종가 => 웹소켓 데이터 사용 (웹 서비스 호출 데이터 중 마지막 데이터는 캔들이 완성되지 않음) // 시가 => 웹 서비스 데이터 사용 @@ -219,7 +224,7 @@ namespace BitgetAPI.WebService candleDataList.Add(candleData); candleData.WebServiceUpdate = true; } - + } /* //var sameCandleData_WebService = candleDataList.Find(i => i.Argument.Minute == candleData.Argument.Minute && @@ -241,7 +246,7 @@ namespace BitgetAPI.WebService } } break; - #endregion + #endregion } } } @@ -281,7 +286,7 @@ namespace BitgetAPI.WebService * secretKey : 사용자가 APIKey를 신청할 때 생성되는 보안 키입니다. 예: 22582BD0CFF14C41EDBF1AB98506286D */ - CommonProperty commonProperty = CommonProperty.Instance; + webSocket = new ClientWebSocket(); @@ -330,10 +335,373 @@ namespace BitgetAPI.WebService } } var datalist = JsonConvert.DeserializeObject>(message); + lock (obj) + { + webSocketDataList.Add(datalist); + } + #region 접어 둘거 + //if (datalist.ContainsKey("data")) + //{ + // switch (bitgetWebSocketType) + // { + // case CommonProperty.BitgetWebSocketType.현황정보_전체종목: + // { + // 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)); + // } + // } + // } + + // } + + // } + // break; + // case CommonProperty.BitgetWebSocketType.캔들정보: + // #region 캔들 웹소켓 : 종목 50, 캔들 1 개만 해도 뒤지려고 함 !! (일딴 패스) + // { + // 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 + } + } + + catch (Exception ex) + { + Console.WriteLine("WebSocket 연결 중 오류 발생: " + ex.Message); + } + finally + { + closeWebSocket(); + + // 웹소켓 재귀 + if (Is_th_webSocketThread) + { + BitGetWebSocektStart(bitgetWebSocketType, dic); + } + } + } + + // 웹소켓 종료 + public async void closeWebSocket() + { + if (webSocket != null) + { + if (webSocket.State == WebSocketState.Open) + { + if (th_PingTimer != null) + { + th_PingTimer.Abort(); + th_PingTimer = null; + } + + await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "WebSocket 연결 종료", CancellationToken.None); + } + + webSocket.Dispose(); + } + + } + + // Ping 테스트 (25초), 30초에 한번 응답 확인 필요 + public static async void ContinuePing(ClientWebSocket webSocket) + { + while (true) + { + Thread.Sleep(25000); + await SendMessage(webSocket, "ping"); + } + } + + private static async Task SendMessage(ClientWebSocket webSocket, string message) + { + try + { + byte[] buffer = Encoding.UTF8.GetBytes(message); + await webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); + Console.WriteLine("메시지 전송: " + message); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + public static bool ValidateJSON(string s) + { + try + { + JToken.Parse(s); + return true; + } + catch (JsonReaderException) + { + return false; + } + } + + public void CalculateDataList(BitgetWebSocketType bitgetWebSocketType) + { + try + { + var cloneList = new List>(); + lock (obj) + { + try + { + foreach (var item in webSocketDataList) + { + var dic = new Dictionary(); + + foreach (var key in item.Keys) + { + dic[key] = item[key]; + } + + cloneList.Add(dic); + } + webSocketDataList.Clear(); + } + catch (Exception e) + { + + } + } + foreach (var datalist in cloneList) + { if (datalist.ContainsKey("data")) { - switch(bitgetWebSocketType) + switch (bitgetWebSocketType) { case CommonProperty.BitgetWebSocketType.현황정보_전체종목: { @@ -356,7 +724,7 @@ namespace BitgetAPI.WebService // 캔들 리스트에서 해당 데이터 찾기 var searchIndex_c = commonProperty.candleDataLists.IndexOf(i => i.ConGoodsData.MarketName == tickerList.instId); - + // 캔들 리스트에 업데이트 (전체 시간별) foreach (CommonProperty.MCandleTimeType interval in Enum.GetValues(typeof(CommonProperty.MCandleTimeType))) { @@ -372,10 +740,10 @@ namespace BitgetAPI.WebService candleDataList.Add(candleData); else { - var lastCandleData_Edit = candleDataList.ToList(); + var lastCandleData_Edit = candleDataList.ToList(); // 마지막 시간 데이터 가져오기 - var lastCandleData = lastCandleData_Edit.Find(j=>j.Argument == lastCandleData_Edit.Max(i => i.Argument)); + var lastCandleData = lastCandleData_Edit.Find(j => j.Argument == lastCandleData_Edit.Max(i => i.Argument)); if (lastCandleData == null) return; // 업데이트 or 추가 @@ -390,7 +758,7 @@ namespace BitgetAPI.WebService break; case CommonProperty.MCandleTimeType.M3: // 같은 분이면 무조건 업데이트 - if (lastCandleData.Argument.Minute != candleData.Argument.Minute && + if (lastCandleData.Argument.Minute != candleData.Argument.Minute && candleData.Argument.Minute % 3 == 1) updateFlag = false; break; case CommonProperty.MCandleTimeType.M5: @@ -431,7 +799,7 @@ namespace BitgetAPI.WebService // 종가 수정 lastCandleData.Close = candleData.Close; // 저가 등록 - if(lastCandleData.Low == 0 || lastCandleData.Low > candleData.Close) lastCandleData.Low = 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; @@ -457,18 +825,18 @@ namespace BitgetAPI.WebService } } } - + } - + } break; case CommonProperty.BitgetWebSocketType.캔들정보: #region 캔들 웹소켓 : 종목 50, 캔들 1 개만 해도 뒤지려고 함 !! (일딴 패스) { - var argList = JsonConvert.DeserializeObject>(datalist["arg"]?.ToString()); + var argList = JsonConvert.DeserializeObject>(datalist["arg"]?.ToString()); var candleInfos = JsonConvert.DeserializeObject>>(datalist["data"]?.ToString()); - var candleInfo = candleInfos[0]; + var candleInfo = candleInfos[0]; DateTime dt = new DateTime(1970, 01, 01); var candleData = new CandleData( @@ -489,13 +857,13 @@ namespace BitgetAPI.WebService // Description var description = Utils.Convertor.GetEnumDescription((Enum)interval); if (argList["channel"].ToString().Contains(description)) - mCandleTimeType = (CommonProperty.MCandleTimeType) interval; + mCandleTimeType = (CommonProperty.MCandleTimeType)interval; break; } // 캔들 리스트에서 해당 데이터 찾기 var searchIndex = commonProperty.candleDataLists.IndexOf(i => i.ConGoodsData.MarketName == argList["instId"].ToString()); - + var candleDataList = commonProperty.candleDataLists[searchIndex].candleDataList[mCandleTimeType]; // 마지막 데이터 (최신데이터) 가져오기 @@ -519,15 +887,19 @@ namespace BitgetAPI.WebService updateFlag = true; break; case CommonProperty.MCandleTimeType.M3: - if (candleData.Argument.Minute % 3 != 1) + 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 != 1) + 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 != 1) + 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: @@ -535,15 +907,15 @@ namespace BitgetAPI.WebService updateFlag = true; break; case CommonProperty.MCandleTimeType.H4: - if (candleData.Argument.Hour % 4 != 1) + 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 != 1) + 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 != 1) + if (candleData.Argument.Hour % 12 != 0 || (candleData.Argument.Hour % 12 == 0 && candleData.Argument.Hour == lastCandleData.Argument.Hour)) updateFlag = true; break; } @@ -560,15 +932,15 @@ namespace BitgetAPI.WebService // 새 데이터 등록 candleDataList.Add(candleData); // 기존 데이터 삭제 - if(candleDataList.Count > 250) + if (candleDataList.Count > 250) { - - var minData = candleDataList.Min(t => t.Argument); + + var minData = candleDataList.Min(t => t.Argument); var minCandle = candleDataList.FirstOrDefault(t => t.Argument == minData); if (minCandle != null) { candleDataList.Remove(minCandle); - } + } } } } @@ -576,82 +948,11 @@ namespace BitgetAPI.WebService #endregion break; } - } - } - } - - catch (Exception ex) + } catch(Exception e) { - Console.WriteLine("WebSocket 연결 중 오류 발생: " + ex.Message); - } - finally - { - closeWebSocket(); - // 웹소켓 재귀 - if (Is_th_webSocketThread) - { - BitGetWebSocektStart(bitgetWebSocketType, dic); - } - } - } - - // 웹소켓 종료 - public async void closeWebSocket() - { - if (webSocket != null) - { - if (webSocket.State == WebSocketState.Open) - { - if (th_PingTimer != null) - { - th_PingTimer.Abort(); - th_PingTimer = null; - } - - await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "WebSocket 연결 종료", CancellationToken.None); - } - - webSocket.Dispose(); - } - - } - - // Ping 테스트 (25초), 30초에 한번 응답 확인 필요 - public static async void ContinuePing(ClientWebSocket webSocket) - { - while(true) - { - Thread.Sleep(25000); - await SendMessage(webSocket, "ping"); - } - } - - private static async Task SendMessage(ClientWebSocket webSocket, string message) - { - try - { - byte[] buffer = Encoding.UTF8.GetBytes(message); - await webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); - Console.WriteLine("메시지 전송: " + message); - } catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - public static bool ValidateJSON(string s) - { - try - { - JToken.Parse(s); - return true; - } - catch (JsonReaderException) - { - return false; } } }