diff --git a/BitgetApi/BitgetApi.csproj b/BitgetApi/BitgetApi.csproj index c525670..058ceae 100644 --- a/BitgetApi/BitgetApi.csproj +++ b/BitgetApi/BitgetApi.csproj @@ -67,6 +67,7 @@ + Form diff --git a/BitgetApi/CommonProperty.cs b/BitgetApi/CommonProperty.cs index 0b1efb2..00826b0 100644 --- a/BitgetApi/CommonProperty.cs +++ b/BitgetApi/CommonProperty.cs @@ -4,8 +4,9 @@ using BitgetAPI.Data; using BitgetAPI.Utils; using System.Collections.Generic; using System.ComponentModel; +using BitgetApi.Data; -namespace BitgetApi +namespace BitgetAPI { public class CommonProperty : BaseSettings { @@ -52,6 +53,11 @@ namespace BitgetApi public List marketInfoList = null; public List candleDataLists = null; + public List webSocketCandles = null; + public WebService.WebConnection webConnection = null; + + // 폼 및 컨트롤 + public MainForm mainform = null; /// /// TODO 업비트 기능 추가 @@ -75,7 +81,7 @@ namespace BitgetApi UpbitMarket = 11, #endregion - #region + #region 비트겟 웹 요청 타입 [Description("BitgetMarketInfo_SPOT")] BitgetMarket_Spot = 20, [Description("BitgetMarketInfo_FUTURE")] diff --git a/BitgetApi/Data/CandleData.cs b/BitgetApi/Data/CandleData.cs index a527277..680a623 100644 --- a/BitgetApi/Data/CandleData.cs +++ b/BitgetApi/Data/CandleData.cs @@ -1,4 +1,4 @@ -using BitgetApi; +using BitgetAPI; using System; using System.Collections.Generic; using System.Linq; diff --git a/BitgetApi/Data/CandleDataList.cs b/BitgetApi/Data/CandleDataList.cs index 0e50174..98b19d9 100644 --- a/BitgetApi/Data/CandleDataList.cs +++ b/BitgetApi/Data/CandleDataList.cs @@ -1,4 +1,4 @@ -using BitgetApi; +using BitgetAPI; using System; using System.Collections.Generic; diff --git a/BitgetApi/Data/WebSocketCandle.cs b/BitgetApi/Data/WebSocketCandle.cs new file mode 100644 index 0000000..763501d --- /dev/null +++ b/BitgetApi/Data/WebSocketCandle.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BitgetApi.Data +{ + public class WebSocketCandle + { + // 종목 + public string instId { get; set; } + // 최종가격 + public double lastPr { get; set; } + // 24시간 시가 + public double open24h { get; set; } + // 24시간 고가 + public double high24h { get; set; } + // 24시간 저가 + public double low24h { get; set; } + // 수익률 + public double change24h { get; set; } + public double bidPr { get; set; } + public double askPr { get; set; } + public double bidSz { get; set; } + public double askSz { get; set; } + // 코인 거래량 + public double baseVolume { get; set; } + // 견적통화 거래량 + public double quoteVolume { get; set; } + public double openUtc { get; set; } + public double changeUtc24h { get; set; } + public long ts { get; set; } + public DateTime reciveTime { get; set; } + } +} diff --git a/BitgetApi/MainForm.Designer.cs b/BitgetApi/MainForm.Designer.cs index 60a3d49..255a5c0 100644 --- a/BitgetApi/MainForm.Designer.cs +++ b/BitgetApi/MainForm.Designer.cs @@ -1,4 +1,4 @@ -namespace BitgetApi +namespace BitgetAPI { partial class MainForm { @@ -34,11 +34,18 @@ this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); this.groupControl_MarketInfo = new DevExpress.XtraEditors.GroupControl(); + this.labelControl_MarketCount = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); this.treeList_MarketInfo = new DevExpress.XtraTreeList.TreeList(); this.treeListColumn_ExchangePlace = new DevExpress.XtraTreeList.Columns.TreeListColumn(); - this.treeListColumn_MarketName = new DevExpress.XtraTreeList.Columns.TreeListColumn(); - this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); - this.labelControl_MarketCount = new DevExpress.XtraEditors.LabelControl(); + this.treeListColumn_instId = new DevExpress.XtraTreeList.Columns.TreeListColumn(); + this.treeListColumn_open24h = new DevExpress.XtraTreeList.Columns.TreeListColumn(); + this.treeListColumn_low24h = new DevExpress.XtraTreeList.Columns.TreeListColumn(); + this.treeListColumn_high24h = new DevExpress.XtraTreeList.Columns.TreeListColumn(); + this.treeListColumn_lastPr = new DevExpress.XtraTreeList.Columns.TreeListColumn(); + this.treeListColumn_change24h = new DevExpress.XtraTreeList.Columns.TreeListColumn(); + this.treeListColumn_baseVolume = new DevExpress.XtraTreeList.Columns.TreeListColumn(); + this.treeListColumn_quoteVolume = new DevExpress.XtraTreeList.Columns.TreeListColumn(); ((System.ComponentModel.ISupportInitialize)(this.groupControl_Setting)).BeginInit(); this.groupControl_Setting.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit_ConinType.Properties)).BeginInit(); @@ -112,6 +119,22 @@ this.groupControl_MarketInfo.TabIndex = 1; this.groupControl_MarketInfo.Text = "종목 현황"; // + // labelControl_MarketCount + // + this.labelControl_MarketCount.Location = new System.Drawing.Point(856, 36); + this.labelControl_MarketCount.Name = "labelControl_MarketCount"; + this.labelControl_MarketCount.Size = new System.Drawing.Size(21, 14); + this.labelControl_MarketCount.TabIndex = 2; + this.labelControl_MarketCount.Text = "220"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(804, 36); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(46, 14); + this.labelControl3.TabIndex = 1; + this.labelControl3.Text = "총 개수 : "; + // // treeList_MarketInfo // this.treeList_MarketInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) @@ -119,7 +142,14 @@ | System.Windows.Forms.AnchorStyles.Right))); this.treeList_MarketInfo.Columns.AddRange(new DevExpress.XtraTreeList.Columns.TreeListColumn[] { this.treeListColumn_ExchangePlace, - this.treeListColumn_MarketName}); + this.treeListColumn_instId, + this.treeListColumn_open24h, + this.treeListColumn_low24h, + this.treeListColumn_high24h, + this.treeListColumn_lastPr, + this.treeListColumn_change24h, + this.treeListColumn_baseVolume, + this.treeListColumn_quoteVolume}); this.treeList_MarketInfo.Location = new System.Drawing.Point(2, 56); this.treeList_MarketInfo.Name = "treeList_MarketInfo"; this.treeList_MarketInfo.Size = new System.Drawing.Size(908, 372); @@ -130,32 +160,72 @@ this.treeListColumn_ExchangePlace.Caption = "거래소"; this.treeListColumn_ExchangePlace.FieldName = "ExchangePlace"; this.treeListColumn_ExchangePlace.Name = "treeListColumn_ExchangePlace"; - this.treeListColumn_ExchangePlace.Visible = true; - this.treeListColumn_ExchangePlace.VisibleIndex = 0; // - // treeListColumn_MarketName + // treeListColumn_instId // - this.treeListColumn_MarketName.Caption = "종목"; - this.treeListColumn_MarketName.FieldName = "MarketName"; - this.treeListColumn_MarketName.Name = "treeListColumn_MarketName"; - this.treeListColumn_MarketName.Visible = true; - this.treeListColumn_MarketName.VisibleIndex = 1; + this.treeListColumn_instId.Caption = "종목"; + this.treeListColumn_instId.FieldName = "instId"; + this.treeListColumn_instId.Name = "treeListColumn_instId"; + this.treeListColumn_instId.Visible = true; + this.treeListColumn_instId.VisibleIndex = 0; // - // labelControl3 + // treeListColumn_open24h // - this.labelControl3.Location = new System.Drawing.Point(804, 36); - this.labelControl3.Name = "labelControl3"; - this.labelControl3.Size = new System.Drawing.Size(46, 14); - this.labelControl3.TabIndex = 1; - this.labelControl3.Text = "총 개수 : "; + this.treeListColumn_open24h.Caption = "시가 (24시간)"; + this.treeListColumn_open24h.FieldName = "open24h"; + this.treeListColumn_open24h.Name = "treeListColumn_open24h"; + this.treeListColumn_open24h.Visible = true; + this.treeListColumn_open24h.VisibleIndex = 1; // - // labelControl_MarketCount + // treeListColumn_low24h // - this.labelControl_MarketCount.Location = new System.Drawing.Point(856, 36); - this.labelControl_MarketCount.Name = "labelControl_MarketCount"; - this.labelControl_MarketCount.Size = new System.Drawing.Size(21, 14); - this.labelControl_MarketCount.TabIndex = 2; - this.labelControl_MarketCount.Text = "220"; + this.treeListColumn_low24h.Caption = "저가 (24시간)"; + this.treeListColumn_low24h.FieldName = "low24h"; + this.treeListColumn_low24h.Name = "treeListColumn_low24h"; + this.treeListColumn_low24h.Visible = true; + this.treeListColumn_low24h.VisibleIndex = 2; + // + // treeListColumn_high24h + // + this.treeListColumn_high24h.Caption = "고가 (24시간 )"; + this.treeListColumn_high24h.FieldName = "high24h"; + this.treeListColumn_high24h.Name = "treeListColumn_high24h"; + this.treeListColumn_high24h.Visible = true; + this.treeListColumn_high24h.VisibleIndex = 3; + // + // treeListColumn_lastPr + // + this.treeListColumn_lastPr.AppearanceCell.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192))))); + this.treeListColumn_lastPr.AppearanceCell.Options.UseBackColor = true; + this.treeListColumn_lastPr.Caption = "현재가"; + this.treeListColumn_lastPr.FieldName = "lastPr"; + this.treeListColumn_lastPr.Name = "treeListColumn_lastPr"; + this.treeListColumn_lastPr.Visible = true; + this.treeListColumn_lastPr.VisibleIndex = 4; + // + // treeListColumn_change24h + // + this.treeListColumn_change24h.Caption = "수익률 (24시간)"; + this.treeListColumn_change24h.FieldName = "change24h"; + this.treeListColumn_change24h.Name = "treeListColumn_change24h"; + this.treeListColumn_change24h.Visible = true; + this.treeListColumn_change24h.VisibleIndex = 5; + // + // treeListColumn_baseVolume + // + this.treeListColumn_baseVolume.Caption = "코인 거래량"; + this.treeListColumn_baseVolume.FieldName = "baseVolume"; + this.treeListColumn_baseVolume.Name = "treeListColumn_baseVolume"; + this.treeListColumn_baseVolume.Visible = true; + this.treeListColumn_baseVolume.VisibleIndex = 6; + // + // treeListColumn_quoteVolume + // + this.treeListColumn_quoteVolume.Caption = "통화 거래량"; + this.treeListColumn_quoteVolume.FieldName = "quoteVolume"; + this.treeListColumn_quoteVolume.Name = "treeListColumn_quoteVolume"; + this.treeListColumn_quoteVolume.Visible = true; + this.treeListColumn_quoteVolume.VisibleIndex = 7; // // MainForm // @@ -189,9 +259,16 @@ private DevExpress.XtraEditors.LabelControl labelControl2; private DevExpress.XtraEditors.LabelControl labelControl1; private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_ExchangePlace; - private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_MarketName; + private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_instId; private DevExpress.XtraEditors.LabelControl labelControl_MarketCount; private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_open24h; + private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_low24h; + private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_high24h; + private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_lastPr; + private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_change24h; + private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_baseVolume; + private DevExpress.XtraTreeList.Columns.TreeListColumn treeListColumn_quoteVolume; } } diff --git a/BitgetApi/MainForm.cs b/BitgetApi/MainForm.cs index 95b8ad5..1606569 100644 --- a/BitgetApi/MainForm.cs +++ b/BitgetApi/MainForm.cs @@ -1,4 +1,5 @@ using BitgetAPI.Data; +using BitgetAPI.WebService; using DevExpress.XtraEditors; using Newtonsoft.Json; using System; @@ -13,9 +14,9 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -using static BitgetApi.CommonProperty; +using static BitgetAPI.CommonProperty; -namespace BitgetApi +namespace BitgetAPI { public partial class MainForm : Form { @@ -31,11 +32,15 @@ namespace BitgetApi // 폼 초기화 작업 public void init() { + commonProperty.mainform = this; + // 거래소 항목 추가 및 설정하기 comboBoxEdit_ExchangePlace.Properties.Items.AddRange(Enum.GetNames(typeof(CommonProperty.ExchangePlace))); comboBoxEdit_ExchangePlace.SelectedIndex = (int)CommonProperty.ExchangePlace.Bitget; commonProperty.selectedChangePlace = CommonProperty.ExchangePlace.Bitget; + treeList_MarketInfo.DataSource = commonProperty.webSocketCandles; + // API Key 가져오기 및 등록 // BITGET Raster 소켓 테스트 @@ -46,81 +51,36 @@ namespace BitgetApi // 구름떼, 볼린저 생성 - // + // 마켓정보 가져오기 (25초), Ping 유지용 + // 트리 현황판 업데이트 + var marketInfoListUpdateTimer = new Thread(new ThreadStart(MarketInfoListUpdate)); + marketInfoListUpdateTimer.Start(); - // + // 트리 현황판 업데이트 + var treeListMarketInfoListUpdateTimer = new Thread(new ThreadStart(TreeListMarketInfoListUpdate)); + treeListMarketInfoListUpdateTimer.Start(); } - public async void webSocektStart() + // 마켓정보 가져오기 !! + private void MarketInfoListUpdate() { - string apiUrl = "https://api.upbit.com/v1/market/all?isDetails=true"; + Thread.Sleep(25000); + // 마켓 정보 가져오기 + var marketInfos = (List)BitgetAPI.WebService.WebConnection.SendWebServer(ExchangeWebReqType.BitgetMarket_Future); + } - // IP당 100개 연결 - // 시간당 240회 !!! - // 타이머 30초 유지 > 30초 이내의 응답 메시지 수신 필요 > 아니면 오류 발생 !! > 재접속 필요 !! - // 초당 10개 메시지 허용 - // 단일 연결로 최대 1000개의 스트림 구독 - // 단인 IP 최대의 100개 연결 - - // * - /* timestamp : Unix Epoch 시간 - * passphrase : APIKey 비밀번호 - * timestamp : Unix Epoch 시간, 단위는 초(--restAPI의 서명 타임스탬프와 다름--) - * secretKey : 사용자가 APIKey를 신청할 때 생성되는 보안 키입니다. 예: 22582BD0CFF14C41EDBF1AB98506286D - */ - - - ClientWebSocket webSocket = new ClientWebSocket(); - - string WebSocketUrl = "wss://ws.bitget.com/v2/ws/public"; - string message = ""; - - try + private void TreeListMarketInfoListUpdate() + { + while(true) { - await webSocket.ConnectAsync(new Uri(WebSocketUrl), CancellationToken.None); - // 연결이 성공적으로 이루어지면 처리할 코드 작성 - Console.WriteLine("WebSocket 연결 성공"); + Thread.Sleep(2000); - var jsonDataText = "{\"op\":\"subscribe\",\"args\":[{\"instType\":\"SPOT\",\"channel\":\"ticker\",\"instId\":\"ETHUSDT\"}, {\"instType\":\"SPOT\",\"channel\":\"ticker\",\"instId\":\"BTCUSDT\"}]}"; - - // test11 = JsonConvert.SerializeObject(jsonData); - - await SendMessage(webSocket, jsonDataText); - - - // 데이터 수신을 위한 반복문 시작 - while (webSocket.State == WebSocketState.Open) + Invoke(new MethodInvoker(delegate () { - byte[] buffer = new byte[1024]; - WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); - message = ""; - // 수신한 데이터 처리 - message = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); - var testData = JsonConvert.DeserializeObject(message); - - Console.WriteLine("수신한 데이터: " + message); - DateTime dt = new DateTime(1970, 01, 01); - dt = dt.AddMilliseconds(testData.trade_timestamp).ToLocalTime(); - } + treeList_MarketInfo.RefreshDataSource(); + treeList_MarketInfo.ClearSelection(); + })); } - catch (Exception ex) - { - Console.WriteLine("WebSocket 연결 중 오류 발생: " + ex.Message); - } - finally - { - if (webSocket.State == WebSocketState.Open) - await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "WebSocket 연결 종료", CancellationToken.None); - - webSocket.Dispose(); - } - } - - private static async Task SendMessage(ClientWebSocket webSocket, string message) - { - byte[] buffer = Encoding.UTF8.GetBytes(message); - await webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); - Console.WriteLine("메시지 전송: " + message); } // 거래소 콤보박스 클릭 시 이벤트 처리 @@ -176,8 +136,26 @@ namespace BitgetApi var candleCount = 200; + // 캔들 리스트 생성하기 + foreach (var item in marketInfos) + { + MarketCandleDataList candleDataList = new MarketCandleDataList(); + candleDataList.ConGoodsData = item; + foreach (var interval in Enum.GetValues(typeof(CommonProperty.MCandleTimeType))) + { + candleDataList.candleDataList.Add((MCandleTimeType)interval, new List()); + } + + candleDataLists.Add(candleDataList); + } + + commonProperty.webSocketCandles = new List(); + + var thread = new Thread(new ThreadStart(ThreadEventAsync)); + thread.Start(); + // 캔들 데이터 가져오기 : 종목, 개수, - foreach(var item in marketInfos) + foreach (var item in marketInfos) { MarketCandleDataList candleDataList = new MarketCandleDataList(); candleDataList.ConGoodsData = item; @@ -222,20 +200,27 @@ namespace BitgetApi break; } - var candleList = BitgetAPI.WebService.WebConnection.SendWebServer(exchangeWebReqType, url); + List candleList = null; + //var candleList = BitgetAPI.WebService.WebConnection.SendWebServer(exchangeWebReqType, url); // 초당 20회 제한 !!!! // Thread.Sleep(50); - candleDataList.candleDataList.Add((MCandleTimeType)interval,(List)candleList); + //candleDataList.candleDataList.Add((MCandleTimeType)interval,(List)candleList); } - candleDataLists.Add(candleDataList); + } var test = ""; test += "1"; + } + private async void ThreadEventAsync() + { + // WebSocket 생성 + commonProperty.webConnection = new WebConnection(); + commonProperty.webConnection.webSocektStart(); } } } diff --git a/BitgetApi/Program.cs b/BitgetApi/Program.cs index 6d8189f..630d662 100644 --- a/BitgetApi/Program.cs +++ b/BitgetApi/Program.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; -namespace BitgetApi +namespace BitgetAPI { internal static class Program { diff --git a/BitgetApi/Properties/AssemblyInfo.cs b/BitgetApi/Properties/AssemblyInfo.cs index d50ef1b..34fb556 100644 --- a/BitgetApi/Properties/AssemblyInfo.cs +++ b/BitgetApi/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ using System.Runtime.InteropServices; // 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 // 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 // 이러한 특성 값을 변경하세요. -[assembly: AssemblyTitle("BitgetApi")] +[assembly: AssemblyTitle("BitgetAPI")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("BitgetApi")] +[assembly: AssemblyProduct("BitgetAPI")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/BitgetApi/Properties/Resources.Designer.cs b/BitgetApi/Properties/Resources.Designer.cs index ae7d954..d95a48a 100644 --- a/BitgetApi/Properties/Resources.Designer.cs +++ b/BitgetApi/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace BitgetApi.Properties +namespace BitgetAPI.Properties { @@ -44,7 +44,7 @@ namespace BitgetApi.Properties { if ((resourceMan == null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BitgetApi.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BitgetAPI.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/BitgetApi/Properties/Settings.Designer.cs b/BitgetApi/Properties/Settings.Designer.cs index c74bdc7..3ce3213 100644 --- a/BitgetApi/Properties/Settings.Designer.cs +++ b/BitgetApi/Properties/Settings.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace BitgetApi.Properties +namespace BitgetAPI.Properties { diff --git a/BitgetApi/Properties/licenses.licx b/BitgetApi/Properties/licenses.licx index 9091129..ea721ae 100644 --- a/BitgetApi/Properties/licenses.licx +++ b/BitgetApi/Properties/licenses.licx @@ -1,2 +1,3 @@ DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v23.2, Version=23.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a DevExpress.XtraTreeList.TreeList, DevExpress.XtraTreeList.v23.2, Version=23.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TreeListLookUpEdit, DevExpress.XtraTreeList.v23.2, Version=23.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/BitgetApi/Utils/Convertor.cs b/BitgetApi/Utils/Convertor.cs index 6e473c0..7c80606 100644 --- a/BitgetApi/Utils/Convertor.cs +++ b/BitgetApi/Utils/Convertor.cs @@ -6,7 +6,7 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; -namespace BitgetApi.Utils +namespace BitgetAPI.Utils { public static class Convertor { diff --git a/BitgetApi/WebService/WebConnection.cs b/BitgetApi/WebService/WebConnection.cs index b57c630..3de6b03 100644 --- a/BitgetApi/WebService/WebConnection.cs +++ b/BitgetApi/WebService/WebConnection.cs @@ -1,5 +1,5 @@ -using BitgetApi; -using BitgetApi.Utils; +using BitgetAPI; +using BitgetAPI.Utils; using BitgetAPI.Data; using BitgetAPI.Utils; using Newtonsoft.Json; @@ -8,8 +8,13 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; +using System.Net.WebSockets; using System.Text; +using System.Threading; using System.Threading.Tasks; +using BitgetApi.Data; +using Newtonsoft.Json.Linq; +using DevExpress.Utils.Extensions; namespace BitgetAPI.WebService { @@ -166,5 +171,165 @@ namespace BitgetAPI.WebService return returnJsonData; } + + public async void webSocektStart() + { + string apiUrl = "https://api.upbit.com/v1/market/all?isDetails=true"; + + // IP당 100개 연결 + // 시간당 240회 !!! + // 타이머 30초 유지 > 30초 이내의 응답 메시지 수신 필요 > 아니면 오류 발생 !! > 재접속 필요 !! + // 초당 10개 메시지 허용 + // 단일 연결로 최대 1000개의 스트림 구독 + // 단인 IP 최대의 100개 연결 + + // * + /* timestamp : Unix Epoch 시간 + * passphrase : APIKey 비밀번호 + * timestamp : Unix Epoch 시간, 단위는 초(--restAPI의 서명 타임스탬프와 다름--) + * secretKey : 사용자가 APIKey를 신청할 때 생성되는 보안 키입니다. 예: 22582BD0CFF14C41EDBF1AB98506286D + */ + + ClientWebSocket webSocket = new ClientWebSocket(); + + string WebSocketUrl = "wss://ws.bitget.com/v2/ws/public"; + string message = ""; + var tempStrData = ""; + + CommonProperty commonProperty = CommonProperty.Instance; + + try + { + await webSocket.ConnectAsync(new Uri(WebSocketUrl), CancellationToken.None); + // 연결이 성공적으로 이루어지면 처리할 코드 작성 + Console.WriteLine("WebSocket 연결 성공"); + + // Json String 만들기 + // 종목별 Ticker 구독하기 + var dic = new Dictionary(); + dic.Add("op", "subscribe"); + + var argsList = new List>(); + foreach (var marketInfo in commonProperty.marketInfoList) + { + var args = new Dictionary(); + args.Add("instType", "USDT-FUTURES"); + args.Add("channel", "ticker"); + //args.Add("channel", "candle1m"); + args.Add("instId", marketInfo.MarketName); + argsList.Add(args); + } + dic.Add("args", argsList); + + //var jsonDataText = "{\"op\":\"subscribe\",\"args\":[{\"instType\":\"SPOT\",\"channel\":\"ticker\",\"instId\":\"ETHUSDT\"}, {\"instType\":\"SPOT\",\"channel\":\"ticker\",\"instId\":\"BTCUSDT\"}]}"; + + var jsonData = JsonConvert.SerializeObject(dic); + + await SendMessage(webSocket, jsonData); + + + // 데이터 수신을 위한 반복문 시작 + while (webSocket.State == WebSocketState.Open) + { + //Thread.Sleep(100); + + byte[] buffer = new byte[1024]; + WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + message = ""; + // 수신한 데이터 처리 + message = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); + + if (!ValidateJSON(message)) + { + tempStrData += message; + if (!ValidateJSON(message)) + { + continue; + } + else + { + message = tempStrData; + } + } + var datalist = JsonConvert.DeserializeObject>(message); + + if (datalist.ContainsKey("data")) + { + 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 sendTime = dt.AddMilliseconds(Convert.ToDouble(datalist["ts"])).ToLocalTime(); + + // Candle 리스트에 데이터 쌓기 + //var marketCandleList = commonProperty.candleDataLists.Find(i => i.ConGoodsData.MarketName == candleInfo[0]["instId"].ToString()); + + + // 분 업데이트 (1,3,5,10,15,30) + //if(recieveTime.Second == 0) + { + + } + // 시 업데이트 (1,4,6) + //if(recieveTime.Minute == 0) + { + + } + //else + { + + } + + } + // 요청시간 + + // Candle 시간 + + } + } + + catch (Exception ex) + { + Console.WriteLine("WebSocket 연결 중 오류 발생: " + ex.Message); + } + finally + { + if (webSocket.State == WebSocketState.Open) + await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "WebSocket 연결 종료", CancellationToken.None); + + webSocket.Dispose(); + } + } + + private static async Task SendMessage(ClientWebSocket webSocket, string message) + { + byte[] buffer = Encoding.UTF8.GetBytes(message); + await webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); + Console.WriteLine("메시지 전송: " + message); + } + + public static bool ValidateJSON(string s) + { + try + { + JToken.Parse(s); + return true; + } + catch (JsonReaderException) + { + return false; + } + } } } diff --git a/BitgetApi/bin/Debug/BitgetApi.exe b/BitgetApi/bin/Debug/BitgetApi.exe index 35bb770..eee42f1 100644 Binary files a/BitgetApi/bin/Debug/BitgetApi.exe and b/BitgetApi/bin/Debug/BitgetApi.exe differ diff --git a/BitgetApi/bin/Debug/BitgetApi.pdb b/BitgetApi/bin/Debug/BitgetApi.pdb index 58a30b5..1f50ed8 100644 Binary files a/BitgetApi/bin/Debug/BitgetApi.pdb and b/BitgetApi/bin/Debug/BitgetApi.pdb differ diff --git a/BitgetApi/obj/Debug/BitgetApi.csproj.AssemblyReference.cache b/BitgetApi/obj/Debug/BitgetApi.csproj.AssemblyReference.cache index 8441e32..3e3544c 100644 Binary files a/BitgetApi/obj/Debug/BitgetApi.csproj.AssemblyReference.cache and b/BitgetApi/obj/Debug/BitgetApi.csproj.AssemblyReference.cache differ diff --git a/BitgetApi/obj/Debug/BitgetApi.csproj.CoreCompileInputs.cache b/BitgetApi/obj/Debug/BitgetApi.csproj.CoreCompileInputs.cache index b2760d6..b0ab608 100644 --- a/BitgetApi/obj/Debug/BitgetApi.csproj.CoreCompileInputs.cache +++ b/BitgetApi/obj/Debug/BitgetApi.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -d5ff6d03fc217fbfad1931b3790d8220d6d9c91db92e859321096b373c80c2f3 +833b83b3820eb545e830d1cae7325b611c183140918d39f612927cf30ff14acd diff --git a/BitgetApi/obj/Debug/BitgetApi.csproj.FileListAbsolute.txt b/BitgetApi/obj/Debug/BitgetApi.csproj.FileListAbsolute.txt index 5b11a73..d9499e7 100644 --- a/BitgetApi/obj/Debug/BitgetApi.csproj.FileListAbsolute.txt +++ b/BitgetApi/obj/Debug/BitgetApi.csproj.FileListAbsolute.txt @@ -34,3 +34,39 @@ D:\Project\Bitget API\BitgetApi\BitgetApi\obj\Debug\BitgetApi.csproj.CoreCompile D:\Project\Bitget API\BitgetApi\BitgetApi\obj\Debug\BitgetApi.csproj.Up2Date D:\Project\Bitget API\BitgetApi\BitgetApi\obj\Debug\BitgetApi.exe D:\Project\Bitget API\BitgetApi\BitgetApi\obj\Debug\BitgetApi.pdb +D:\Project\BitGet_API\BitgetApi\bin\Debug\BitgetApi.exe.config +D:\Project\BitGet_API\BitgetApi\bin\Debug\BitgetApi.exe +D:\Project\BitGet_API\BitgetApi\bin\Debug\BitgetApi.pdb +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Data.Desktop.v23.2.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Data.v23.2.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Drawing.v23.2.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Printing.v23.2.Core.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Utils.v23.2.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.XtraEditors.v23.2.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.XtraLayout.v23.2.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.XtraTreeList.v23.2.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\Newtonsoft.Json.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Pdf.v23.2.Core.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Pdf.v23.2.Drawing.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Sparkline.v23.2.Core.dll +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Data.Desktop.v23.2.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Data.v23.2.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Drawing.v23.2.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Printing.v23.2.Core.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Utils.v23.2.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.XtraEditors.v23.2.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.XtraLayout.v23.2.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.XtraTreeList.v23.2.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\Newtonsoft.Json.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Pdf.v23.2.Core.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Pdf.v23.2.Drawing.xml +D:\Project\BitGet_API\BitgetApi\bin\Debug\DevExpress.Sparkline.v23.2.Core.xml +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.csproj.AssemblyReference.cache +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.MainForm.resources +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.Properties.Resources.resources +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.csproj.GenerateResource.cache +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.exe.licenses +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.csproj.CoreCompileInputs.cache +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.csproj.Up2Date +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.exe +D:\Project\BitGet_API\BitgetApi\obj\Debug\BitgetApi.pdb diff --git a/BitgetApi/obj/Debug/BitgetApi.csproj.GenerateResource.cache b/BitgetApi/obj/Debug/BitgetApi.csproj.GenerateResource.cache index c175e88..8ca4dd8 100644 Binary files a/BitgetApi/obj/Debug/BitgetApi.csproj.GenerateResource.cache and b/BitgetApi/obj/Debug/BitgetApi.csproj.GenerateResource.cache differ diff --git a/BitgetApi/obj/Debug/BitgetApi.exe b/BitgetApi/obj/Debug/BitgetApi.exe index 35bb770..eee42f1 100644 Binary files a/BitgetApi/obj/Debug/BitgetApi.exe and b/BitgetApi/obj/Debug/BitgetApi.exe differ diff --git a/BitgetApi/obj/Debug/BitgetApi.pdb b/BitgetApi/obj/Debug/BitgetApi.pdb index 58a30b5..1f50ed8 100644 Binary files a/BitgetApi/obj/Debug/BitgetApi.pdb and b/BitgetApi/obj/Debug/BitgetApi.pdb differ diff --git a/BitgetApi/obj/Debug/DesignTimeResolveAssemblyReferences.cache b/BitgetApi/obj/Debug/DesignTimeResolveAssemblyReferences.cache index 172f15d..212ca5a 100644 Binary files a/BitgetApi/obj/Debug/DesignTimeResolveAssemblyReferences.cache and b/BitgetApi/obj/Debug/DesignTimeResolveAssemblyReferences.cache differ diff --git a/BitgetApi/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/BitgetApi/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache index 8831fc7..54cc995 100644 Binary files a/BitgetApi/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache and b/BitgetApi/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/BitgetApi/obj/Debug/bitgetapi.exe.licenses b/BitgetApi/obj/Debug/bitgetapi.exe.licenses index 9016a2e..6c97813 100644 Binary files a/BitgetApi/obj/Debug/bitgetapi.exe.licenses and b/BitgetApi/obj/Debug/bitgetapi.exe.licenses differ