Compare commits

49 Commits

Author SHA1 Message Date
kyh
9fce4b8636 short수정 2025-09-15 12:51:30 +09:00
kyh
738783473c 수정 2025-08-26 12:49:38 +09:00
kyh
f6b5cdda37 sell price 수정 2025-08-22 15:15:20 +09:00
kyh
424f4fad73 오류 수정 2025-08-18 10:30:27 +09:00
kyh
bb9777f2b1 retouch 코드 수정 2025-08-13 12:49:22 +09:00
kyh
d9ad08d6ad high 조건 추가 2025-08-11 09:56:02 +09:00
kyh
d030c3004c Short 관련 수정 2025-08-08 10:57:12 +09:00
kyh
73c30648d7 재수정 2025-08-06 15:06:38 +09:00
kyh
e02cb70d30 실식가 rate 처리 반영
Short 개선 반영
2025-08-06 10:51:08 +09:00
kyh
29cdaa5156 Sideway Percent로직 추가 2025-07-31 13:36:43 +09:00
kyh
e6e9753b6d 비율로 들어가게 처리 2025-07-25 13:51:05 +09:00
kyh
86aee0b03a 현재꺼로 수정 2025-07-22 12:58:11 +09:00
kyh
3a6423a071 수정 2025-07-07 10:55:01 +09:00
kyh
61ba50e118 url 필요 없어서 뻄 2025-07-03 10:23:05 +09:00
kyh
db2ca84912 판매 시점이 온후로 처리 (pine view와 같이 동작하는거로 보기 위함) 2025-06-26 11:41:34 +09:00
kyh
9f2e5943a7 30분으로 ragne %고침 2025-06-26 11:40:45 +09:00
kyh
240a53aa51 롱 올림 2025-06-26 11:40:32 +09:00
kyh
98c5eb598c chat gpt 이상해서 내가 계산 함 2025-06-19 12:16:35 +09:00
kyh
b2813cc62c 파는 로직에 추가함 2025-06-19 10:48:45 +09:00
kyh
d684edc831 푸시ㅜ푸ㅡ쉬 2025-06-18 15:35:54 +09:00
kyh
044e72664a 전저가 고가 추가해봄 2025-06-17 14:58:00 +09:00
kyh
21440503be SIDE WAY 기준점 변경(높은값 기준이 아닌 낮은값 기준으로 변경) 2025-06-17 13:50:36 +09:00
kyh
122a283cd5 초기화 로직 추가 2025-06-17 11:41:09 +09:00
kyh
00a5860b29 재 수정 2025-06-17 11:33:12 +09:00
kyh
6e05d15571 0.7ㅂ젼경 2025-06-17 11:30:02 +09:00
kyh
52b5fa8015 30분봉 5분봉으로
결과 확인 빠르게 하기 위함

대신 away 거르기 위한 0.7퍼로 변경(12개봉)
2025-06-17 11:28:53 +09:00
kyh
3fe80ee611 데이터 변경 2025-06-17 11:22:43 +09:00
kyh
abf8a4f7f2 수정 2025-06-16 15:05:53 +09:00
kyh
4742970f2d 2.2 로 변경 BTC추가 위해 2025-06-16 13:23:38 +09:00
kyh
9a60569f94 판매조건 수정 2025-06-16 13:23:15 +09:00
kyh
d9aba561cb 삿는데 다음봉 되보니 아닐경우에 대한 예외처리 추가(원본가 오면 팔아버림) 2025-06-16 13:15:49 +09:00
kyh
68548e05f4 isside 관련 오류 수정(자기자신포함하지 않음) 2025-06-11 10:50:50 +09:00
kyh
d32225c46f 구름떼 수정 2025-06-09 12:58:22 +09:00
kyh
ebe11900ee 마지ㅏㄱ 2025-06-09 11:37:10 +09:00
kyh
53ee8f1595 최종 2025-06-09 11:27:53 +09:00
kyh
c2870042f7 wotnwjhd 2025-06-04 10:53:51 +09:00
kyh
0f3e8293de 이상한거 수정 2025-06-04 10:29:49 +09:00
kyh
504cfd8af6 가격으로 사니 늦어서 못삼 현재가로 사도록 수정 2025-05-30 09:43:42 +09:00
kyh
5c797e2b11 구름떼 오류 수정 2025-05-29 13:40:56 +09:00
kyh
b698428681 Short은 구름떼 이후 첫번째만 처리 함(Short은 한번만 가는경우가 많아서) 2025-05-29 11:57:43 +09:00
kyh
d11c703670 test 2025-05-29 11:42:52 +09:00
kyh
07085f88c7 사는 지점과 파는지점이 겹치면 안사는거로 처리 2025-05-28 15:37:09 +09:00
kyh
4a39cf6e70 short수정 2025-05-28 12:51:21 +09:00
kyh
9a90554399 마지막 수정 (코드 간결화) 2025-05-27 14:20:54 +09:00
kyh
ba7b46f86d 재 수정 2025-05-27 13:13:16 +09:00
kyh
a2c307b3d8 buy, sell 정규화 2025-05-27 11:40:01 +09:00
kyh
3be354f879 리플용으로 설정값 지정 2025-05-23 13:17:18 +09:00
kyh
f70aff1a1e 데이터 수정 2025-05-23 12:44:23 +09:00
kyh
b7cf26b8fc 30분봉 제외 모든거 삭제 2025-05-23 11:03:30 +09:00
5 changed files with 673 additions and 714 deletions

