diff --git a/BitgetApi/BitgetApi.csproj b/BitgetApi/BitgetApi.csproj index 1d03ec4..35695d9 100644 --- a/BitgetApi/BitgetApi.csproj +++ b/BitgetApi/BitgetApi.csproj @@ -110,9 +110,11 @@ + + Form diff --git a/BitgetApi/Data/CandleData.cs b/BitgetApi/Data/CandleData.cs index 629078b..474537e 100644 --- a/BitgetApi/Data/CandleData.cs +++ b/BitgetApi/Data/CandleData.cs @@ -1,15 +1,11 @@ -using BitgetAPI; +using BitgetApi.IndicatorData; using BitgetAPI.Data.IndicatorData; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; namespace BitgetAPI.Data { - + public class CandleData { @@ -49,5 +45,6 @@ namespace BitgetAPI.Data public IchimokData IchimokData { get; set; } public Dictionary movingAverageDataList { get; set; } + public Dictionary impulseMacdDataList { get; set; } } } diff --git a/BitgetApi/IndicatorConditionSetup/ImpulseMacdConditionSetup.cs b/BitgetApi/IndicatorConditionSetup/ImpulseMacdConditionSetup.cs new file mode 100644 index 0000000..1a03509 --- /dev/null +++ b/BitgetApi/IndicatorConditionSetup/ImpulseMacdConditionSetup.cs @@ -0,0 +1,134 @@ +using BitgetApi.IndicatorData; +using System; +using System.Collections.Generic; +using System.Linq; + + +namespace BitgetAPI.IndicatorConditionSetup +{ + [Serializable] + public class ImpulseMacdConditionSetup + { + private int lengthMA; + private int lengthSignal; + + private List srcList = new List(); + private List highList = new List(); + private List lowList = new List(); + private List smmaHighList = new List(); + private List smmaLowList = new List(); + private List zlemaList = new List(); + private List mdList = new List(); + private List sbList = new List(); + private List shList = new List(); + + public ImpulseMacdConditionSetup(int lengthMA = 26, int lengthSignal = 12) + { + this.lengthMA = lengthMA; + this.lengthSignal = lengthSignal; + } + + public ImpulseMacdData AddDataPoint(double high, double low, double close, bool flag) + { + double src = (high + low + close) / 3.0; + if (flag) + { + srcList.Add(src); + highList.Add(high); + lowList.Add(low); + } + else + { + srcList[srcList.Count - 1] = src; + } + + double smmaHigh = CalculateSMMA(highList, smmaHighList, lengthMA); + double smmaLow = CalculateSMMA(lowList, smmaLowList, lengthMA); + double zlema = CalculateZLEMA(srcList, zlemaList, lengthMA); + + double md = 0.0; + if (zlema > smmaHigh) + md = zlema - smmaHigh; + else if (zlema < smmaLow) + md = zlema - smmaLow; + + mdList.Add(md); + + if (mdList.Count < lengthSignal) + return null; + + double sb = mdList.Skip(mdList.Count - lengthSignal).Average(); + double sh = md - sb; + + sbList.Add(sb); + shList.Add(sh); + + if (mdList.Count > 100) + { + mdList.RemoveRange(0, 50); + } + if (sbList.Count > 100) + { + sbList.RemoveRange(0, 50); + } + if (shList.Count > 100) + { + shList.RemoveRange(0, 50); + } + + return new ImpulseMacdData() + { + MD = md, + SH = sh, + SB = sb + }; + } + + private double CalculateSMMA(List src, List smmaList, int len) + { + if (src.Count < len) + return src.Last(); + + double smma; + if (smmaList.Count == 0) + { + smma = src.Skip(src.Count - len).Average(); + } + else + { + smma = (smmaList.Last() * (len - 1) + src.Last()) / len; + } + + smmaList.Add(smma); + return smma; + } + + private double CalculateZLEMA(List src, List zlemaList, int length) + { + if (src.Count < length * 2) + return src.Last(); + + var ema1 = CalculateEMA(src, length); + var ema2 = CalculateEMA(ema1, length); + double d = ema1.Last() - ema2.Last(); + double zlema = ema1.Last() + d; + zlemaList.Add(zlema); + return zlema; + } + + private List CalculateEMA(List src, int length) + { + List ema = new List(); + double k = 2.0 / (length + 1); + ema.Add(src.Take(length).Average()); + + for (int i = length; i < src.Count; i++) + { + double value = src[i] * k + ema.Last() * (1 - k); + ema.Add(value); + } + + return ema; + } + } +} \ No newline at end of file diff --git a/BitgetApi/IndicatorConditionSetup/IndicatorProcess.cs b/BitgetApi/IndicatorConditionSetup/IndicatorProcess.cs index e316ca6..fd8ca23 100644 --- a/BitgetApi/IndicatorConditionSetup/IndicatorProcess.cs +++ b/BitgetApi/IndicatorConditionSetup/IndicatorProcess.cs @@ -1,30 +1,16 @@ using BitgetApi.Data; +using BitgetApi.IndicatorData; using BitgetAPI.Data; -using BitgetAPI.IndicatorConditionSetup; using BitgetAPI.WebService; -using DevExpress.Internal.WinApi.Windows.UI.Notifications; -using DevExpress.Utils.DirectXPaint; -using DevExpress.Utils.Filtering.Internal; -using DevExpress.Utils.IoC; -using DevExpress.Xpo.Logger; -using DevExpress.XtraPrinting.Native; using Newtonsoft.Json; using Serilog; -using Serilog.Debugging; using System; using System.Collections.Generic; using System.Collections.Specialized; -using System.ComponentModel; using System.Linq; using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; using static BitgetAPI.CommonProperty; -using static DevExpress.Utils.Drawing.Helpers.NativeMethods; -using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox; - namespace BitgetAPI.IndicatorConditionSetup { public class IndicatorProcess @@ -136,10 +122,10 @@ namespace BitgetAPI.IndicatorConditionSetup public void calProcess() { - + var range = 34; IchimokuConditionSetup ichimokuConditionSetup = new IchimokuConditionSetup(); MovingAverageConditionSetup movingAverageConditionSetup = new MovingAverageConditionSetup(); - + ImpulseMacdConditionSetup impulseMacdConditionSetup = new ImpulseMacdConditionSetup(); signals_LU.Clear(); signals_SD.Clear(); signals_LD.Clear(); @@ -155,10 +141,10 @@ namespace BitgetAPI.IndicatorConditionSetup //var orderValue = new Dictionary(); //orderValue.Add("orderId", orderDic["orderId"]); - //var sellData = FutureOrder("XRPUSDT", FutureMarginMode.isolated, 10, 0, FutureSide.SellShort, OrderType.market, 10, orderDic["orderId"]); - - + //var sellData = FutureOrder("XRPUSDT", FutureMarginMode.isolated, 10, 0, FutureSide.SellShort, OrderType.market, 10, orderDic["orderId"]); + var totalImperseMACDData = new Dictionary>(); + var 전저고점Flag = true; // 추후 공통화 및 소스정리 필요 while (true) { @@ -236,28 +222,35 @@ namespace BitgetAPI.IndicatorConditionSetup var strInterval = Utils.Convertor.GetEnumDescription((Enum)interval); if (!intervalList.Contains(strInterval)) continue; - if (!전저고점.ContainsKey(market + strInterval) || (nowTime.Minute == 0 && nowTime.Hour == 24)) + if (nowTime.Minute == 0 && nowTime.Hour == 24 && 전저고점Flag) { 전저고점.Clear(); - var dic = new Dictionary(); - dic.Add("전고가", 0); - dic.Add("전저가", 0); - dic.Add("전전고가", 0); - dic.Add("전전저가", 0); - dic.Add("전전전저가", 0); - dic.Add("전전전고가", 0); - dic.Add("전전전전저가", 0); - dic.Add("전전전전고가", 0); - dic.Add("tempHighVal", 0); - dic.Add("tempLowVal", 0); - dic.Add("tempHigh2Val", 0); - dic.Add("tempLow2Val", 0); - dic.Add("tempHigh3Val", 0); - dic.Add("tempLow3Val", 0); - dic.Add("tempHigh4Val", 0); - dic.Add("tempLow4Val", 0); - dic.Add("switchLowVal", 0); - dic.Add("switchHighVal", 0); + 전저고점Flag = false; + } + + if (!전저고점.ContainsKey(market + strInterval)) + { + var dic = new Dictionary + { + { "전고가", 0 }, + { "전저가", 0 }, + { "전전고가", 0 }, + { "전전저가", 0 }, + { "전전전저가", 0 }, + { "전전전고가", 0 }, + { "전전전전저가", 0 }, + { "전전전전고가", 0 }, + { "tempHighVal", 0 }, + { "tempLowVal", 0 }, + { "tempHigh2Val", 0 }, + { "tempLow2Val", 0 }, + { "tempHigh3Val", 0 }, + { "tempLow3Val", 0 }, + { "tempHigh4Val", 0 }, + { "tempLow4Val", 0 }, + { "switchLowVal", 0 }, + { "switchHighVal", 0 } + }; 전저고점.Add(market + strInterval, dic); @@ -265,20 +258,27 @@ namespace BitgetAPI.IndicatorConditionSetup var candleDatas_정렬_Temp = candleDatas_Temp.OrderBy(i => i.Argument).ToList(); var candleDatas_Temp_List = new List(); + totalImperseMACDData[market + strInterval] = new Dictionary(); + + for (var i = 0; i < 199; i++) candleDatas_Temp_List.Add(candleDatas_정렬_Temp[i]); for (var i = 199; i < candleDatas_정렬_Temp.Count; i++) { - + var candleData_Main = candleDatas_정렬_Temp[i]; if (candleData_Main == null) continue; - candleDatas_Temp_List.Add(candleData_Main); + if(interval == MCandleTimeType.M30) + totalImperseMACDData[market + strInterval].Add(candleData_Main.Argument, impulseMacdConditionSetup.AddDataPoint(candleData_Main.High, candleData_Main.Low, candleData_Main.Close, true)); + candleDatas_Temp_List.Add(candleData_Main); + ichimokuConditionSetup.calIchimokuData(candleDatas_Temp_List, candleData_Main); movingAverageConditionSetup.Cal_YHK_Downpublic(candleDatas_Temp_List, candleData_Main); + if (i > 210) { var 현재봉4_Temp = candleDatas_Temp_List[i].movingAverageDataList[4].Value; @@ -286,10 +286,23 @@ namespace BitgetAPI.IndicatorConditionSetup var 전전봉4_Temp = candleDatas_Temp_List[i - 2].movingAverageDataList[4].Value; var 전전전봉4_Temp = candleDatas_Temp_List[i - 3].movingAverageDataList[4].Value; - var returnVal = Calculate전고점(market, strInterval, interval, 전봉4_Temp, 전전봉4_Temp, 전전전봉4_Temp, candleDatas_Temp_List[candleDatas_Temp_List.Count - 1]); + var returnVal = Calculate전고점(market, strInterval, interval, 전봉4_Temp, 전전봉4_Temp, 전전전봉4_Temp, candleDatas_Temp_List[candleDatas_Temp_List.Count - 1]); } } } + else { + if(nowTime.Minute > 0 && nowTime.Hour == 24) + 전저고점Flag = true; + } + var keys = totalImperseMACDData[market + strInterval].Keys.OrderBy(t => t).ToList(); + + + if (keys.Count > 500) + { + for (var i = 0; i < 250; i++) + totalImperseMACDData[market + strInterval].Remove(keys[i]); + } + if (!BuyShortStep.ContainsKey(market + strInterval)) { BuyShortStep[market + strInterval] = false; @@ -304,12 +317,16 @@ namespace BitgetAPI.IndicatorConditionSetup var candleDatas = findedMarket.candleDataList[MCandleTimeType.M1]; var candleDatas_정렬 = candleDatas.OrderBy(i => i.Argument).ToList(); + + var calMacdCandleDatas_정렬 = candleDatas.OrderBy(i => i.Argument).ToList(); + var candleData = candleDatas.Find(i => i.Argument == candleDatas_정렬.Last().Argument); if (candleData == null) continue; ichimokuConditionSetup.calIchimokuData(candleDatas_정렬, candleData); movingAverageConditionSetup.Cal_YHK_Downpublic(candleDatas_정렬, candleData); + candleDatas_정렬.RemoveAt(candleDatas_정렬.Count - 1); var candleData_전봉 = candleDatas.Find(i => i.Argument == candleDatas_정렬.Last().Argument); @@ -392,9 +409,23 @@ namespace BitgetAPI.IndicatorConditionSetup if (candleData_30 == null) continue; + ichimokuConditionSetup.calIchimokuData(candleDatas_30_정렬, candleData_30); movingAverageConditionSetup.Cal_YHK_Downpublic(candleDatas_30_정렬, candleData_30); + var macdData = new ImpulseMacdData(); + + if (keys.LastOrDefault() < candleData_30.Argument) + { + macdData = impulseMacdConditionSetup.AddDataPoint(candleData_30.High, candleData_30.Low, candleData_30.Close, true); + totalImperseMACDData[market + "30m"].Add(candleData_30.Argument, macdData); + } + else + { + macdData = impulseMacdConditionSetup.AddDataPoint(candleData_30.High, candleData_30.Low, candleData_30.Close, false); + totalImperseMACDData[market + "30m"][candleData_30.Argument] = macdData; + } + candleDatas_30_정렬.RemoveAt(candleDatas_30_정렬.Count - 1); var candleData_30_전봉 = candleDatas_30.Find(i => i.Argument == candleDatas_30_정렬.Last().Argument); @@ -655,7 +686,22 @@ namespace BitgetAPI.IndicatorConditionSetup var flag_1 = 현재봉4 > 현재봉72 && 전봉4 > 전봉72; - if (flag_30 && flag_5 && flag_1) + //추가 + + // + + var macdFlag = false; + + if ((macdData.SH > 0 && macdData.MD < 0 && macdData.MD < -50) + || (totalImperseMACDData[market + "30m"][keys[keys.Count - 2]].MD == 0 && + totalImperseMACDData[market + "30m"][keys[keys.Count - 3]].MD == 0 && + macdData.MD > 0 && macdData.SH > 0)) + { + macdFlag = true; + } + + + if (flag_30 && flag_5 && flag_1 && macdFlag) { buyFlag = true; } @@ -875,7 +921,18 @@ namespace BitgetAPI.IndicatorConditionSetup var flag_1 = 현재봉4 < 현재봉72 && 전봉4 < 전봉72; - if (flag_30 && flag_5 && flag_1) + var macdFlag = false; + + if ((macdData.SH < 0 && macdData.MD > 0 && macdData.MD > 50) + || (totalImperseMACDData[market + "30m"][keys[keys.Count - 2]].MD == 0 && + totalImperseMACDData[market + "30m"][keys[keys.Count - 3]].MD == 0 && + macdData.MD < 0 && macdData.SH < 0)) + { + macdFlag = true; + } + + + if (flag_30 && flag_5 && flag_1 && macdFlag) { buyFlag = true; } diff --git a/BitgetApi/IndicatorData/ImpulseMacdData.cs b/BitgetApi/IndicatorData/ImpulseMacdData.cs new file mode 100644 index 0000000..c47eeb1 --- /dev/null +++ b/BitgetApi/IndicatorData/ImpulseMacdData.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +namespace BitgetApi.IndicatorData +{ + public class ImpulseMacdData + { + public double MD; + public double SH; + public double SB; + } +}