임시 수정

This commit is contained in:
kyh
2024-07-10 11:46:59 +09:00
parent c63771797f
commit ef6eaeb89a
2 changed files with 434 additions and 117 deletions

View File

@@ -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;
@@ -40,7 +41,7 @@ namespace BitgetAPI
// 웹소켓 스레드
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
}
}
/// <summary>
/// Data 처리 관련 Thread
/// </summary>
/// <param name="type"></param>
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();

View File

@@ -17,6 +17,7 @@ using Newtonsoft.Json.Linq;
using DevExpress.Utils.Extensions;
using static BitgetAPI.CommonProperty;
using DateTime = System.DateTime;
using DevExpress.Xpo.Logger;
namespace BitgetAPI.WebService
{
@@ -27,6 +28,10 @@ namespace BitgetAPI.WebService
// 웹소켓 스레드 시작/종료 플래그
public bool Is_th_webSocketThread { get; set; } = false;
public ClientWebSocket webSocket { get; set; } = null;
private object obj = new object();
public List<Dictionary<string, object>> webSocketDataList = new List<Dictionary<string, object>>();
CommonProperty commonProperty = CommonProperty.Instance;
public static object SendWebServer(CommonProperty.ExchangeWebReqType exchangeWebReqType, string url = "",
MarketCandleDataList marketCandleDataList = null, CommonProperty.MCandleTimeType interval = MCandleTimeType.M1,
@@ -281,7 +286,7 @@ namespace BitgetAPI.WebService
* secretKey : 사용자가 APIKey를 신청할 때 생성되는 보안 키입니다. 예: 22582BD0CFF14C41EDBF1AB98506286D
*/
CommonProperty commonProperty = CommonProperty.Instance;
webSocket = new ClientWebSocket();
@@ -330,7 +335,370 @@ namespace BitgetAPI.WebService
}
}
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(message);
lock (obj)
{
webSocketDataList.Add(datalist);
}
#region 접어 둘거
//if (datalist.ContainsKey("data"))
//{
// switch (bitgetWebSocketType)
// {
// case CommonProperty.BitgetWebSocketType.현황정보_전체종목:
// {
// var candleInfo = JsonConvert.DeserializeObject<List<WebSocketTickerInfo>>(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<Dictionary<string, object>>(datalist["arg"]?.ToString());
// var candleInfos = JsonConvert.DeserializeObject<List<List<object>>>(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<byte>(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<Dictionary<string, object>>();
lock (obj)
{
try
{
foreach (var item in webSocketDataList)
{
var dic = new Dictionary<string, object>();
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)
@@ -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;
}
@@ -576,83 +948,12 @@ namespace BitgetAPI.WebService
#endregion
break;
}
}
}
} catch(Exception e)
{
}
}
}
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<byte>(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;
}
}
}
}