using DevExpress.XtraEditors; using DevExpress.XtraTreeList; using Million; using Million.IndicatorConditionSetup; using Million.HunterSubForm; using Million.HunterSubForm.IndicatorSetupForm; using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using Million.Data; using Million.DbManagement; using Million.FileDBManagement; using Million.Manager; using Million.SaveData; using Microsoft.CodeAnalysis.CSharp.Scripting; using System.Threading.Tasks; using DevExpress.Data.Helpers; using System.Drawing; using static Million.CommonProperty; using Million.Data.SaveData; using Million_Hunter.HunterSubForm; using System.Threading; namespace Million { public partial class MainForm : Form { // 계산 저정 할/ 계산 저장 된 데이터 Class public SavedResultData _saveResultData; public List multiSavedResultDatas; // 현재 선택된 Indicator 폼 private CommonIndicatorSetupUserForm _curruentIndicatorform; // 현재 수정/삭제 대기중인 클래스의 초기화 private IndicatorCoditionSetup _curIndicatorSetup = null; private int _indexOfList = 0; public MainForm() { InitializeComponent(); InitForm(); } private void InitForm() { InitManager.InitFunc("Upbit", CommonProperty.PaymentType.KRW); // 기간 선택 dateEdit_StartDateTime.DateTime = DateTime.Now; dateEdit_EndDateTime.DateTime = DateTime.Now; // 버튼 태그 값 설정 simpleButton_TobuyList.Tag = "Buy"; simpleButton_ToSellList.Tag = "Sell"; // 지표 ComboBox 초기화 comboBoxEdit_IndicatorSelection.Properties.Items.Clear(); comboBoxEdit_IndicatorSelection.Properties.Items.AddRange(InitManager.GetIndicatorTypeList()); // 저장 할 계산 데이터 클래스 생성 _saveResultData = new SavedResultData(); if(multiSavedResultDatas == null) multiSavedResultDatas = new List(); // 트리리스트 와 클래스 리스트 연결 treeList_BuySetupList.DataSource = _saveResultData.BuySetupList = new List(); treeList_SellSetupList.DataSource = _saveResultData.SellSetupList = new List(); // 지표 새로 추가 시 수정/삭제 버튼 Visible 처리 simpleButton_SetupEdit.Visible = false; simpleButton_SetupDelete.Visible = false; simpleButton_TobuyList.Visible = true; simpleButton_ToSellList.Visible = true; } // 지표 콤보박스 클릭 시 이벤트 private void comboBoxEdit_IndicatorSelection_SelectedIndexChanged(object sender, EventArgs e) { var comboboxEdit = sender as ComboBoxEdit; if (comboboxEdit == null) return; if (comboboxEdit.SelectedIndex < 0) return; Enum.TryParse(comboBoxEdit_IndicatorSelection.SelectedItem.ToString(), out CommonProperty.IndicatorType indicatorType); // 지표 조건 설정 폼 생성하기 CreateIndicatorForm(indicatorType); // 지표 새로 추가 시 수정/삭제 버튼 Hidden 처리 simpleButton_SetupEdit.Visible = false; simpleButton_SetupDelete.Visible = false; simpleButton_TobuyList.Visible = true; simpleButton_ToSellList.Visible = true; // 현재 수정/삭제 대기중인 클래스의 초기화 _curIndicatorSetup = null; } // 지표 조건 설정 폼 생성하기 public void CreateIndicatorForm(CommonProperty.IndicatorType indicatorType, object setupData = null) { // 조건 설정 창 초기화 panelControl_IndicatorSetup.Controls.Clear(); // 공통 Indicator 폼 생성 _curruentIndicatorform = new CommonIndicatorSetupUserForm(indicatorType, setupData); // 패널에 Indicator 폼 추가 if (_curruentIndicatorform != null) panelControl_IndicatorSetup.Controls.Add(_curruentIndicatorform); } // 구매/판매에 추가 버튼 클릭 시 이벤트 처리 private void simpleButton_BuySellButton_Click(object sender, EventArgs e) { var button = sender as SimpleButton; // 예외처리 if (_curruentIndicatorform == null || comboBoxEdit_IndicatorSelection.SelectedItem == null) return; // 선택된 콤보박스로 부터 Indicator type 가져오기 Enum.TryParse(comboBoxEdit_IndicatorSelection.SelectedItem.ToString(), out CommonProperty.IndicatorType indicatorType); // Buy Sell 구분 Enum.TryParse(button.Tag.ToString(), out CommonProperty.BuySellType buySelltype); _curIndicatorSetup = (IndicatorCoditionSetup)_curruentIndicatorform.SaveIndicatorSetup(true); _curIndicatorSetup.ByBuySellType = buySelltype; var totalIndi = new List(); totalIndi.AddRange( _saveResultData.BuySetupList); totalIndi.AddRange(_saveResultData.SellSetupList); var indexStringList = totalIndi.OfType().Select(x=>x.IndexString).ToList(); var num = 0; if(indexStringList.Count != 0) { foreach (var item in indexStringList) { int.TryParse(item, out var compareInt); if (num < compareInt) num = compareInt; } num++; } _curIndicatorSetup.IndexString = num.ToString(); switch (buySelltype) { case CommonProperty.BuySellType.Buy: _saveResultData.BuySetupList.Add(_curIndicatorSetup); treeList_BuySetupList.RefreshDataSource(); break; case CommonProperty.BuySellType.Sell: _saveResultData.SellSetupList.Add(_curIndicatorSetup); treeList_SellSetupList.RefreshDataSource(); break; } // 현재 수정/삭제 대기중인 클래스의 초기화 _curIndicatorSetup = null; } // 구매/판매 트리 리스트 더블 클릭 시 이벤트 처리 private void treeList_BuySetupList_MouseDoubleClick(object sender, MouseEventArgs e) { var treeList = sender as TreeList; if (treeList == null) return; var hitInfo = treeList.CalcHitInfo(e.Location); if (hitInfo.HitInfoType != HitInfoType.Cell) return; var indicatorType = (CommonProperty.IndicatorType)hitInfo.Node["IndicatorType"]; var indicatorSetupClassData = treeList.GetDataRecordByNode(hitInfo.Node); // 현재 수정/삭제 대기중인 클래스 저장 _curIndicatorSetup = (IndicatorCoditionSetup)indicatorSetupClassData; _indexOfList = treeList.Nodes.IndexOf(hitInfo.Node); // 지표 조건 설정 폼 생성하기 CreateIndicatorForm(indicatorType, indicatorSetupClassData); // 지표 새로 추가 시 수정/삭제 버튼 Visible 처리 simpleButton_SetupEdit.Visible = true; simpleButton_SetupDelete.Visible = true; simpleButton_TobuyList.Visible = false; simpleButton_ToSellList.Visible = false; // 조건 설정 창 초기화 comboBoxEdit_IndicatorSelection.Text = ""; } // 조건 수정 버튼 클릭 private void simpleButton_SetupEdit_Click(object sender, EventArgs e) { if (_curIndicatorSetup == null) return; var type = _curIndicatorSetup.GetType(); _curruentIndicatorform.SaveIndicatorSetup(); // 해당 List안에 있는 Class를 수정 if (_saveResultData.BuySetupList.Contains(_curIndicatorSetup)) treeList_BuySetupList.RefreshDataSource(); else treeList_SellSetupList.RefreshDataSource(); } // 조건 삭제 버튼 클릭 private void simpleButton_SetupDelete_Click(object sender, EventArgs e) { if (_curIndicatorSetup == null) return; // 해당 List안에 있는 Class를 삭제 if (_curIndicatorSetup.ByBuySellType == CommonProperty.BuySellType.Buy) { _saveResultData.BuySetupList.RemoveAt(_indexOfList); treeList_BuySetupList.RefreshDataSource(); } else { _saveResultData.SellSetupList.RemoveAt(_indexOfList); treeList_SellSetupList.RefreshDataSource(); } // 조건 설정 창 초기화 _curruentIndicatorform = null; panelControl_IndicatorSetup.Controls.Clear(); comboBoxEdit_IndicatorSelection.Text = ""; // 지표 새로 추가 시 수정/삭제 버튼 Visible 처리 simpleButton_SetupEdit.Visible = false; simpleButton_SetupDelete.Visible = false; simpleButton_TobuyList.Visible = true; simpleButton_ToSellList.Visible = true; } //지표 Refresh private void simpleButton_SetupRefresh_Click(object sender, EventArgs e) { // 선택된 지표가 있는 경우, 해당 지표를 새로 생성함 if (comboBoxEdit_IndicatorSelection.SelectedIndex <= 0) return; Enum.TryParse(comboBoxEdit_IndicatorSelection.SelectedItem.ToString(), out CommonProperty.IndicatorType indicatorType); // 지표 조건 설정 폼 생성하기 CreateIndicatorForm(indicatorType); // 지표 새로 추가 시 수정/삭제 버튼 Hidden 처리 simpleButton_SetupEdit.Visible = false; simpleButton_SetupDelete.Visible = false; simpleButton_TobuyList.Visible = true; simpleButton_ToSellList.Visible = true; // 현재 수정/삭제 대기중인 클래스의 초기화 _curIndicatorSetup = null; } // 계산하기 버튼 클릭 시 이벤트 처리 // 조건 검색을 반영하여 데이터 계산 private void simpleButton_CalcurateData_Click(object sender, EventArgs e) { CommonProperty.StarValueLowBuyValueUp = cb_StarValueLowOverlapUp.Checked; // 계산 결과 데이터 관련 클래스에 값 채우기 DeafultDataSet(); CommonProperty.InsertLogFlag = false; CalculateDatas(_saveResultData, cb_UpperMainIndi.Checked, cb_IncludeClearIndicator.Checked, cb_DownBeforeValueFlag.Checked, rd_Hunter.Checked); // 3. 자동으로 저장하기 if (DBConnection.QueryInsertExecuter_SavedResultData(_saveResultData)) { MessageBox.Show("데이터 저장 성공"); } else { MessageBox.Show("데이터 저장 실패"); } // 데이터가 있는 경우 버튼 색 변경 if (_saveResultData.SearchResultList != null) { simpleButton_ViewResultData.Appearance.BackColor = Color.FromArgb(128, 128, 255); } } /// /// Saved Result Data에 Data Setting /// private void DeafultDataSet() { _saveResultData.StartDateTime = dateEdit_StartDateTime.DateTime; _saveResultData.EndDateTime = dateEdit_EndDateTime.DateTime; _saveResultData.SavedDateTime = DateTime.Now; _saveResultData.SearchResultList = new List(); _saveResultData.BuyRegularExpression = textEdit_BuyRegularExpression.Text; _saveResultData.SellRegularExpression = textEdit_SellRegularExpression.Text; _saveResultData.SellExceptionRegularExpression = textEdit_SellExceptionRegularExpression.Text; } /// /// 실행 함수 /// /// private void CalculateDatas(SavedResultData savedResult, bool upperMainIndicatorFlag, bool includeClearIndicator, bool downBeforeValueFlag, bool hunterMode) { // 예외 처리 var buyIndicatorList = IndicatorSetupManager.InitDataSetup(savedResult.BuySetupList); var sellIndicatorList = IndicatorSetupManager.InitDataSetup(savedResult.SellSetupList); var totalIndicator = new List(); totalIndicator.AddRange(buyIndicatorList); totalIndicator.AddRange(sellIndicatorList); var tableList = CommonProperty.selectedMarketOfPlaceList; var totalResultList = new List(); var startDate = savedResult.StartDateTime; var endDate = savedResult.EndDateTime; Dictionary overlapBuyManagementList = null; if (!hunterMode) { CommonProperty.RealtimeHunterMode = true; overlapBuyManagementList = new Dictionary(); } InitManager.SettingInit(includeClearIndicator, overlapBuyManagementList, totalIndicator); CommonProperty.UpperMainIndicatorFlag = upperMainIndicatorFlag; CommonProperty.DownBeforeValueFlag = downBeforeValueFlag; var buyScript = new InteratorScripter("Buy Script"); buyScript.regularExpressionString = savedResult.BuyRegularExpression; var sellScript = new InteratorScripter("Sell Script"); sellScript.regularExpressionString = savedResult.SellRegularExpression; var sellExceptionScript = new InteratorScripter("Sell Exception Script"); sellExceptionScript.regularExpressionString = savedResult.SellExceptionRegularExpression; var dic = new Dictionary>(); Parallel.For(0, tableList.Count, i => { // for (var i = 0; i < tableList.Count; i++) //{ var market = tableList[i]; var distinctIndicator = IndicatorSetupManager.Distinct(totalIndicator); if (hunterMode) { var list = CalculateHunter(totalIndicator, startDate, endDate, market, distinctIndicator, buyScript, sellScript); dic[market.CoinFullName] = list; } else { var list = CalculateHunterRealtime(totalIndicator, startDate, endDate, market, distinctIndicator, overlapBuyManagementList, buyScript, sellScript, sellExceptionScript); dic[market.CoinFullName] = list; } //} }); foreach (var item in dic.Keys) { if (dic.ContainsKey(item)) totalResultList.AddRange(dic[item]); } //수익 률 계산 로직 -> 이거는 추후 빼도 될듯 double totalVal = 0; double win = 0; double lose = 0; double firstProfitRate = 0; double firstWin = 0; //승률, 수익률 계산 foreach (var item in totalResultList) { if (item.FirstWinFlag) firstWin++; firstProfitRate += item.FirstEarningRate; win += item.WinCount; lose += item.LoseCount; totalVal += item.TotalEarningRate; } var winRate = 0.0; if (win == 0) { winRate = 0; } else if (lose == 0) { winRate = 100; } else { winRate = (win * 100 / (win + lose)); } double tt = 0; double t1 = 0; foreach (var item in totalResultList) { var buy = item.BuyList.CandleDataLists_Im[0]; var sell = item.SellData; tt += ((sell.SellValue - buy.BuyValue) / buy.BuyValue) * 100; if (buy.BuyValue < sell.SellValue) t1++; } //savedResult.EndDateTime = DateTime.Now; savedResult.SavedDateTime = DateTime.Now; tt /= totalResultList.Count; savedResult.ResultDataCount = totalResultList.Count; savedResult.FirstWinRate = (firstWin * 100) / totalResultList.Count; savedResult.FirstProfitRate = firstProfitRate; savedResult.WinRate = winRate; savedResult.ProfitRate = totalVal / totalResultList.Count; savedResult.SearchResultList = totalResultList; if(string.IsNullOrEmpty(savedResult.Name)) savedResult.Name = savedResult.SavedDateTime.ToString("yyyy-MM-dd HH:mm:ss") + (hunterMode ? "Hunter" : "Hunter Realtime"); savedResult.Type = "Data"; savedResult.SaveResultType = (hunterMode ? "Hunter" : "Hunter Realtime"); savedResult.ExchangePlace = "Upbit"; } /// /// Hunter Realtime Mode /// /// /// /// /// /// /// /// private List CalculateHunterRealtime(List totalIndicator, DateTime startDate, DateTime endDate, MarketData market, List distinctIndicator, Dictionary overlapBuyManagementList, InteratorScripter buyScript, InteratorScripter sellScript, InteratorScripter sellExceptionScript) { var totalCandleTypeList = totalIndicator.Select(t => t.MCandleTimeType).ToList(); var maxCandleType = totalCandleTypeList.Max(); var list = totalCandleTypeList.Where(t => t < MCandleTimeType.H1).ToList(); var minMaxCandleType = MCandleTimeType.M1; if (!(list == null || list.Count == 0)) minMaxCandleType = list.Max(); var buyList = new List(); var subBuyList = new List(); var item = market.CoinFullName; var subIndStringiList = DataManager.GetSubIndicatorStringList(totalIndicator); var resultData = new List(); var startMiniuteDate = startDate.AddMinutes((int)minMaxCandleType * -80); var mCandleTypeList = new List(); mCandleTypeList.Add(CommonProperty.MCandleTimeType.M1); var standardData = DataManager.GetStandardData(totalIndicator, startMiniuteDate, startDate, market, distinctIndicator, true, mCandleTypeList); totalCandleTypeList.AddRange(mCandleTypeList); if (maxCandleType >= MCandleTimeType.H1) { var startHourDate = startDate.AddHours((int)maxCandleType / 60 * -80); var hCandleTypeList = new List(); hCandleTypeList.Add(CommonProperty.MCandleTimeType.H1); var hStandardData = DataManager.GetStandardData(totalIndicator, startHourDate, startDate, market, distinctIndicator, true, hCandleTypeList); standardData.Add(CommonProperty.MCandleTimeType.H1, hStandardData[CommonProperty.MCandleTimeType.H1]); totalCandleTypeList.AddRange(hCandleTypeList); } totalCandleTypeList = totalCandleTypeList.Distinct().ToList(); foreach(var candleTimeType in totalCandleTypeList) { if (standardData.ContainsKey(candleTimeType)) continue; var candleDataList = standardData[MCandleTimeType.M1]; if (candleTimeType >= MCandleTimeType.H1) candleDataList = standardData[MCandleTimeType.H1]; if (candleTimeType == MCandleTimeType.M1 || candleTimeType == MCandleTimeType.H1) continue; standardData[candleTimeType] = DataManager.GetConvertCandleDataList(candleDataList, candleTimeType); } //속도 및 메모리 부하를 줄이기 위한 로직 추가 //db 전체 데이터 불러오는 로직 -> 1분봉 데이터 하나도 안빠져있다는 가정 #region 개선 후 var standardStartDate = startDate; var standardEndDate = startDate.AddDays(7); if (endDate <= standardEndDate) { standardEndDate = endDate; } var mDataList = DbServiceFunctions.GetCandleData(market, standardStartDate, standardEndDate); var breakFlag = true; var count = 0; while (true) { if (mDataList.CandleDataLists_Im.Count == 0) break; if(mDataList.CandleDataLists_Im.Count < 10) { if (breakFlag) { standardStartDate = standardEndDate; standardEndDate = standardEndDate.AddDays(7); if (standardEndDate >= endDate) { breakFlag = false; standardEndDate = endDate; } var tempMDataList = DbServiceFunctions.GetCandleData(market, standardStartDate, standardEndDate); mDataList.CandleDataLists_Im.AddRange(tempMDataList.CandleDataLists_Im); } } var minData = mDataList.CandleDataLists_Im[0]; var compareMin = standardData[CommonProperty.MCandleTimeType.M1].LastOrDefault(); if (compareMin == null || compareMin.DateTime == minData.DateTime || compareMin.DateTime > minData.DateTime) { mDataList.CandleDataLists_Im.RemoveAt(0); continue; } //remove foreach (var key in standardData.Keys) { if (standardData[key].Count > 150) standardData[key].RemoveAt(0); } //1분씩 증가하면서 나머지 처리 minData.RecentlyDataFlag = true; standardData[CommonProperty.MCandleTimeType.M1].Add(minData); foreach (var key in standardData.Keys) { var compareData = standardData[key].LastOrDefault(); var newFlag = false; var candleData = DataManager.GetRecentlyCandleData(minData, compareData, key, ref newFlag); if (newFlag) standardData[key].Add(candleData); } standardData = DataManager.GetExecuteData(standardData, totalIndicator); var minDateTime = standardData[CommonProperty.MCandleTimeType.M1].Select(t => t.DateTime).Min(); var maxDateTime = standardData[CommonProperty.MCandleTimeType.M1].Select(t => t.DateTime).Max().AddHours(1); var buyDataList = buyList.FirstOrDefault(t => t.ConGoodsData.CoinFullName == market.CoinFullName); if (buyDataList != null && buyDataList.CandleDataLists_Im.Count > 0) { standardData = IndicatorSetupManager.CalculateIndicator(standardData, totalIndicator, minDateTime, maxDateTime, item, true, buyDataList.CandleDataLists_Im[0]); } else { standardData = IndicatorSetupManager.CalculateIndicator(standardData, totalIndicator, minDateTime, maxDateTime, item, true); } var recentlyData = DataManager.GetRecentlyData(standardData, MCandleTimeType.M1, true); if (recentlyData == null) { mDataList.CandleDataLists_Im.RemoveAt(0); continue; } //before 데이터 가져오는 함수 -> 사는 케이스만 var beforeData = standardData[maxCandleType].LastOrDefault(); if (!buyList.Any(t => t.ConGoodsData.CoinFullName == item)) { var flag = buyScript.DicExcuteScript(recentlyData.CalculateFlag); if (flag) { //var buyData = new CandleDataList(); //buyData.CandleDataLists_Im.Add(recentlyData); //var valDic = ResultLogicManager.GetIndicateValue(recentlyData.CalculateFlag, totalIndicator, recentlyData); //recentlyData.BuyValue = OrderbookManager.GetAskPrice(CalculateManager.GetConditionValue(buyScript.regularExpressionString, valDic, recentlyData.CalculateFlag)); //recentlyData.BuyTime = recentlyData.DateTime; //buyData.ConGoodsData = CommonProperty.selectedMarketOfPlaceList.FirstOrDefault(t => t.CoinFullName == item); //recentlyData.BuyCount = 1; //buyList.Add(buyData); if (overlapBuyManagementList[item]) { var buyData = new CandleDataList(); buyData.CandleDataLists_Im.Add(recentlyData); var valDic = ResultLogicManager.GetIndicateValue(recentlyData.CalculateFlag, totalIndicator, recentlyData); recentlyData.BuyValue = OrderbookManager.GetAskPrice(CalculateManager.GetConditionValue(buyScript.regularExpressionString, valDic, recentlyData.CalculateFlag)); // 이전 전봉(H1)의 고가가 사려는 가격보다 높을경우 pass if (StarValueLowBuyValueUp) { //if (recentlyData.StartValue < beforeData.HighValue) //{ // foreach (var indi in totalIndicator) // subIndicatorStateManagement[indi.IndexString][item] = false; // overlapBuyManagementList[item] = true; // continue; //} if (recentlyData.BuyValue < beforeData.HighValue) { foreach (var indi in totalIndicator) subIndicatorStateManagement[indi.IndexString][item] = false; overlapBuyManagementList[item] = true; continue; } } recentlyData.BuyTime = recentlyData.DateTime; buyData.ConGoodsData = CommonProperty.selectedMarketOfPlaceList.FirstOrDefault(t => t.CoinFullName == item); recentlyData.BuyCount = 1; buyList.Add(buyData); subBuyList.Add(buyData); overlapBuyManagementList[item] = false; count++; } } else { overlapBuyManagementList[item] = true; } } //Hunter의 경우 1분안에 사고 팔고가 다 끝날수도 있음 그러므로 처리해야함 if (buyList.Any(t => t.ConGoodsData.CoinFullName == item)) { //buy count 수 var flagData = buyScript.DicExcuteScript(recentlyData.CalculateFlag); if (flagData) { var buyItem = buyList.FirstOrDefault(x => x.ConGoodsData.CoinFullName == item); //buyItem.CandleDataLists_Im.Add(recentlyData); count++; } var flag = false; var scriptStr = sellScript.regularExpressionString; if (sellExceptionScript.regularExpressionString != null && sellExceptionScript.regularExpressionString.Length > 0) { //예외처리 로직 추가 flag = sellExceptionScript.DicExcuteScript(recentlyData.CalculateFlag); if (flag) scriptStr = sellExceptionScript.regularExpressionString; } if (!flag) { //default sell flag = sellScript.DicExcuteScript(recentlyData.CalculateFlag); scriptStr = sellScript.regularExpressionString; } if (flag) { var buyItem = buyList.FirstOrDefault(x => x.ConGoodsData.CoinFullName == item); var sellItem = recentlyData; var valDic = ResultLogicManager.GetIndicateValue(sellItem.CalculateFlag, totalIndicator, sellItem); sellItem.SellValue = OrderbookManager.GetAskPrice(CalculateManager.GetConditionValue(scriptStr, valDic, sellItem.CalculateFlag), false); var sellVal = sellItem.SellValue; sellItem.SellTime = recentlyData.DateTime; var buyCandleData = buyItem.CandleDataLists_Im[0]; var result = DataManager.GetBuyerSearchResult(buyCandleData, recentlyData, buyItem.ConGoodsData, buyItem.CandleDataLists_Im); result.BuyCount = count; resultData.Add(result); //초기화 작업 foreach (var sublIndi in subIndStringiList) { CommonProperty.subIndicatorStateManagement[sublIndi][item] = false; } //처리한 buyList는 삭제 buyList.Remove(buyItem); count = 0; } } mDataList.CandleDataLists_Im.RemoveAt(0); } #endregion #region 개선 전 /* var mTotalDataList = DbServiceFunctions.GetCandleData(market, startDate, endDate); lastData = mTotalDataList.CandleDataLists_Im.LastOrDefault(); foreach (var minData in mTotalDataList.CandleDataLists_Im) { var compareMin = standardData[CommonProperty.MCandleTimeType.M1].LastOrDefault(); if (compareMin == null || compareMin.DateTime == minData.DateTime || compareMin.DateTime > minData.DateTime) continue; //remove if (standardData[CommonProperty.MCandleTimeType.M1].Count > 250) standardData[CommonProperty.MCandleTimeType.M1].RemoveAt(0); if (standardData[CommonProperty.MCandleTimeType.H1].Count > 250) standardData[CommonProperty.MCandleTimeType.H1].RemoveAt(0); //1분씩 증가하면서 1h 처리 minData.RecentlyDataFlag = true; standardData[CommonProperty.MCandleTimeType.M1].Add(minData); var compareHour = standardData[CommonProperty.MCandleTimeType.H1].LastOrDefault(); if (compareHour.DateTime.Hour != minData.DateTime.Hour) { var candle = new CandleData(); candle.CandleTimeType = (int)MCandleTimeType.H1; candle.StartValue = minData.StartValue; candle.HighValue = minData.HighValue; candle.LowValue = minData.LowValue; candle.RecentlyDataFlag = true; candle.EndValue = minData.EndValue; var date = compareHour.DateTime.AddHours(1); date = date.AddMinutes(-1 * date.Minute); date = date.AddSeconds(-1 * date.Second); candle.DateTime = date; standardData[CommonProperty.MCandleTimeType.H1].Add(candle); } else { compareHour.HighValue = compareHour.HighValue < minData.HighValue ? minData.HighValue : compareHour.HighValue; compareHour.LowValue = compareHour.LowValue < minData.LowValue ? compareHour.LowValue : minData.LowValue; compareHour.EndValue = minData.EndValue; compareHour.RecentlyDataFlag = true; } standardData = DataManager.GetExecuteData(standardData, totalIndicator); var minDateTime = standardData[CommonProperty.MCandleTimeType.M1].Select(t => t.DateTime).Min(); var maxDateTime = standardData[CommonProperty.MCandleTimeType.M1].Select(t => t.DateTime).Max().AddHours(1); var buyDataList = buyList.FirstOrDefault(t => t.ConGoodsData.CoinFullName == market.CoinFullName); if (buyDataList != null && buyDataList.CandleDataLists_Im.Count > 0) { standardData = IndicatorSetupManager.CalculateIndicator(standardData, totalIndicator, minDateTime, maxDateTime, item, true, buyDataList.CandleDataLists_Im[0]); } else { standardData = IndicatorSetupManager.CalculateIndicator(standardData, totalIndicator, minDateTime, maxDateTime, item, true); } var recentlyData = DataManager.GetRecentlyData(standardData, MCandleTimeType.M1, true); if (recentlyData == null) continue; if (!buyList.Any(t => t.ConGoodsData.CoinFullName == item)) { var flag = buyScript.DicExcuteScript(recentlyData.CalculateFlag); if (flag) { //var buyData = new CandleDataList(); //buyData.CandleDataLists_Im.Add(recentlyData); //var valDic = ResultLogicManager.GetIndicateValue(recentlyData.CalculateFlag, totalIndicator, recentlyData); //recentlyData.BuyValue = OrderbookManager.GetAskPrice(CalculateManager.GetConditionValue(buyScript.regularExpressionString, valDic, recentlyData.CalculateFlag)); //recentlyData.BuyTime = recentlyData.DateTime; //buyData.ConGoodsData = CommonProperty.selectedMarketOfPlaceList.FirstOrDefault(t => t.CoinFullName == item); //recentlyData.BuyCount = 1; //buyList.Add(buyData); if (overlapBuyManagementList[item]) { var buyData = new CandleDataList(); buyData.CandleDataLists_Im.Add(recentlyData); var valDic = ResultLogicManager.GetIndicateValue(recentlyData.CalculateFlag, totalIndicator, recentlyData); recentlyData.BuyValue = OrderbookManager.GetAskPrice(CalculateManager.GetConditionValue(buyScript.regularExpressionString, valDic, recentlyData.CalculateFlag)); recentlyData.BuyTime = recentlyData.DateTime; buyData.ConGoodsData = CommonProperty.selectedMarketOfPlaceList.FirstOrDefault(t => t.CoinFullName == item); recentlyData.BuyCount = 1; buyList.Add(buyData); overlapBuyManagementList[item] = false; } } else { overlapBuyManagementList[item] = true; } } //Hunter의 경우 1분안에 사고 팔고가 다 끝날수도 있음 그러므로 처리해야함 if (buyList.Any(t => t.ConGoodsData.CoinFullName == item)) { var flag = false; var scriptStr = sellScript.regularExpressionString; if (sellExceptionScript.regularExpressionString != null && sellExceptionScript.regularExpressionString.Length > 0) { //예외처리 로직 추가 flag = sellExceptionScript.DicExcuteScript(recentlyData.CalculateFlag); if (flag) scriptStr = sellExceptionScript.regularExpressionString; } if (!flag) { //default sell flag = sellScript.DicExcuteScript(recentlyData.CalculateFlag); scriptStr = sellScript.regularExpressionString; } if (flag) { var buyItem = buyList.FirstOrDefault(x => x.ConGoodsData.CoinFullName == item); var sellItem = recentlyData; var valDic = ResultLogicManager.GetIndicateValue(sellItem.CalculateFlag, totalIndicator, sellItem); sellItem.SellValue = OrderbookManager.GetAskPrice(CalculateManager.GetConditionValue(scriptStr, valDic, sellItem.CalculateFlag), false); var sellVal = sellItem.SellValue; sellItem.SellTime = recentlyData.DateTime; var buyCandleData = buyItem.CandleDataLists_Im[0]; var result = DataManager.GetBuyerSearchResult(buyCandleData, recentlyData, buyItem.ConGoodsData); resultData.Add(result); //초기화 작업 foreach (var sublIndi in subIndStringiList) { CommonProperty.subIndicatorStateManagement[sublIndi][item] = false; } //처리한 buyList는 삭제 buyList.Remove(buyItem); } } } */ #endregion if (buyList.Count > 0) { var lastData = standardData[MCandleTimeType.M1].LastOrDefault(); foreach(var buy in buyList) { lastData.SellValue = lastData.EndValue; lastData.SellTime = new DateTime(2000, 1, 1); var result = DataManager.GetBuyerSearchResult(buy.CandleDataLists_Im[0], lastData, buy.ConGoodsData); resultData.Add(result); } } return resultData; } /// /// Hunter 처리 로직 /// private List CalculateHunter(List totalIndicator, DateTime startDate, DateTime endDate, MarketData market, List distinctIndicator, InteratorScripter buyScript, InteratorScripter sellScript) { // 총 데이터 var dic = DataManager.GetStandardData(totalIndicator, startDate, endDate, market, distinctIndicator, true); // buy, sell 계산 var lossIndicator = new List(); // 1분봉 데이터 Setting var resultCandleDataList = dic[CommonProperty.MCandleTimeType.M1]; resultCandleDataList = resultCandleDataList.Where(t => startDate <= t.DateTime && t.DateTime < endDate).ToList(); var subIndStringiList = DataManager.GetSubIndicatorStringList(totalIndicator); // Sub Indicator Class var subIndicator = totalIndicator.Where(t => subIndStringiList.Any(u => u == t.IndexString)).ToList(); // 선처리 CalculateManager.GetCalculateIndicator(totalIndicator, subIndStringiList, lossIndicator, startDate, endDate, resultCandleDataList, subIndicator, dic, rd_RealtimeHunter.Checked); var totalIndi = totalIndicator.Select(t => t.IndexString).ToList(); // 중복계산 방지 foreach (var sub in subIndStringiList) totalIndi.Remove(sub); // 후처리 CalculateManager.GetCalculateIndicator(totalIndicator, totalIndi, lossIndicator, startDate, endDate, resultCandleDataList, subIndicator, dic, rd_RealtimeHunter.Checked); // 계산 로직 var resultLsit = ResultLogicManager.GetSearchResultList(resultCandleDataList, lossIndicator, market, totalIndicator, false, buyScript, sellScript); return resultLsit; } // 결과 보기 버튼 클릭 시 이벤트 처리 private void simpleButton_ViewResultData_Click(object sender, EventArgs e) { // 예외 처리 if (_saveResultData.SearchResultList == null || _saveResultData.SearchResultList.Count <= 0) { MessageBox.Show("계산 처리된 데이터가 없습니다."); return; } var resultViewerForm = new ResultViewerForm(_saveResultData) { StartPosition = FormStartPosition.CenterScreen }; resultViewerForm.ShowDialog(); } // 저장된 결과 데이터 폼 불러오기 private void simpleButton_SavedResultViewer_Click(object sender, EventArgs e) { var savedResultViewerForm = new SavedResultViewerForm(this) { StartPosition = FormStartPosition.CenterScreen }; if (savedResultViewerForm.ShowDialog() != DialogResult.OK) return; // 시간 데이터 추가 dateEdit_StartDateTime.DateTime = _saveResultData.StartDateTime.Date; dateEdit_EndDateTime.DateTime = _saveResultData.EndDateTime.Date; textEdit_BuyRegularExpression.Text = _saveResultData.BuyRegularExpression; textEdit_SellRegularExpression.Text = _saveResultData.SellRegularExpression; textEdit_SellExceptionRegularExpression.Text = _saveResultData.SellExceptionRegularExpression; // Buy/Sell 리스트에 데이터 추가 treeList_BuySetupList.DataSource = _saveResultData.BuySetupList; treeList_SellSetupList.DataSource = _saveResultData.SellSetupList; treeList_BuySetupList.RefreshDataSource(); treeList_SellSetupList.RefreshDataSource(); } /// /// 전체 초기화 /// /// /// private void simpleButton1_Click(object sender, EventArgs e) { //List 처리에 대한 초기화 처리 tb_SearchResultDataName.Text = ""; cb_DownBeforeValueFlag.Checked = true; cb_IncludeClearIndicator.Checked = true; cb_UpperMainIndi.Checked = true; rd_RealtimeHunter.Checked = true; InitForm(); } // 임시 저장 버튼 private void simpleButton_SaveTest_Click(object sender, EventArgs e) { // 계산 결과 데이터 관련 클래스에 값 채우기 _saveResultData.StartDateTime = dateEdit_StartDateTime.DateTime; _saveResultData.EndDateTime = dateEdit_EndDateTime.DateTime; _saveResultData.SavedDateTime = DateTime.Now; if (_saveResultData == null) _saveResultData.SearchResultList = new List(); _saveResultData.BuyRegularExpression = textEdit_BuyRegularExpression.Text; _saveResultData.SellRegularExpression = textEdit_SellRegularExpression.Text; _saveResultData.SellExceptionRegularExpression = textEdit_SellExceptionRegularExpression.Text; if (DBConnection.QueryInsertExecuter_SavedResultData(_saveResultData)) MessageBox.Show("데이터 저장 성공"); else MessageBox.Show("데이터 저장 실패"); } /// /// Buyer 정규식에 추가 /// /// /// private void bt_InsertBuyerIndicator_Click(object sender, EventArgs e) { var name = tb_BuyerIndicatorName.Text; _saveResultData.StartDateTime = dateEdit_StartDateTime.DateTime; _saveResultData.EndDateTime = dateEdit_EndDateTime.DateTime; _saveResultData.SavedDateTime = DateTime.Now; if (_saveResultData == null) _saveResultData.SearchResultList = new List(); _saveResultData.BuyRegularExpression = textEdit_BuyRegularExpression.Text; _saveResultData.SellRegularExpression = textEdit_SellRegularExpression.Text; _saveResultData.SellExceptionRegularExpression = textEdit_SellExceptionRegularExpression.Text; if (DBConnection.QueryInsertExecuter_RealTimeIndicator(_saveResultData, name)) MessageBox.Show("데이터 저장 성공"); else MessageBox.Show("데이터 저장 실패"); } /// /// List 데이터 계산하기 /// /// /// private void bt_CalculateList_Click(object sender, EventArgs e) { if (multiSavedResultDatas.Count > 0) { LogManager.WriteLog("헌터 리스트 계산 시작", "Hunter List 계산"); CommonProperty.InsertLogFlag = true; foreach (var item in multiSavedResultDatas) { CommonProperty.StarValueLowBuyValueUp = item.StarValueLowOverlapUp; CalculateDatas(item.SavedResultData, item.UpperMainIndicatorFlag, item.IncludeClearIndicator, item.DownBeforeValueFlag, item.HunterMode); LogManager.WriteLog("헌터 리스트 계산 완료. Name : " + item.SavedResultData.Name, "Hunter List 계산"); // 3. 자동으로 저장하기 if (DBConnection.QueryInsertExecuter_SavedResultData(item.SavedResultData)) { LogManager.WriteLog("데이터 저장 성공. Name : " + item.SavedResultData.Name, "Hunter List 계산"); } else { LogManager.WriteLog("데이터 저장 실패. Name : " + item.SavedResultData.Name, "Hunter List 계산"); } } MessageBox.Show("List 계산 완료"); } } /// /// List에 데이터 추가하기 /// /// /// private void bt_InsertList_Click(object sender, EventArgs e) { if(tb_SearchResultDataName.Text.Length == 0) { MessageBox.Show("Name 입력 바람"); } else { if(multiSavedResultDatas.Any(t=>t.Name == tb_SearchResultDataName.Text)) { MessageBox.Show("겹치는 Name이 존재 함. 다르게 입력 바람."); } else { _saveResultData.Name = tb_SearchResultDataName.Text; DeafultDataSet(); var data = new MultiSavedResultData(); data.Name = tb_SearchResultDataName.Text.ToString(); data.SavedResultData = _saveResultData.Clone(); data.DownBeforeValueFlag = cb_DownBeforeValueFlag.Checked; data.HunterMode = rd_Hunter.Checked; data.IncludeClearIndicator = cb_IncludeClearIndicator.Checked; data.UpperMainIndicatorFlag = cb_UpperMainIndi.Checked; data.StarValueLowOverlapUp = cb_StarValueLowOverlapUp.Checked; multiSavedResultDatas.Add(data); MessageBox.Show("추가 완료"); } } } /// /// List 확인 /// /// /// private void bt_CheckedList_Click(object sender, EventArgs e) { var subForm = new LoadCalculateDataList(); subForm.Init(multiSavedResultDatas); if (subForm.ShowDialog() == DialogResult.OK) multiSavedResultDatas = subForm.dataList; } } }