From fcd338993885fdd7fdc0b64c6d15466fd0b00b69 Mon Sep 17 00:00:00 2001
From: kyh <1329522@naver.com>
Date: Fri, 18 Apr 2025 15:04:49 +0900
Subject: [PATCH] =?UTF-8?q?impulse=20macd=20=EC=B6=94=EA=B0=80(chatgpt=20?=
=?UTF-8?q?=EB=B2=84=EC=A0=84)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
BitgetApi/BitgetApi.csproj | 2 +
BitgetApi/Data/CandleData.cs | 9 +-
.../ImpulseMacdConditionSetup.cs | 134 ++++++++++++++++
.../IndicatorProcess.cs | 147 ++++++++++++------
BitgetApi/IndicatorData/ImpulseMacdData.cs | 16 ++
5 files changed, 257 insertions(+), 51 deletions(-)
create mode 100644 BitgetApi/IndicatorConditionSetup/ImpulseMacdConditionSetup.cs
create mode 100644 BitgetApi/IndicatorData/ImpulseMacdData.cs
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;
+ }
+}