View File

@@ -112,6 +112,7 @@
<Compile Include="IndicatorConditionSetup\IchimokuConditionSetup.cs" /> <Compile Include="IndicatorConditionSetup\IchimokuConditionSetup.cs" />
<Compile Include="IndicatorConditionSetup\ImpulseMacdConditionSetup.cs" /> <Compile Include="IndicatorConditionSetup\ImpulseMacdConditionSetup.cs" />
<Compile Include="IndicatorConditionSetup\MovingAverageConditionSetup.cs" /> <Compile Include="IndicatorConditionSetup\MovingAverageConditionSetup.cs" />
<Compile Include="IndicatorConditionSetup\SMABandConditionSetup.cs" />
<Compile Include="IndicatorConditionSetup\TradingViewConditionSetup.cs" /> <Compile Include="IndicatorConditionSetup\TradingViewConditionSetup.cs" />
<Compile Include="IndicatorData\IchimokData.cs" /> <Compile Include="IndicatorData\IchimokData.cs" />
<Compile Include="IndicatorConditionSetup\IndicatorProcess.cs" /> <Compile Include="IndicatorConditionSetup\IndicatorProcess.cs" />

View File

@@ -48,6 +48,15 @@ namespace BitgetAPI
MARGIN_보류 = 2 MARGIN_보류 = 2
} }
// SMA Band Type
public enum SMABandType
{
LongBuy = 0,
LongSell = 1,
ShortBuy = 2,
ShortSell = 3
}
public ExchangePlace selectedChangePlace; public ExchangePlace selectedChangePlace;
public PaymentType selectedPaymentType; public PaymentType selectedPaymentType;
public BitgetProductType selectedBitgetProductType; public BitgetProductType selectedBitgetProductType;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,304 @@
using BitgetAPI.Data;
using BitgetAPI.Data.IndicatorData;
using DevExpress.Utils.Extensions;
using DevExpress.XtraBars.Ribbon.Gallery;
using DevExpress.XtraBars.ViewInfo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;
using static BitgetAPI.CommonProperty;
using static DevExpress.Utils.Diagnostics.GUIResources;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;
namespace BitgetApi.IndicatorConditionSetup
{
public class IchimokuResult
{
public DateTime Time { get; set; }
public double TenkanSen { get; set; } // 전환선
public double KijunSen { get; set; } // 기준선
public double SenkouSpanA { get; set; } // 선행스팬1
public double SenkouSpanB { get; set; } // 선행스팬2
public double ChikouSpan { get; set; } // 후행스팬
}
public class SMABandConditionSetup
{
private readonly int rangeLookback = 12;
private double rangeThresholdLongPercent = 2;
private double rangeThresholdShortPercent = 2;
/// <summary>
/// false 는 구매 전, true는 판매 후
/// </summary>
private bool firstCloudFlag = true;
public bool Calculate(List<CandleData> candles, SMABandType type, bool flag = false)
{
var close = candles.Select(t => t.Close).ToList();
var high = candles.Select(t => t.High).ToList();
var low = candles.Select(t => t.Low).ToList();
var open = candles.Select(t => t.Open).ToList();
if (flag)
{
close.RemoveAt(close.Count - 1);
high.RemoveAt(high.Count - 1);
low.RemoveAt(low.Count - 1);
open.RemoveAt(open.Count - 1);
}
int i = close.Count - 1;
if (close.Count < 100 || high.Count < 100 || low.Count < 100 || open.Count < 100)
return false;
var avgLongList = new List<double>();
var avgShortList = new List<double>();
for (var cntData = high.Count - 120; cntData < high.Count; cntData++)
{
var lowestData = Lowest(low, cntData, 12, 1);
var highData = high[cntData];
avgLongList.Add((highData - lowestData)/lowestData * 100);
}
for (var cntData = high.Count - 12; cntData < high.Count; cntData++)
{
var highestData = Highest(high, cntData, 4, 1);
var lowData = low[cntData];
avgShortList.Add((highestData - lowData) / highestData * 100);
}
rangeThresholdLongPercent = avgLongList.Average();
rangeThresholdShortPercent = avgShortList.Average() * 2.5;
double sma72 = CalculateSMA(close, i);
double prevSma72 = CalculateSMA(close, i - 1);
double sma24 = CalculateSMA(close, i, 24);
double prevSma24 = CalculateSMA(close, i - 1, 24);
// SMA4 관련
double sma4 = CalculateSMA(close, i, 4);
double prevSma4 = CalculateSMA(close, i - 1, 4);
double prev2Sma4 = CalculateSMA(close, i - 2, 4);
double prev3Sma4 = CalculateSMA(close, i - 3, 4);
// 밴드 계산
double sma4High = Highest(close, i, 12, 4);
double sma4Middle = Middle(close, i, 12, 4);
double sma4Low = Lowest(close, i, 12, 4);
double prevSma4High = Highest(close, i - 1, 12, 4);
double prevSma4Middle = Middle(close, i - 1, 12, 4);
double prevSma4Low = Lowest(close, i - 1, 12, 4);
double prev2Sma4High = Highest(close, i - 2, 12, 4);
double prev2Sma4Low = Lowest(close, i - 2, 12, 4);
double prev2Sma4Middle = Middle(close, i - 2, 12, 4);
double prev3Sma4High = Highest(close, i - 3, 12, 4);
double prev3Sma4Low = Lowest(close, i - 3, 12, 4);
double prev3Sma4Middle = Middle(close, i - 3, 12, 4);
var ichmok = GetIchimokuCloud(candles, i - 25);
var ichmokCurrent = GetIchimokuCloud(candles, i);
var cloudTopNow = Math.Max(ichmok.SenkouSpanA, ichmok.SenkouSpanB);
var cloudBottomNow = Math.Min(ichmok.SenkouSpanA, ichmok.SenkouSpanB);
var cloudTopAfter = Math.Max(ichmokCurrent.SenkouSpanA, ichmokCurrent.SenkouSpanB);
var cloudBottomAfter = Math.Min(ichmokCurrent.SenkouSpanA, ichmokCurrent.SenkouSpanB);
bool isSma4BelowCloud = low[i] < cloudBottomNow;
bool isSma4AboveCloud = high[i] > cloudTopNow;
bool greenCandle = open[i] < close[i];
bool redCandle = open[i] > close[i];
var isLongRecentTouch = false;
for (var cnt = 0; cnt < 10; cnt++)
{
if (Lowest(close, i - cnt, 12, 4) == CalculateSMA(close, i - cnt, 4) && Lowest(close, i - cnt - 1, 12, 4) <= CalculateSMA(close, i - cnt - 1, 4))
{
isLongRecentTouch = true;
break;
}
}
//high 데이터 비교(기본 12개)
var highestTempData = Highest(high, i, 12, 1);
// 진입/청산 조건
bool rawNewLong = highestTempData == high[i] && isLongRecentTouch && greenCandle && IsSideways(high, low, i, true, rangeThresholdLongPercent) && prevSma4 <= sma4 && sma4High == sma4 && prevSma4High >= prevSma4 && (prev2Sma4Middle - prevSma4Middle) > (prevSma4Middle - sma4Middle) && sma4Middle > sma72 && sma4 > cloudTopNow;
bool rawLongSell = (sma4Middle < sma72 && prevSma4Middle > prevSma72) || (sma4 == sma4Low);
bool rawNewShort = (sma72 < cloudTopNow && prevSma4Middle > prevSma24 && sma4Middle > cloudBottomNow && sma4 < sma72 && sma4High > sma72 && sma24 > sma4Middle && sma4 == sma4Low && IsSideways(high, low, i, false, rangeThresholdShortPercent) && prevSma4 > sma4 && sma4 < cloudBottomNow) || (sma4 < sma72 && sma4High > sma72 && sma24 < sma4Middle && sma4 == sma4Low && IsSideways(high, low, i, false, rangeThresholdShortPercent) && redCandle && sma4 < cloudBottomNow && sma4Middle < cloudTopNow);
bool rawShortSell = (sma4High <= sma4 && sma4High < sma72) || sma4 > sma72;
//bool rawNewLong = greenCandle && sma4Low < sma72 && IsSideways(high, low, i, true) && sma4 > cloudTopNow && prevSma4 <= prevSma4High && sma4 == sma4High && prevSma4 < sma4 && sma4Middle > sma72 && sma4 > cloudTopNow && ichmok.SenkouSpanA >= ichmok.SenkouSpanB && ichmokCurrent.SenkouSpanA >= ichmokCurrent.SenkouSpanB;
//sma4 == sma4High && prevSma4 < sma4High && sma4Middle > sma72 && sma4 > cloudTopNow && ichmokCurrent.SenkouSpanA > ichmokCurrent.SenkouSpanB && ichmok.SenkouSpanA >= ichmok.SenkouSpanB; // sma4 > cloudBottomNow && IsSideways(high, low, i, true) && isSma4AboveCloud && (sma4 == sma4High && prevSma4 <= prevSma4High && prev2Sma4 <= prev2Sma4High) && (sma4 >= prevSma4 && prevSma4 >= prev2Sma4 && prev2Sma4 >= prev3Sma4);
//bool rawLongSell = (sma4Middle < sma72 && prevSma4Middle > prevSma72) || (sma4 == sma4Low);
//(sma4Middle < sma72 && prevSma4Middle > prevSma72) || (sma4 < cloudBottomNow);// (sma4 <= prevSma4 && prevSma4 <= prev2Sma4 && sma4 < sma4Middle);
//cloudFlag &&
//bool rawNewShort = sma4 == sma4Low && prevSma4 > sma4Low && sma4Middle < sma72 && sma4 < cloudBottomNow;// sma4High < sma72 && prevSma4High > prevSma72;//sma4 < cloudTopNow && IsSideways(high, low, i, false) && isSma4BelowCloud && (sma4 == sma4Low && prevSma4 >= prevSma4Low && prev2Sma4 >= prev2Sma4Low) && (sma4 <= prevSma4 && prevSma4 <= prev2Sma4 && prev2Sma4 <= prev3Sma4);
//bool rawShortSell = (sma4Middle > sma72 && prevSma4Middle < prevSma72) || (sma4 > cloudTopNow);//(sma4 >= prevSma4 && prevSma4 >= prev2Sma4 && sma4 > sma4Middle);
// === 시그널 계산 ===
if (type == SMABandType.LongBuy)
{
return rawNewLong;
}
else if (type == SMABandType.ShortBuy)
{
return rawNewShort;
}
else if (type == SMABandType.LongSell)
{
return rawLongSell;
}
else if (type == SMABandType.ShortSell)
{
//if (rawShortSell)
// firstCloudFlag = true;
return rawShortSell;
}
return false;
}
public static double CalculateSMA(List<double> data, int index, int period = 72)
{
var result = 0.0;
for (var i = 0; i < period; i++)
result += data[index - i];
return result / period;
}
private List<double> GetAvgList(List<double> source, int index, int period, int num)
{
var list = new List<double>();
for (var i = 0; i < period; i++)
{
list.Add(CalculateSMA(source, index - i, num));
}
return list;
}
private double Highest(List<double> source, int index, int period, int num)
{
return GetAvgList(source, index, period, num).Max();
}
private double Middle(List<double> source, int index, int period, int num)
{
return GetAvgList(source, index, period, num).Average();
}
private double Lowest(List<double> source, int index, int period, int num)
{
return GetAvgList(source, index, period, num).Min();
}
private bool IsSideways(List<double> high, List<double> low, int index, bool type, double rangeThresholdPercent)
{
double highestHigh = Highest(high, index, rangeLookback, 1);
double lowestLow = Lowest(low, index, rangeLookback, 1);
// long
if (type)
{
double range = high[index] - lowestLow;
return range > (highestHigh * rangeThresholdPercent / 100.0);
}
//short
else
{
double range = highestHigh - low[index];
return range > (lowestLow * rangeThresholdPercent / 100.0);
}
}
private IchimokuResult GetIchimokuCloud(List<CandleData> candles, int i)
{
var highs = candles.Select(t => t.High).ToList();
var lows = candles.Select(t => t.Low).ToList();
var closes = candles.Select(t => t.Close).ToList();
var result = new IchimokuResult();
double tenkan = 0;
double kijun = 0;
double senkouA = 0;
double senkouB = 0;
double chikou = 0;
// Tenkan-sen (9)
if (i >= 8)
{
double max9 = highs.GetRange(i - 8, 9).Max();
double min9 = lows.GetRange(i - 8, 9).Min();
tenkan = (max9 + min9) / 2.0;
}
// Kijun-sen (26)
if (i >= 25)
{
double max26 = highs.GetRange(i - 25, 26).Max();
double min26 = lows.GetRange(i - 25, 26).Min();
kijun = (max26 + min26) / 2.0;
}
// Senkou Span A (현재 시점에서 계산만, 시프트는 X)
if (tenkan != 0 && kijun != 0)
{
senkouA = (tenkan + kijun) / 2.0;
}
// Senkou Span B (52)
if (i >= 51)
{
double max52 = highs.GetRange(i - 51, 52).Max();
double min52 = lows.GetRange(i - 51, 52).Min();
senkouB = (max52 + min52) / 2.0;
}
return new IchimokuResult
{
TenkanSen = tenkan,
KijunSen = kijun,
SenkouSpanA = senkouA,
SenkouSpanB = senkouB,
ChikouSpan = chikou
};
}
}
}

