Files
Million/Million/Manager/DataManager.cs
2024-05-28 11:20:42 +09:00

570 lines
23 KiB
C#

using DevExpress.Pdf.Native;
using Million.Data;
using Million.Data.Upbit;
using Million.DbManagement;
using Million.IndicatorConditionSetup;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Humanizer.In;
using static Million.CommonProperty;
namespace Million.Manager
{
/// <summary>
/// 데이터 구성 Manager Class
/// </summary>
public static class DataManager
{
/// <summary>
/// DB에서 데이터 가져오며 Setting 처리 함
/// </summary>
/// <param name="candleTypeList"></param>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <param name="market"></param>
/// <param name="distinctIndicator"></param>
/// <returns></returns>
public static Dictionary<MCandleTimeType, List<CandleData>> GetStandardData(List<IndicatorCoditionSetup> totalIndicator, DateTime startDate,
DateTime endDate, MarketData market, List<IndicatorCoditionSetup> distinctIndicator, bool flag = false, List<MCandleTimeType> candleTypes = null)
{
var candleTypeList = totalIndicator.Select(t => t.MCandleTimeType).ToList();
if (candleTypes != null)
{
candleTypeList = candleTypes;
}
else
{
candleTypeList.Add(CommonProperty.MCandleTimeType.M1);
candleTypeList = candleTypeList.Distinct().ToList();
}
var dic = new Dictionary<CommonProperty.MCandleTimeType, List<CandleData>>();
//계산로직에 필요한 Data setting
foreach (var item in candleTypeList)
{
var candleDataListClass = DbServiceFunctions.GetCandleData(market,
startDate, endDate, item);
var indicatorSetUpList = distinctIndicator.Where(t => t.MCandleTimeType == item).ToList();
foreach (var setup in indicatorSetUpList)
{
setup.excute(candleDataListClass.CandleDataLists_Im);
}
candleDataListClass.CandleDataLists_Im = candleDataListClass.CandleDataLists_Im.OrderBy(t => t.DateTime).ToList();
var list = new List<CandleData>();
if (flag)
{
var parentData = ValidationCheckManager.SplitValidationCandleDataList(candleDataListClass.CandleDataLists_Im, item);
foreach (var parent in parentData)
list.AddRange(parent);
dic[item] = list;
}
else
dic[item] = candleDataListClass.CandleDataLists_Im;
}
return dic;
}
/// <summary>
/// Data Indicator Execute
/// </summary>
/// <param name="dataList"></param>
/// <param name="totalIndicatorList"></param>
/// <param name="coinFullName"></param>
/// <returns></returns>
public static Dictionary<MCandleTimeType, List<CandleData>> GetExecuteData(Dictionary<MCandleTimeType, List<CandleDataList>> dataList, List<IndicatorCoditionSetup> totalIndicatorList, string coinFullName)
{
var dic = new Dictionary<MCandleTimeType, List<CandleData>>();
var distinctIndicator = IndicatorSetupManager.Distinct(totalIndicatorList);
foreach (var key in dataList.Keys)
{
var candleDataList = dataList[key].FirstOrDefault(t => t.ConGoodsData.CoinFullName == coinFullName);
dic[key] = candleDataList.CandleDataLists_Im;
var indicatorSetUpList = distinctIndicator.Where(t => t.MCandleTimeType == key).ToList();
foreach (var setup in indicatorSetUpList)
{
setup.excute(dic[key], true);
//setup.excute(dic[key], true);
}
}
return dic;
}
/// <summary>
/// Data Indicator Execute
/// </summary>
/// <param name="dataList"></param>
/// <param name="totalIndicatorList"></param>
/// <returns></returns>
public static Dictionary<MCandleTimeType, List<CandleData>> GetExecuteData(Dictionary<MCandleTimeType, List<CandleData>> dataList, List<IndicatorCoditionSetup> totalIndicatorList)
{
var distinctIndicator = IndicatorSetupManager.Distinct(totalIndicatorList);
foreach (var key in dataList.Keys)
{
var indicatorSetUpList = distinctIndicator.Where(t => t.MCandleTimeType == key).ToList();
foreach (var setup in indicatorSetUpList)
{
setup.excute(dataList[key], true);
}
}
return dataList;
}
/// <summary>
/// Sub Indicator List String 반환 Function
/// </summary>
/// <param name="totalIndicator"></param>
/// <returns></returns>
public static List<string> GetSubIndicatorStringList(List<IndicatorCoditionSetup> totalIndicator)
{
// 최초와 cross의 조건먼저 계산이 필요함(선처리)
var parentIndicator = totalIndicator.Where(t => t.SubIndicatorSetupType == CommonProperty.SubIndicatorSetupType.최초돌파 ||
t.SubIndicatorSetupType == CommonProperty.SubIndicatorSetupType.크로스 || t.IndicatorType == IndicatorType.조건단순비교).ToList();
var subIndStringiList = new List<string>();
foreach (var item in parentIndicator)
{
var subRegExpression = "";
if (item.IndicatorType == CommonProperty.IndicatorType.조건단순비교)
{
subRegExpression = ((CompareConditionSetup)item).Origin + "," + ((CompareConditionSetup)item).Compare;
}
else if (item.SubIndicatorSetupType == CommonProperty.SubIndicatorSetupType.크로스)
{
subRegExpression = item.CrossSubRegExpression;
}
else
{
subRegExpression = item.FirstOverSubRegExpression;
}
subIndStringiList.AddRange(subRegExpression.Split(',').ToList());
}
subIndStringiList = subIndStringiList.Distinct().ToList();
return subIndStringiList;
}
/// <summary>
/// Get Recently Data
/// </summary>
/// <param name="dic"></param>
/// <param name="timeType"></param>
/// <param name="realTimeFlag"></param>
/// <returns></returns>
public static CandleData GetRecentlyData(Dictionary<MCandleTimeType, List<CandleData>> dic, MCandleTimeType timeType = MCandleTimeType.M1, bool realTimeFlag = false)
{
CandleData returnData = null;
var list = dic[timeType];
var orderList = list.OrderByDescending(t => t.DateTime).ToList();
if (orderList.Count > 0)
{
if (realTimeFlag)
{
var recentlyList = orderList.Where(t => t.RecentlyDataFlag).ToList();
if (recentlyList.Count > 0)
returnData = recentlyList[0];
}
else
{
returnData = orderList[0];
}
}
// Parent Recently Data는 indicator에 따라 달라질수 있으므로 전부다 처리한 후 초기화
foreach (var data in dic)
{
var recentlyList = data.Value.Where(t => t.RecentlyDataFlag).ToList();
foreach (var recentlyItem in recentlyList)
recentlyItem.RecentlyDataFlag = false;
}
return returnData;
}
/// <summary>
/// Get SearchResult Class Data
/// </summary>
/// <param name="buyCandleData"></param>
/// <param name="sellCandleData"></param>
/// <param name="market"></param>
/// <returns></returns>
public static SearchResult GetBuyerSearchResult(CandleData buyCandleData, CandleData sellCandleData, MarketData market, List<CandleData> buyCandleDatas = null)
{
var result = new SearchResult();
var rate = ((sellCandleData.SellValue - buyCandleData.BuyValue) / buyCandleData.BuyValue) * 100;
result.FirstEarningRate = rate;
result.EndDate = sellCandleData.DateTime;
result.CoinFullName = market.CoinFullName;
result.MarketData = market;
result.BuyEarningRate.Add(rate);
result.BuyValueList.Add(buyCandleData.BuyValue);
result.BuyList.ConGoodsData = market;
if (buyCandleDatas != null) result.BuyList.CandleDataLists_Im = buyCandleDatas;
else result.BuyList.CandleDataLists_Im.Add(buyCandleData);
result.StartDate = buyCandleData.DateTime;
result.SellData = sellCandleData;
result.SellValue = sellCandleData.SellValue;
result.TotalEarningRate = rate;
result.WinCount = rate > 0 ? 1 : 0;
result.LoseCount = rate < 0 ? 1 : 0;
result.FirstWinFlag = rate > 0 ? true : false;
result.BuyCount = buyCandleData.BuyCount;
result.SellCount = sellCandleData.BuyCount;
return result;
}
private static CandleData CreateCandleData(CandleData candle, int timeFlagValue, string timeFlag)
{
var firstData = candle;
if (timeFlag == "minute")
{
var minute = firstData.DateTime.Minute / timeFlagValue * timeFlagValue;
return new CandleData()
{
DateTime = new DateTime(firstData.DateTime.Year, firstData.DateTime.Month, firstData.DateTime.Day, firstData.DateTime.Hour, minute, 0),
HighValue = firstData.HighValue,
StartValue = firstData.StartValue,
LowValue = firstData.LowValue,
EndValue = firstData.EndValue,
RecentlyDataFlag = true,
MoneyVolume = firstData.MoneyVolume
};
}
else if (timeFlag == "hour")
{
var tempDateTime = firstData.DateTime;
tempDateTime = tempDateTime.AddHours(((int)CommonProperty.ExchangeTime.UpbitorBithumb * -1));
var hour = tempDateTime.Hour / timeFlagValue * timeFlagValue;
var dateTime = new DateTime(tempDateTime.Year, tempDateTime.Month, tempDateTime.Day, hour, 0, 0);
dateTime = dateTime.AddHours((int)CommonProperty.ExchangeTime.UpbitorBithumb);
return new CandleData()
{
DateTime = dateTime,
HighValue = firstData.HighValue,
StartValue = firstData.StartValue,
LowValue = firstData.LowValue,
RecentlyDataFlag = true,
EndValue = firstData.EndValue,
MoneyVolume = firstData.MoneyVolume
};
}
else //if (timeFlag == "day")
{
//var hour = firstData.DateTime.Day / timeFlagValue * timeFlagValue;
return new CandleData()
{
DateTime = new DateTime(firstData.DateTime.Year, firstData.DateTime.Month, firstData.DateTime.Day, 0, 0, 0),
HighValue = firstData.HighValue,
StartValue = firstData.StartValue,
LowValue = firstData.LowValue,
RecentlyDataFlag = true,
EndValue = firstData.EndValue,
MoneyVolume = firstData.MoneyVolume
};
}
}
/// <summary>
/// CandleList 만들어주는거
/// </summary>
/// <param name="currentCandleList"></param>
/// <param name="mCandleTimeType"></param>
/// <returns></returns>
public static List<CandleData> GetConvertCandleDataList(List<CandleData> currentCandleList, MCandleTimeType mCandleTimeType)
{
var returnData = new List<CandleData>();
var timeFlag = "minute";
var timeFlagValue = 0;
if (mCandleTimeType < MCandleTimeType.H1)
{
timeFlagValue = (int)mCandleTimeType;
}
else if (mCandleTimeType < MCandleTimeType.D1)
{
timeFlag = "hour";
timeFlagValue = ((int)mCandleTimeType) / 60;
}
else if (mCandleTimeType < MCandleTimeType.W1)
{
timeFlag = "day";
timeFlagValue = 1;
}
if (currentCandleList == null || currentCandleList.Count == 0)
return returnData;
foreach (var item in currentCandleList)
{
var recentlyData = returnData.LastOrDefault();
if (recentlyData == null)
{
returnData.Add(CreateCandleData(item, timeFlagValue, timeFlag));
continue;
}
var coverTime = recentlyData.DateTime;
if (timeFlag == "minute")
{
coverTime = coverTime.AddMinutes(timeFlagValue);
}
else if (timeFlag == "hour")
{
coverTime = coverTime.AddHours(timeFlagValue);
}
else if (timeFlag == "day")
{
coverTime = coverTime.AddDays(timeFlagValue);
}
if (!(recentlyData.DateTime < item.DateTime && item.DateTime < coverTime))
{
returnData.Add(CreateCandleData(item, timeFlagValue, timeFlag));
continue;
}
recentlyData.HighValue = recentlyData.HighValue < item.HighValue ? item.HighValue : recentlyData.HighValue;
recentlyData.LowValue = recentlyData.LowValue < item.LowValue ? recentlyData.LowValue : item.LowValue;
recentlyData.EndValue = item.EndValue;
recentlyData.MoneyVolume += item.MoneyVolume;
recentlyData.RecentlyDataFlag = true;
}
return returnData;
}
/// <summary>
/// 최근 데이터 업데이트 하는 로직
/// </summary>
/// <param name="candleData"></param>
/// <param name="recentlyData"></param>
/// <param name="mCandleTimeType"></param>
/// <param name="newFlag"></param>
/// <returns></returns>
public static CandleData GetRecentlyCandleData(CandleData candleData, CandleData recentlyData, MCandleTimeType mCandleTimeType, ref bool newFlag)
{
var timeFlag = "minute";
var timeFlagValue = 0;
if (mCandleTimeType < MCandleTimeType.H1)
{
timeFlagValue = (int)mCandleTimeType;
}
else if (mCandleTimeType < MCandleTimeType.D1)
{
timeFlag = "hour";
timeFlagValue = ((int)mCandleTimeType) / 60;
}
else if (mCandleTimeType < MCandleTimeType.W1)
{
timeFlag = "day";
timeFlagValue = 1;
}
var flag = false;
if (recentlyData != null)
{
if (timeFlag == "minute")
{
if (candleData.DateTime.Minute % timeFlagValue == 0
|| recentlyData.DateTime.AddMinutes((int)mCandleTimeType) < candleData.DateTime)
{
if (recentlyData.DateTime != candleData.DateTime)
flag = true;
}
}
else if (timeFlag == "hour")
{
var hour = candleData.DateTime.Hour;
if (hour == 0) hour += 24;
if ((hour - (int)CommonProperty.ExchangeTime.UpbitorBithumb) % timeFlagValue == 0
|| recentlyData.DateTime.AddHours((int)mCandleTimeType / 60) < candleData.DateTime)
{
if(timeFlagValue == 1)
{
var temp = candleData.DateTime;
temp = temp.AddMinutes(-1 * temp.Minute);
temp = temp.AddSeconds(-1 * temp.Second);
if (temp != recentlyData.DateTime)
flag = true;
}
else
{
if (recentlyData.DateTime != candleData.DateTime)
flag = true;
}
}
}
else if (timeFlag == "day")
{
if (recentlyData.DateTime != candleData.DateTime)
flag = true;
}
}
else flag = true;
//새로 생성
if (flag)
{
newFlag = true;
var candle = new CandleData();
candle.CandleTimeType = (int)mCandleTimeType;
candle.StartValue = candleData.StartValue;
candle.HighValue = candleData.HighValue;
candle.LowValue = candleData.LowValue;
candle.RecentlyDataFlag = true;
candle.EndValue = candleData.EndValue;
candle.MoneyVolume = candleData.MoneyVolume;
if (timeFlag == "minute")
{
var date = recentlyData.DateTime.AddMinutes((int)mCandleTimeType);
if(recentlyData != null)
{
if (recentlyData.DateTime.AddMinutes((int)mCandleTimeType) < candleData.DateTime)
{
var temp = candleData.DateTime.Minute % timeFlagValue;
date = candleData.DateTime.AddMinutes(-1 * temp);
}
}
else
{
var temp = candleData.DateTime.Minute % timeFlagValue;
date = candleData.DateTime.AddMinutes(-1 * temp);
}
date = date.AddSeconds(-1 * date.Second);
candle.DateTime = date;
}
else if (timeFlag == "hour")
{
var date = candleData.DateTime;
if (recentlyData == null)
{
var hour = candleData.DateTime.Hour;
if (hour == 0) hour += 24;
var temp = (hour - (int)CommonProperty.ExchangeTime.UpbitorBithumb) % timeFlagValue;
date = candleData.DateTime.AddHours(-1 * temp);
}
else
{
date = recentlyData.DateTime.AddHours((int)mCandleTimeType / 60);
if (recentlyData.DateTime.AddHours((int)mCandleTimeType / 60) < candleData.DateTime)
{
var hour = candleData.DateTime.Hour;
if (hour == 0) hour += 24;
var temp = (hour - (int)CommonProperty.ExchangeTime.UpbitorBithumb) % timeFlagValue;
date = candleData.DateTime.AddHours(-1 * temp);
}
}
date = date.AddMinutes(-1 * date.Minute);
date = date.AddSeconds(-1 * date.Second);
candle.DateTime = date;
}
else if (timeFlag == "day")
{
var date = recentlyData.DateTime.AddDays(1);
date = date.AddHours(-1 * date.Hour);
date = date.AddMinutes(-1 * date.Minute);
date = date.AddSeconds(-1 * date.Second);
candle.DateTime = date;
}
return candle;
}
//기존 데이터 엎어쓰기
else
{
recentlyData.HighValue = recentlyData.HighValue < candleData.HighValue ? candleData.HighValue : recentlyData.HighValue;
recentlyData.LowValue = recentlyData.LowValue < candleData.LowValue ? recentlyData.LowValue : candleData.LowValue;
recentlyData.EndValue = candleData.EndValue;
recentlyData.RecentlyDataFlag = true;
recentlyData.MoneyVolume += candleData.MoneyVolume;
return recentlyData;
}
}
/// <summary>
/// 실시간 체결 데이터 1분봉 처리
/// </summary>
/// <param name="realtimeConclusions"></param>
/// <returns></returns>
public static List<CandleData> GetOneMinuteCandleDataFromConclusionList(List<RealtimeConclusion> realtimeConclusions)
{
var returnData = new List<CandleData>();
var dateTimeList = realtimeConclusions.Select(t => t.TradeDateTime.Minute).Distinct().ToList();
foreach (var item in dateTimeList)
{
var list = realtimeConclusions.Where(t => t.TradeDateTime.Minute == item).ToList();
if (list.Count > 0)
{
var valueList = list.Select(t => t.trade_price).ToList();
var startValue = list[0].trade_price;
var endValue = list[list.Count - 1].trade_price;
var highValue = valueList.Max();
var lowValue = valueList.Min();
var candle = new CandleData();
candle.DateTime = list[0].TradeDateTime;
candle.DateTime = candle.DateTime.AddSeconds(candle.DateTime.Second * -1);
candle.CandleTimeType = 1;
candle.StartValue = startValue;
candle.HighValue = highValue;
candle.LowValue = lowValue;
candle.RecentlyDataFlag = true;
candle.EndValue = endValue;
candle.MoneyVolume = list.Select(t => t.trade_volume).Sum();
returnData.Add(candle);
}
}
return returnData;
}
/// <summary>
/// Json 검사
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static bool ValidateJSON(string s)
{
try
{
JToken.Parse(s);
return true;
}
catch (JsonReaderException)
{
return false;
}
}
}
}