Files
Million/Million Buyer/MainForm.cs

1032 lines
44 KiB
C#

using DevExpress.XtraTreeList.Nodes;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Million;
using Million.Data;
using Million.Data.Upbit;
using Million.Data.Upbit.Order;
using Million.DbManagement;
using Million.IndicatorConditionSetup;
using Million.Manager;
using Million.SaveData;
using Million_Buyer.SubForm;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Million.CommonProperty;
namespace Million_Buyer
{
public partial class MainForm : Form
{
bool RealTimeMode = true;
private SavedResultData _saveResultData;
//결과 데이터
private List<SearchResult> resultDataList;
//구매 데이터
private List<CandleDataList> buyList;
bool SetIndicator = false;
bool ThreadFlag = false;
bool AliveCheckor = false;
private Thread thread = null;
private Thread orderThread = null;
private List<Account> accounts = null;
private PaymentType payment = PaymentType.KRW;
private Stopwatch unlimitThreadStopWatch = new Stopwatch();
private bool unlimitChecker = false;
private long second = 0;
private int cycleCount = 0;
private double cycleBuyMoney = 0;
private int buyCycleCount = 0;
private bool buyFlag = true;
public MainForm()
{
InitializeComponent();
Init();
}
public void Init()
{
// data setting
DbServiceFunctions.GetMarketTable_FromDB("Upbit", "KRW");
// Result Data DB에 생성
Million.DbManagement.DBConnection.QueryUpdateExcuter
(CommonProperty.DbConnectionResultData, DbServiceFunctions.CreateSavedAnalysisDataTableQuery());
Million.DbManagement.DBConnection.QueryUpdateExcuter
(CommonProperty.DbConnectionResultData, DbServiceFunctions.CreateSavedResultDataTableQuery());
Million.DbManagement.DBConnection.QueryUpdateExcuter
(CommonProperty.DbConnectionResultData, DbServiceFunctions.CreateRealTimeIndicatorTableQuery());
_saveResultData = new SavedResultData
{
BuySetupList = new List<object>(),
SellSetupList = new List<object>()
};
resultDataList = new List<SearchResult>();
buyList = new List<CandleDataList>();
// 현재 연결되어 있는 KEY를 이용하여 확인
cb_UserList.Items.Add("이장화");
cb_UserList.Items.Add("김영호");
cb_UserList.Items.Add("이찬균");
//cb_UserList.SelectedIndex = 0;
unlimitThreadStopWatch.Start();
}
/// <summary>
/// 실시간 모드일 경우
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void rd_Realtime_CheckedChanged(object sender, EventArgs e)
{
RealTimeMode = true;
SetReadOnly(true);
}
/// <summary>
/// Buyer 모드일 경우
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void rd_buyer_CheckedChanged(object sender, EventArgs e)
{
RealTimeMode = false;
SetReadOnly(false);
}
/// <summary>
/// Read Only Set(모드 변경)
/// </summary>
/// <param name="flag"></param>
private void SetReadOnly(bool flag)
{
tb_CycleCount.ReadOnly = flag;
tb_CycleMoneyValue.ReadOnly = flag;
}
/// <summary>
/// 조건식 폼 띄우기
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bt_Modify_Click(object sender, EventArgs e)
{
var subForm = new IndicatorLoadForm();
if (subForm.ShowDialog() == DialogResult.OK)
{
_saveResultData.SellSetupList = ((List<object>)subForm.selectData["SellSetupList"]);
_saveResultData.BuySetupList = ((List<object>)subForm.selectData["BuySetupList"]);
_saveResultData.BuyRegularExpression = subForm.selectData["BuyRegularExpression"].ToString();
_saveResultData.SellRegularExpression = subForm.selectData["SellRegularExpression"].ToString();
lb_IndiName.Text = subForm.selectData["Name"].ToString();
SetIndicator = true;
}
}
/// <summary>
/// Start Button Event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bt_Start_Click(object sender, EventArgs e)
{
if (!SetIndicator)
{
MessageBox.Show("Indicator Setting 필요");
}
else
{
int.TryParse(tb_CycleCount.Text, out cycleCount);
double.TryParse(tb_CycleMoneyValue.Text, out cycleBuyMoney);
bt_BuyStart_Click(null, null);
CommonProperty.UpperMainIndicatorFlag = cb_UpperMainIndi.Checked;
CommonProperty.DownBeforeValueFlag = cb_DownBeforeValueFlag.Checked;
if (!RealTimeMode)
{
if (cycleCount == 0 || cycleBuyMoney == 0)
{
MessageBox.Show("한번에 구입 할 종목 수, 종목 별 구입 금액 입력 바람(Double, Int)");
return;
}
}
if (!ThreadFlag)
{
SetReadOnly(true);
bt_Start.Enabled = false;
thread = new Thread(ThreadFunction);
thread.Start();
//실시간 검증에는 동작하지 않음
if (!RealTimeMode)
{
orderThread = new Thread(OrderThreadFunction);
orderThread.Start();
}
ThreadFlag = true;
cb_UserList.Enabled = false;
cb_AccountList.Enabled = false;
cb_DownBeforeValueFlag.Enabled = false;
}
}
}
/// <summary>
/// Stop Button Event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bt_Stop_Click(object sender, EventArgs e)
{
ThreadFlag = false;
//if (!RealTimeMode && thread != null) thread.Abort();
//if (!RealTimeMode && orderThread != null) orderThread.Abort();
bt_Start.Enabled = true;
rd_buyer.Enabled = true;
rd_Realtime.Enabled = true;
if (rd_buyer.Checked)
SetReadOnly(false);
cb_UserList.Enabled = true;
cb_AccountList.Enabled = true;
cb_DownBeforeValueFlag.Enabled = true;
/*
* 종료 된 후 데이터 처리 소스는 여기서 처리
* 1. Grid에 Stop 후 데이터 처리
* 2. 종료 후 데이터 저장 처리
*/
}
/// <summary>
/// 실시간 Order 현황 Check(1초에 한번씩 호출할까 2초에 한번할까 고민중
/// </summary>
private void OrderThreadFunction()
{
InsertLog("Order Thread Start");
var orderList = CommonProperty.UpbitApi.GetOrderListInformation(UpbitOrderListTypes.waitwatch);
//setting
foreach (var item in orderList)
{
var account = this.accounts.FirstOrDefault(t => t.UnitCurrency + "-" + t.Currency == item.CoinFullName);
if (account != null)
account.Balance = item.ExecutedVolume;
}
while (ThreadFlag)
{
//Oder List는 Wait, Watch로 구분되어 있는 List 최신 100개, Done, Cancel로 구분되어 있는 List 최신 100개를 표기함
orderList = CommonProperty.UpbitApi.GetOrderListInformation(UpbitOrderListTypes.waitwatch);
orderList.AddRange(CommonProperty.UpbitApi.GetOrderListInformation(UpbitOrderListTypes.donecancel));
orderList = orderList.Distinct().ToList();
this.BeginInvoke(new Action(delegate ()
{
try
{
tl_RealtimeOrder.Nodes.Clear();
foreach (var item in orderList)
{
tl_RealtimeOrder.AppendNode(new object[]
{
item.Uuid,
item.CoinFullName,
item.Side,
item.OrderPrice,
item.State,
item.Volume,
item.ExecutedVolume,
item.CreateOrderTime.ToString("yyyy-MM-dd HH:mm:ss")
}, null);
}
var tempData = orderList.Select(t => t.CoinFullName).ToList();
var buyListUuids = buyList.Select(t => t.ConGoodsData.CoinFullName).ToList();
tempData.AddRange(buyListUuids);
buyCycleCount = tempData.Distinct().ToList().Count;
lb_BuyMarketCount.Text = buyCycleCount.ToString();
}
catch (Exception e)
{
InsertLog("Order Thread Error : " + e.Message);
}
}));
//1초에 한번씩 부르게 처리
Thread.Sleep(1000);
}
InsertLog("Order Thread End");
}
/// <summary>
/// 실제 동작 Thread
/// </summary>
private void ThreadFunction()
{
#region Default Setting
//시간 체크
var sw = new System.Diagnostics.Stopwatch();
unlimitThreadStopWatch.Start();
var dataList = new Dictionary<MCandleTimeType, List<CandleDataList>>();
var sellIndicator = _saveResultData.SellSetupList.OfType<IndicatorCoditionSetup>().ToList();
var buyIndicator = _saveResultData.BuySetupList.OfType<IndicatorCoditionSetup>().ToList();
var totalIndicatorList = new List<IndicatorCoditionSetup>();
totalIndicatorList.AddRange(sellIndicator);
totalIndicatorList.AddRange(buyIndicator);
var candleTypeList = totalIndicatorList.Select(t => t.MCandleTimeType).ToList();
candleTypeList.Add(MCandleTimeType.M1);
candleTypeList = candleTypeList.Distinct().ToList();
//사고 파는 rex 데이터 가져오는 부분
var buyRex = _saveResultData.BuyRegularExpression;
var sellRex = _saveResultData.SellRegularExpression;
var buyScript = new InteratorScripter("Buy Script");
buyScript.regularExpressionString = buyRex;
var sellScript = new InteratorScripter("Sell Script");
sellScript.regularExpressionString = sellRex;
var scriptDic = new Dictionary<string, bool>();
//TODO 모든 조건 데이터 미리 계산 필요
//save 데이터
_saveResultData.StartDateTime = DateTime.Now;
//구매 후 데이터 여러개 계속 겹치는 경우 제외하기 위한 List
var overlapBuyManagementList = new Dictionary<string, bool>();
int firstFlag = 0;
RealtimeDataSettingManager realTimeMsg = null;
var standardTime = DateTime.Now;
this.BeginInvoke(new Action(delegate ()
{
lb_StartDate.Text = standardTime.ToString("yyyy-MM-dd HH:mm:ss");
}));
if (RealTimeMode)
InsertLog("실시간 검증 구동 중..");
else
InsertLog("Buyer 구동 중..");
var cnt = 0;
sw.Start();
#endregion
while (ThreadFlag)
{
try
{
unlimitThreadStopWatch.Restart();
if (AliveCheckor)
{
AliveCheckor = false;
InsertLog("Alive");
}
#region 기본 데이터 Setting
if (firstFlag == 0)
{
realTimeMsg = new RealtimeDataSettingManager(null, this.payment);
dataList = realTimeMsg.GetRealTimeCandleData(candleTypeList, 200);
foreach (var item in realTimeMsg.coinFullNameList)
{
if (cb_IncludeClearIndicator.Checked)
overlapBuyManagementList[item] = false;
else
overlapBuyManagementList[item] = true;
}
foreach (var item in totalIndicatorList)
{
var dic = new Dictionary<string, bool>();
foreach (var codeFullname in realTimeMsg.coinFullNameList)
{
if (cb_IncludeClearIndicator.Checked)
dic[codeFullname] = false;
else
dic[codeFullname] = true;
}
CommonProperty.subIndicatorStateManagement[item.IndexString] = dic;
}
#region TODO 이미 구매되어 있는 종목에 대한 기본 데이터 Setting 필요
if (!RealTimeMode)
{
foreach(var item in this.accounts)
{
if(item.Currency != "KRW")
{
var buyItem = new CandleDataList();
buyItem.Uuid = "";
var temp = dataList[MCandleTimeType.M1].FirstOrDefault(t => t.ConGoodsData.CoinFullName == item.UnitCurrency + "-" + item.Currency);
if (temp == null) continue;
buyItem.ConGoodsData = temp.ConGoodsData;
var candle = new CandleData();
candle.BuyTime = new DateTime(2000, 1, 1);
candle.BuyValue = item.AvgBuyPrice;
candle.BuyCount = item.Balance;
buyItem.CandleDataLists_Im.Add(candle);
buyList.Add(buyItem);
}
}
this.BeginInvoke(new Action(delegate ()
{
try
{
foreach (var item in buyList)
{
var recentlyData = item.CandleDataLists_Im[0];
var time = recentlyData.BuyTime;
tl_BuyList.AppendNode(new object[]
{
item.ConGoodsData.CoinFullName, recentlyData.BuyValue, recentlyData.BuyCount, time.ToString("yyyy-MM-dd HH:mm:ss")
}, null);
}
lb_BuyMarketCount.Text = buyList.Count.ToString();
}
catch (Exception e)
{
InsertLog("이전에 사놓은 개수 입력 관련 에러" + e.Message);
}
}));
}
#endregion
firstFlag = 1;
InsertLog("Deafult Data Setting 완료..");
sw.Stop();
InsertLog("Default 계산 시간 : " + sw.Elapsed.ToString());
LogManager.WriteLog("Default 계산 시간 : " + sw.Elapsed.ToString());
}
else
{
if (firstFlag == 1)
{
sw.Restart();
dataList = realTimeMsg.ProcessRecentlyCandleDatas(dataList, candleTypeList);
sw.Stop();
if (sw.Elapsed.TotalSeconds > 1)
InsertLog("Ticker 계산 시간 : " + sw.Elapsed.ToString());
}
}
#endregion
foreach (var item in realTimeMsg.coinFullNameList)
{
#region Indicator 계산 -> Code full name 으로 for문 돌면서 계산 처리
var dic = new Dictionary<MCandleTimeType, List<CandleData>>();
var distinctIndicator = IndicatorSetupManager.Distinct(totalIndicatorList);
sw.Restart();
foreach (var key in dataList.Keys)
{
var candleDataList = dataList[key].FirstOrDefault(t => t.ConGoodsData.CoinFullName == item);
dic[key] = candleDataList.CandleDataLists_Im;
var indicatorSetUpList = distinctIndicator.Where(t => t.MCandleTimeType == key).ToList();
foreach (var setup in indicatorSetUpList)
{
setup.excute(dic[key], true);
}
}
sw.Stop();
if (sw.Elapsed.TotalSeconds > 1)
InsertLog("Execute 계산 시간 : " + sw.Elapsed.ToString());
var minDateTime = dic[MCandleTimeType.M1].Select(t => t.DateTime).Min();
var maxDateTime = dic[MCandleTimeType.M1].Select(t => t.DateTime).Max().AddHours(1);
sw.Restart();
dic = IndicatorSetupManager.CalculateIndicator(dic, totalIndicatorList, minDateTime, maxDateTime, item, true);
sw.Stop();
if (sw.Elapsed.TotalSeconds > 1)
InsertLog("Indicator Calculate 계산 시간 : " + sw.Elapsed.ToString());
#endregion
#region 사고 파는 로직
//최신 데이터 가져오기
var recentlyDataList = dic[MCandleTimeType.M1].Where(t=>t.RecentlyDataFlag).ToList();
if (recentlyDataList.Count == 0)
continue;
var maxTime = recentlyDataList.Select(t => t.DateTime).Max();
var recentlyData = recentlyDataList.FirstOrDefault(t => t.DateTime == maxTime);
if (recentlyData == null)
continue;
// 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;
}
/*
* 로직 설명
* 1. Buy List에 있는지 확인
* 2. 없을 경우 추가(Buy Script 처리)
* 3. Buy List에 있을 경우 Sell Script 확인
* 4. Sell 처리 후 결과 처리
*/
//없을 시 -> BUY
if (!buyList.Any(t => t.ConGoodsData.CoinFullName == item))
{
if (!buyFlag) continue;
var flag = buyScript.DicExcuteScript(recentlyData.CalculateFlag);
if (flag)
{
if (overlapBuyManagementList[item])
{
InsertLog("Insert Buy Logic");
if (!RealTimeMode)
{
LogManager.WriteLog("Buy CoinFullName : " + item + "\r\nCandleData : " + JsonConvert.SerializeObject(recentlyData), "BuySell");
InsertLog("Buy Coin Name : " + item + ", DateTime : " + recentlyData.DateTime.ToString("yyyy-MM-dd HH:mm:ss"));
if (buyCycleCount >= cycleCount)
continue;
}
sw.Restart();
//if (resultDataList.Select(t => t.MarketData).ToList().Any(t => t.CoinFullName == item)) continue;
var time = DateTime.Now;
var buyData = new CandleDataList();
buyData.CandleDataLists_Im.Add(recentlyData);
var valDic = ResultLogicManager.GetIndicateValue(recentlyData.CalculateFlag, totalIndicatorList, recentlyData);
recentlyData.BuyValue = OrderbookManager.GetAskPrice(CalculateManager.GetConditionValue(buyRex, valDic, recentlyData.CalculateFlag));
recentlyData.BuyTime = time;
buyData.ConGoodsData = dataList[MCandleTimeType.M1].FirstOrDefault(t => t.ConGoodsData.CoinFullName == item).ConGoodsData;
// 임시 -> 실시간은 1개만 삿다고 처리
if (RealTimeMode)
{
recentlyData.BuyCount = 1;
}
else
{
recentlyData.BuyCount = Math.Round(cycleBuyMoney / recentlyData.BuyValue, 8);
buyData.Uuid = OrderBuy(buyData.ConGoodsData.CoinFullName, recentlyData.BuyCount, recentlyData.BuyValue);
if (buyData.Uuid == "")
{
InsertLog("Return Data 가 에러라서 구매 불가. Log 확인 바람");
continue;
}
buyCycleCount++;
}
buyList.Add(buyData);
string str = "Buy : " + item + ",\r\n Buy Candle Data : " + JsonConvert.SerializeObject(recentlyData) + "\r\n";
LogManager.WriteLog(str, item);
overlapBuyManagementList[item] = false;
InsertLog(buyData.ConGoodsData.CoinFullName + " Market Data 구입 DateTime : " + time.ToString("yyyy-MM-dd HH:mm:ss"));
//grid 처리 구매항목, 구매 가격, 구매 개수, 구매시점
this.BeginInvoke(new Action(delegate ()
{
try {
tl_BuyList.AppendNode(new object[]
{
buyData.ConGoodsData.CoinFullName, recentlyData.BuyValue, recentlyData.BuyCount, time.ToString("yyyy-MM-dd HH:mm:ss")
}, null);
lb_BuyMarketCount.Text = buyList.Count.ToString();
}
catch (Exception e)
{
InsertLog("Buy 후 Grid Insert Error : " + e.Message);
}
}));
sw.Stop();
if (sw.Elapsed.TotalSeconds > 1)
InsertLog("Buy 계산 로직 : " + sw.Elapsed.ToString());
}
}
else
{
overlapBuyManagementList[item] = true;
}
}
else
{
var flag = sellScript.DicExcuteScript(recentlyData.CalculateFlag);
if (flag)
{
sw.Restart();
var buyItem = buyList.FirstOrDefault(x => x.ConGoodsData.CoinFullName == item);
var time = DateTime.Now;
var sellItem = recentlyData;
var valDic = ResultLogicManager.GetIndicateValue(sellItem.CalculateFlag, totalIndicatorList, sellItem);
sellItem.SellValue = OrderbookManager.GetAskPrice(CalculateManager.GetConditionValue(sellRex, valDic, sellItem.CalculateFlag), false);
sellItem.SellTime = time;
var buyCandleData = buyItem.CandleDataLists_Im[0];
var sellVal = sellItem.SellValue;
var result = new SearchResult();
var rate = ((sellVal - buyCandleData.BuyValue) / buyCandleData.BuyValue) * 100;
result.FirstEarningRate = rate;
result.EndDate = sellItem.DateTime;
result.CoinFullName = buyItem.ConGoodsData.CoinFullName;
result.MarketData = buyItem.ConGoodsData;
result.BuyEarningRate.Add(rate);
result.BuyValueList.Add(buyCandleData.BuyValue);
result.BuyList.ConGoodsData = buyItem.ConGoodsData;
result.BuyList.CandleDataLists_Im.Add(buyCandleData);
result.StartDate = buyCandleData.DateTime;
result.SellData = sellItem;
result.SellValue = sellVal;
result.TotalEarningRate = rate;
result.WinCount = rate > 0 ? 1 : 0;
result.LoseCount = rate < 0 ? 1 : 0;
result.FirstWinFlag = rate > 0 ? true : false;
result.BuyCount = buyItem.CandleDataLists_Im[0].BuyCount;
result.SellCount = sellItem.BuyCount;
// buycount 에서 sell count를 제외한 양이 미체결 량
if (!RealTimeMode)
{
LogManager.WriteLog("Sell Point 진입 : " + item, item);
InsertLog("Sell Point 진입 : " + item);
recentlyData.BuyCount = Math.Round(cycleBuyMoney / recentlyData.BuyValue, 8);
result.SellCount = OrderSell(buyItem.ConGoodsData.CoinFullName, buyItem.Uuid, sellVal);
buyCycleCount--;
}
resultDataList.Add(result);
string str = "Sell : " + item + ",\r\n Sell Candle Data : " + JsonConvert.SerializeObject(recentlyData) + "\r\n";
LogManager.WriteLog(str, item);
//처리한 buyList는 삭제
buyList.Remove(buyItem);
InsertLog(buyItem.ConGoodsData.CoinFullName + " Market Data 판매 DateTime : " + time.ToString("yyyy-MM-dd HH:mm:ss"));
this.BeginInvoke(new Action(delegate ()
{
try
{
//Grid 처리
TreeListNode buyNode = null;
foreach (TreeListNode node in tl_BuyList.Nodes)
{
if (node.GetValue("BuyMarket").ToString() == buyItem.ConGoodsData.CoinFullName)
{
buyNode = node;
break;
}
}
var moneyVal = (sellVal * (1 - 0.0015) - buyCandleData.BuyValue * (1 - 0.0015)) * result.SellCount;
tl_Result.AppendNode(new object[] {
buyNode.GetValue("BuyMarket"),
buyNode.GetValue("BuyValue"),
buyNode.GetValue("BuyCount"),
buyNode.GetValue("BuyDateTime"),
sellVal,
result.SellCount,
time.ToString("yyyy-MM-dd HH:mm:ss"),
result.FirstEarningRate,
moneyVal
}, null);
tl_BuyList.Nodes.Remove(buyNode);
lb_BuyMarketCount.Text = buyList.Count.ToString();
}
catch (Exception e)
{
InsertLog("Sell Logic Grid Error" + e.Message);
}
}));
if (sw.Elapsed.TotalSeconds > 1)
InsertLog("Sell 계산 로직 : " + sw.Elapsed.ToString());
}
}
#endregion
}
cnt++;
if (cnt % 100000 == 0)
{
InsertLog("Scanning......" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
cnt = 0;
}
}
catch (Exception e)
{
InsertLog("Error : " + e.Message);
}
}
#region Thread 종료 후 후 처리 할 로직
if (RealTimeMode)
{
}
else
{
}
#endregion
SaveData();
InsertLog("Thread Out");
}
/// <summary>
/// 데이터 저장 기능
/// </summary>
/// <param name="resultDataList"></param>
public void SaveData()
{
if (resultDataList.Count > 0)
{
//수익 률 계산 로직 -> 이거는 추후 빼도 될듯
double totalVal = 0;
double win = 0;
double lose = 0;
double firstProfitRate = 0;
double firstWin = 0;
//승률, 수익률 계산
foreach (var item in resultDataList)
{
if (item.FirstWinFlag) firstWin++;
firstProfitRate += item.FirstEarningRate;
win += item.WinCount;
lose += item.LoseCount;
totalVal += item.TotalEarningRate;
}
double winRate;
if (win == 0)
{
winRate = 0;
}
else if (lose == 0)
{
winRate = 100;
}
else
{
winRate = (win * 100 / (win + lose));
}
_saveResultData.ResultDataCount = resultDataList.Count;
_saveResultData.FirstWinRate = (firstWin * 100) / resultDataList.Count;
_saveResultData.FirstProfitRate = firstProfitRate;
_saveResultData.WinRate = winRate;
_saveResultData.ProfitRate = totalVal / resultDataList.Count;
_saveResultData.SearchResultList = resultDataList;
_saveResultData.Name = _saveResultData.SavedDateTime.ToString("yyyy-MM-dd HH:mm:ss") + " Realtime Result";
_saveResultData.Type = "Data";
_saveResultData.SaveResultType = "Realtime";
_saveResultData.ExchangePlace = "Upbit";
_saveResultData.ParentId = null;
_saveResultData.EndDateTime = DateTime.Now;
_saveResultData.SavedDateTime = DateTime.Now;
//buy list가 남아 있을 시
if (buyList.Count > 0)
{
foreach (var item in buyList)
{
var result = new SearchResult();
var buyCandleData = item.CandleDataLists_Im[0];
result.CoinFullName = item.ConGoodsData.CoinFullName;
result.MarketData = item.ConGoodsData;
result.BuyValueList.Add(buyCandleData.BuyValue);
result.BuyList.ConGoodsData = item.ConGoodsData;
result.BuyList.CandleDataLists_Im.Add(buyCandleData);
result.StartDate = buyCandleData.DateTime;
result.BuyCount = buyCandleData.BuyCount;
resultDataList.Add(result);
}
}
_saveResultData.SearchResultList = resultDataList;
DBConnection.QueryInsertExcuter_SavedResultData(_saveResultData);
_saveResultData.StartDateTime = DateTime.Now;
resultDataList.Clear();
MessageBox.Show("데이터 저장 완료");
}
}
/// <summary>
/// 데이터 저장 기능
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bt_Save_Click(object sender, EventArgs e)
{
SaveData();
}
/// <summary>
/// Text Area 에 Log 입력
/// </summary>
/// <param name="log"></param>
private bool InsertLog(string log)
{
this.BeginInvoke(new Action(delegate ()
{
if (lb_log.Items.Count > 500)
{
lb_log.Items.Clear();
}
lb_log.Items.Insert(0, log);
}));
return true;
}
/// <summary>
/// Thread 가 살아 있는지 확인
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bt_alive_Click(object sender, EventArgs e)
{
if (thread != null && thread.IsAlive)
InsertLog("Realtime Thread Alive.");
else
InsertLog("Realtime Thread Death.");
if (orderThread != null && orderThread.IsAlive)
InsertLog("Order List Thread Alive.");
else
InsertLog("Order List Thread Death.");
AliveCheckor = true;
}
/// <summary>
/// 구매 함수
/// Price가 0일경우 현재가 구매
/// return data는 uuid임
/// </summary>
/// <param name="coinFullName"></param>
/// <param name="volume"></param>
/// <param name="price"></param>
private string OrderBuy(string coinFullName, double volume, double price)
{
var side = UpbitOrderSide.bid;
var ordType = UpbitOrderType.limit;
if (price == 0)
ordType = UpbitOrderType.price;
var returnData = CommonProperty.UpbitApi.TryOrder(coinFullName, side, volume, price, InsertLog, ordType);
InsertLog("------------------------------------");
InsertLog("Buy Return Data : " + JsonConvert.SerializeObject(returnData));
InsertLog("------------------------------------");
if (returnData == null) return "";
return returnData.Uuid;
}
/// <summary>
/// 판매하는 함수
/// price가 0일 경우 지정가 판매
/// return data는 총 판매 체결량임
/// </summary>
/// <param name="coinFullName"></param>
/// <param name="volume"></param>
/// <param name="price"></param>
private double OrderSell(string coinFullName, string uuid, double price)
{
var side = UpbitOrderSide.ask;
var ordType = UpbitOrderType.limit;
if (price == 0)
ordType = UpbitOrderType.market;
// 판매시 Order Cancel 진행
OrderCancel(coinFullName, uuid);
var orderData = CommonProperty.UpbitApi.GetOrderInformation(uuid);
if(orderData == null)
{
orderData = new Order();
var account = this.accounts.FirstOrDefault(t => t.UnitCurrency + "-" + t.Currency == coinFullName);
if(account != null)
{
orderData.ExecutedVolume = account.Balance;
}
}
if (orderData.ExecutedVolume != 0)
{
var returnData = CommonProperty.UpbitApi.TryOrder(coinFullName, side, orderData.ExecutedVolume, price, InsertLog, ordType);
InsertLog("------------------------------------");
InsertLog("Sell Return Data : " + JsonConvert.SerializeObject(returnData));
InsertLog("------------------------------------");
}
return orderData.ExecutedVolume;
}
/// <summary>
/// Order 취소 함수
/// </summary>
/// <param name="coinFullName"></param>
/// <param name="uuid"></param>
private void OrderCancel(string coinFullName, string uuid ="")
{
InsertLog("------------------------------------");
InsertLog("Order Cancel");
var orderList = CommonProperty.UpbitApi.GetOrderListInformation(UpbitOrderListTypes.waitwatch, uuid);
foreach (var item in orderList)
{
if (item.State == "wait" || item.State == "watch")
{
if(item.CoinFullName == coinFullName)
{
var returnData = CommonProperty.UpbitApi.CancelOrder(item.Uuid);
InsertLog("Order Cancel Data : " + JsonConvert.SerializeObject(returnData));
}
}
}
InsertLog("------------------------------------");
}
/// <summary>
/// User 변경
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cb_UserList_SelectedIndexChanged(object sender, EventArgs e)
{
//CommonProperty.ChangeUpbitApiKey.
var flag = CommonProperty.ChangeUpbitApiKey(cb_UserList.Text);
if (flag)
{
this.accounts = CommonProperty.UpbitApi.GetAccounts();
var list = this.accounts.Select(t => t.Currency).ToList();
foreach (var item in list)
cb_AccountList.Items.Add(item);
}
else
MessageBox.Show("해당 사용자는 Key List에 존재하지 않습니다.");
}
/// <summary>
/// Payment 변경
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cb_AccountList_SelectedIndexChanged(object sender, EventArgs e)
{
var account = this.accounts.FirstOrDefault(t => t.Currency == cb_AccountList.Text);
if (account == null)
{
MessageBox.Show("해당 사용자의 Account가 정상적이지 않습니다.");
}
else
{
var subStr = "원";
if (cb_AccountList.Text == "KRW")
{
this.payment = PaymentType.KRW;
}
else if (cb_AccountList.Text == "BTC")
{
this.payment = PaymentType.BTC;
subStr = "Bit Coin";
}
else if (cb_AccountList.Text == "USDT")
{
this.payment = PaymentType.USDT;
subStr = "USDT";
}
lb_TotalMoney.Text = account.Balance.ToString() + subStr;
}
}
private void bt_BuyStop_Click(object sender, EventArgs e)
{
buyFlag = false;
lb_BuyFlag.Text = "매수 정지";
}
private void bt_BuyStart_Click(object sender, EventArgs e)
{
buyFlag = true;
lb_BuyFlag.Text = "매수 진행 중";
}
private void timer1_Tick(object sender, EventArgs e)
{
var milli = unlimitThreadStopWatch.ElapsedMilliseconds;
if (milli > 60000)
{
if (!unlimitChecker)
{
InsertLog("무한루프 : 60초 이상 동작 하지 않음");
unlimitChecker = true;
}
}
if (second > milli)
{
unlimitChecker = false;
}
second = milli;
}
}
}