View File

@@ -118,128 +118,148 @@ namespace BitgetAPI.WebService
using (var wRes = (HttpWebResponse)wReq.GetResponse()) using (var wRes = (HttpWebResponse)wReq.GetResponse())
{ {
var respPostStream = wRes.GetResponseStream(); try
var readerPost = new StreamReader(respPostStream, Encoding.UTF8, true);
var resResult = readerPost.ReadToEnd();
switch (exchangeWebReqType)
{ {
#region Bitget var respPostStream = wRes.GetResponseStream();
case CommonProperty.ExchangeWebReqType.BitgetMarket_Spot: var readerPost = new StreamReader(respPostStream, Encoding.UTF8, true);
{ var resResult = readerPost.ReadToEnd();
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); switch (exchangeWebReqType)
var marketInfo = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(datalist["data"]?.ToString()); {
var data = marketInfo.FindAll(x => x["coin"].ToString().Contains("USDT")); #region Bitget
} case CommonProperty.ExchangeWebReqType.BitgetMarket_Spot:
break;
case CommonProperty.ExchangeWebReqType.BitgetMarket_Future:
{
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
var marketInfos = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(datalist["data"]?.ToString());
commonProperty.marketInfoList = new List<MarketInfo>();
foreach (var item in marketInfos)
{ {
MarketInfo marketInfo = new MarketInfo(); var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
marketInfo.MarketName = item["symbol"].ToString(); var marketInfo = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(datalist["data"]?.ToString());
marketInfo.ExchangePlace = Enum.GetName(typeof(CommonProperty.ExchangePlace), commonProperty.selectedChangePlace); var data = marketInfo.FindAll(x => x["coin"].ToString().Contains("USDT"));
marketInfo.lastPr = Convert.ToDouble(item["lastPr"]);
marketInfo.change24h = Convert.ToDouble(item["change24h"]);
marketInfo.baseVolume = Convert.ToDouble(item["baseVolume"]);
marketInfo.quoteVolume = Convert.ToDouble(item["quoteVolume"]);
marketInfo.high24h = Convert.ToDouble(item["high24h"]);
marketInfo.low24h = Convert.ToDouble(item["low24h"]);
marketInfo.open24h = Convert.ToDouble(item["open24h"]);
commonProperty.marketInfoList.Add(marketInfo);
} }
break;
return commonProperty.marketInfoList; case CommonProperty.ExchangeWebReqType.BitgetMarket_Future:
}
case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Coin:
{
}
break;
case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Future:
{
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
var datas = JsonConvert.DeserializeObject<List<List<object>>>(datalist["data"]?.ToString());
if (marketCandleDataList == null) return null;
var candleDataList = marketCandleDataList.candleDataList[interval];
foreach (var item in datas)
{ {
CandleData candleData = new CandleData(); var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
var marketInfos = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(datalist["data"]?.ToString());
candleData.Argument = Convertor.GetUnixtimeStampToDateTime(long.Parse(item[0].ToString())); commonProperty.marketInfoList = new List<MarketInfo>();
candleData.Open = Convert.ToDouble(item[1]);
candleData.High = Convert.ToDouble(item[2]);
candleData.Low = Convert.ToDouble(item[3]);
candleData.Close = Convert.ToDouble(item[4]);
candleData.Vol_C = Convert.ToDouble(item[5]);
candleData.Vol_USD = Convert.ToDouble(item[6]);
// 같은 시간이 존재하면 업데이트 : 1개밖에 없음 foreach (var item in marketInfos)
// 마지막 시간 데이터는 불완전 > 웹소켓 데이터와 합체
if (item == datas.Last())
{ {
var timespan_add = new System.TimeSpan(0, 0, 0); MarketInfo marketInfo = new MarketInfo();
marketInfo.MarketName = item["symbol"].ToString();
marketInfo.ExchangePlace = Enum.GetName(typeof(CommonProperty.ExchangePlace), commonProperty.selectedChangePlace);
marketInfo.lastPr = Convert.ToDouble(item["lastPr"]);
marketInfo.change24h = Convert.ToDouble(item["change24h"]);
marketInfo.baseVolume = Convert.ToDouble(item["baseVolume"]);
marketInfo.quoteVolume = Convert.ToDouble(item["quoteVolume"]);
marketInfo.high24h = Convert.ToDouble(item["high24h"]);
marketInfo.low24h = Convert.ToDouble(item["low24h"]);
marketInfo.open24h = Convert.ToDouble(item["open24h"]);
commonProperty.marketInfoList.Add(marketInfo);
}
switch (interval) return commonProperty.marketInfoList;
}
case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Coin:
{
}
break;
case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Future:
{
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
var datas = JsonConvert.DeserializeObject<List<List<object>>>(datalist["data"]?.ToString());
if (marketCandleDataList == null) return null;
var candleDataList = marketCandleDataList.candleDataList[interval];
foreach (var item in datas)
{
CandleData candleData = new CandleData();
candleData.Argument = Convertor.GetUnixtimeStampToDateTime(long.Parse(item[0].ToString()));
candleData.Open = Convert.ToDouble(item[1]);
candleData.High = Convert.ToDouble(item[2]);
candleData.Low = Convert.ToDouble(item[3]);
candleData.Close = Convert.ToDouble(item[4]);
candleData.Vol_C = Convert.ToDouble(item[5]);
candleData.Vol_USD = Convert.ToDouble(item[6]);
// 같은 시간이 존재하면 업데이트 : 1개밖에 없음
// 마지막 시간 데이터는 불완전 > 웹소켓 데이터와 합체
if (item == datas.Last())
{ {
case CommonProperty.MCandleTimeType.M1: var timespan_add = new System.TimeSpan(0, 0, 0);
// 같은 분이면 무조건 업데이트
timespan_add = new System.TimeSpan(0, 1, 0); switch (interval)
break; {
case CommonProperty.MCandleTimeType.M3: case CommonProperty.MCandleTimeType.M1:
// 같은 분이면 무조건 업데이트 // 같은 분이면 무조건 업데이트
timespan_add = new System.TimeSpan(0, 3, 0); timespan_add = new System.TimeSpan(0, 1, 0);
break; break;
case CommonProperty.MCandleTimeType.M5: case CommonProperty.MCandleTimeType.M3:
timespan_add = new System.TimeSpan(0, 5, 0); // 같은 분이면 무조건 업데이트
break; timespan_add = new System.TimeSpan(0, 3, 0);
case CommonProperty.MCandleTimeType.M15: break;
timespan_add = new System.TimeSpan(0, 15, 0); case CommonProperty.MCandleTimeType.M5:
break; timespan_add = new System.TimeSpan(0, 5, 0);
case CommonProperty.MCandleTimeType.M30: break;
timespan_add = new System.TimeSpan(0, 30, 0); case CommonProperty.MCandleTimeType.M15:
break; timespan_add = new System.TimeSpan(0, 15, 0);
case CommonProperty.MCandleTimeType.H1: break;
timespan_add = new System.TimeSpan(1, 0, 0); case CommonProperty.MCandleTimeType.M30:
break; timespan_add = new System.TimeSpan(0, 30, 0);
case CommonProperty.MCandleTimeType.H2: break;
timespan_add = new System.TimeSpan(2, 0, 0); case CommonProperty.MCandleTimeType.H1:
break; timespan_add = new System.TimeSpan(1, 0, 0);
case CommonProperty.MCandleTimeType.H3: break;
timespan_add = new System.TimeSpan(3, 0, 0); case CommonProperty.MCandleTimeType.H2:
break; timespan_add = new System.TimeSpan(2, 0, 0);
case CommonProperty.MCandleTimeType.H4: break;
timespan_add = new System.TimeSpan(4, 0, 0); case CommonProperty.MCandleTimeType.H3:
break; timespan_add = new System.TimeSpan(3, 0, 0);
case CommonProperty.MCandleTimeType.H6: break;
timespan_add = new System.TimeSpan(6, 0, 0); case CommonProperty.MCandleTimeType.H4:
break; timespan_add = new System.TimeSpan(4, 0, 0);
case CommonProperty.MCandleTimeType.H12: break;
timespan_add = new System.TimeSpan(12, 0, 0); case CommonProperty.MCandleTimeType.H6:
break; timespan_add = new System.TimeSpan(6, 0, 0);
break;
case CommonProperty.MCandleTimeType.H12:
timespan_add = new System.TimeSpan(12, 0, 0);
break;
}
var sameCandleData_WebService = candleDataList.Find(i => candleData.Argument <= i.Argument &&
i.Argument < (candleData.Argument + timespan_add) && i.WebSocketUpdate == true);
if (sameCandleData_WebService != null)
{
// 종가 => 웹소켓 데이터 사용 (웹 서비스 호출 데이터 중 마지막 데이터는 캔들이 완성되지 않음)
// 시가 => 웹 서비스 데이터 사용
sameCandleData_WebService.Open = candleData.Open;
// 저가, 고가 => 비교해서 사용
sameCandleData_WebService.Low = Math.Min(sameCandleData_WebService.Low, candleData.Low);
sameCandleData_WebService.High = Math.Max(sameCandleData_WebService.High, candleData.High);
sameCandleData_WebService.WebServiceUpdate = true;
}
else
{
candleDataList.Add(candleData);
candleData.WebServiceUpdate = true;
}
} }
/*
//var sameCandleData_WebService = candleDataList.Find(i => i.Argument.Minute == candleData.Argument.Minute &&
//i.Argument.Hour == candleData.Argument.Hour && i.WebSocketUpdate == true);
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)
{ {
// 종가 => 웹소켓 데이터 사용 (웹 서비스 호출 데이터 중 마지막 데이터는 캔들이 완성되지 않음)
// 시가 => 웹 서비스 데이터 사용
sameCandleData_WebService.Open = candleData.Open;
// 저가, 고가 => 비교해서 사용
sameCandleData_WebService.Low = Math.Min(sameCandleData_WebService.Low, candleData.Low);
sameCandleData_WebService.High = Math.Max(sameCandleData_WebService.High, candleData.High);
sameCandleData_WebService.WebServiceUpdate = true; }*/
} // 웹 서비스로 받은 데이터를 새로 추가
else else
{ {
candleDataList.Add(candleData); candleDataList.Add(candleData);
@@ -247,60 +267,46 @@ namespace BitgetAPI.WebService
} }
} }
/*
//var sameCandleData_WebService = candleDataList.Find(i => i.Argument.Minute == candleData.Argument.Minute &&
//i.Argument.Hour == candleData.Argument.Hour && i.WebSocketUpdate == true);
// 기존 웹소켓으로 부터 받은 데이터에 수정 등록
if (sameCandleData_WebService != null)
{
}*/
// 웹 서비스로 받은 데이터를 새로 추가
else
{
candleDataList.Add(candleData);
candleData.WebServiceUpdate = true;
}
} }
} break;
break; case ExchangeWebReqType.BitgetAccountList_Future:
case ExchangeWebReqType.BitgetAccountList_Future: {
{ var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); return JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(datalist["data"]?.ToString());
return JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(datalist["data"]?.ToString()); }
} case ExchangeWebReqType.BitgetOrder_Future:
case ExchangeWebReqType.BitgetOrder_Future: {
{ return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); }
} case ExchangeWebReqType.BitgetCancelOrder_Future:
case ExchangeWebReqType.BitgetCancelOrder_Future: {
{ return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); }
} case ExchangeWebReqType.BitgetChangeLeverage_Future:
case ExchangeWebReqType.BitgetChangeLeverage_Future: {
{ return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); }
} case ExchangeWebReqType.BitgetChangeMarginMode_Future:
case ExchangeWebReqType.BitgetChangeMarginMode_Future: {
{ return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); }
} case ExchangeWebReqType.BitgetChangePositionMode_Future:
case ExchangeWebReqType.BitgetChangePositionMode_Future: {
{ return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); }
} case ExchangeWebReqType.BitgetOrderDetail_Future:
case ExchangeWebReqType.BitgetOrderDetail_Future: {
{ return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); }
} case ExchangeWebReqType.BitgetGetTimeStamp:
case ExchangeWebReqType.BitgetGetTimeStamp: {
{ return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
return JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult); }
} #endregion
#endregion }
}catch(Exception e)
{
return returnJsonData;
} }
} }
} }
@@ -1050,7 +1056,7 @@ namespace BitgetAPI.WebService
candleDataList.Add(candleData); candleDataList.Add(candleData);
// 기존 데이터 삭제 // 기존 데이터 삭제
if (candleDataList.Count > 500) if (candleDataList.Count > 1000)
{ {
// 가장 오래된 데이터 삭제 // 가장 오래된 데이터 삭제
candleDataList.Remove(j => j.Argument == candleDataList.Min(i => i.Argument)); candleDataList.Remove(j => j.Argument == candleDataList.Min(i => i.Argument));
@@ -1107,6 +1113,7 @@ namespace BitgetAPI.WebService
foreach (var min in timeList) foreach (var min in timeList)
{ {
var minDataList = temp.Where(t => t.reciveTime.Minute == min).OrderBy(t => t.reciveTime).ToList(); var minDataList = temp.Where(t => t.reciveTime.Minute == min).OrderBy(t => t.reciveTime).ToList();
var lastData = minDataList[minDataList.Count - 1]; var lastData = minDataList[minDataList.Count - 1];
var candleData = new CandleData(); var candleData = new CandleData();
@@ -1150,7 +1157,7 @@ namespace BitgetAPI.WebService
{ {
var max = candleDataList.Max(t => t.Argument); var max = candleDataList.Max(t => t.Argument);
lastCandleData = candleDataList.Find(t => t.Argument == max); lastCandleData = candleDataList.Find(t => t.Argument == max);
var flag = false; var flag = false;
if (((int)mCandleTimeType) < 60) if (((int)mCandleTimeType) < 60)
{ {
@@ -1238,7 +1245,8 @@ namespace BitgetAPI.WebService
{ {
candleData.WebSocketUpdate = true; candleData.WebSocketUpdate = true;
lastCandleData.Close = candleData.Open; lastCandleData.Close = candleData.Open;
if(lastCandleData.High < lastCandleData.Close)
if (lastCandleData.High < lastCandleData.Close)
{ {
lastCandleData.High = lastCandleData.Close; lastCandleData.High = lastCandleData.Close;
} }
@@ -1253,8 +1261,7 @@ namespace BitgetAPI.WebService
if((int)mCandleTimeType > 60) if((int)mCandleTimeType > 60)
{ {
dt = dt.AddMinutes(dt.Minute * -1); dt = dt.AddMinutes(dt.Minute * -1);
} }
// 새 데이터 등록 // 새 데이터 등록
candleDataList.Add(candleData); candleDataList.Add(candleData);