Files
upper-limit-crawler/MainForm.cs

526 lines
15 KiB
C#

using System;
using System.Windows.Forms;
using System.Collections;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading;
namespace upper_limit_crawler
{
//struct ITEM
//{
// string m_strCode;
// DateTime m_Time;
// int m_iCurPrice;
// int m_iAskCount;
// int m_iBidCount;
// int m_iStartPrice;
// int m_iTradingVolume;
// float m_fRatePerStart;
//}
public partial class MainForm : Form
{
ArrayList m_TraceList = new ArrayList();
System.Windows.Forms.Timer m_MainTimer = new System.Windows.Forms.Timer();
int m_iLastTime = 0;
static ULDataMgr m_DataMgr = new ULDataMgr();
ULOwn m_Own = new ULOwn(m_DataMgr);
ULMonitorDlg m_MonitorDlg = null;
ULBalanceDlg m_BalanceDlg = null;
public MainForm()
{
InitializeComponent();
SetDoubleBuffered(tbLog);
ULUtil.Init(tbLog);
btApply_Click(null, null);
m_MonitorDlg = new ULMonitorDlg(m_DataMgr);
splitContainer3.Panel1.Controls.Add(m_MonitorDlg);
m_MonitorDlg.Dock = DockStyle.Fill;
m_MonitorDlg.Show();
m_BalanceDlg = new ULBalanceDlg(m_DataMgr);
splitContainer3.Panel2.Controls.Add(m_BalanceDlg);
m_BalanceDlg.Dock = DockStyle.Fill;
m_BalanceDlg.Show();
m_MainTimer.Interval = 10;
m_MainTimer.Tick += Refresh;
m_MainTimer.Start();
ULUtil.Trace("시작");
}
public static void SetDoubleBuffered(Control control)
{
// set instance non-public property with name "DoubleBuffered" to true
typeof(Control).InvokeMember("DoubleBuffered",
BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, control, new object[] { true });
}
private bool IsOnTime()
{
DateTime CurTime = ULUtil.GetCurTime();
if (CurTime.DayOfWeek == DayOfWeek.Sunday || CurTime.DayOfWeek == DayOfWeek.Saturday)
return false;
if (CurTime.Hour < 8 || CurTime.Hour > 15)
return false;
if (CurTime.Hour == 8 && CurTime.Minute < 50)
return false;
if (CurTime.Hour == 15 && CurTime.Minute > 15)
return false;
return true;
}
private void Refresh(object sender, EventArgs e)
{
//if(IsOnTime() == false)
// return;
int iCurTime = Environment.TickCount;
if(m_iLastTime == 0)
{
m_iLastTime=iCurTime;
return;
}
if(cbStart.Checked == true && ULUtil.IsConnected() == false)
{
cbStart.Checked = false;
return;
}
int iDeltaT = iCurTime - m_iLastTime;
m_Own.Refresh(iCurTime);
lbRQCnt.Text = "RQ Count : " + ULUtil.GetLimitRemainCountRQ().ToString();
lbSBCnt.Text = "SB Count : " + ULUtil.GetLimitRemainCountSB().ToString();
lbCacheBalance.Text = "잔고 : " + m_DataMgr.GetCacheBalance().ToString("###,###,###,###,##0원");
lbEvalProfit.Text = "평가손익 : " + m_DataMgr.GetEvalProfit().ToString("###,###,###,###,##0원");
statusBar1.Panels[1].Text = ULUtil.GetCurTimeString() + " ";
m_iLastTime = iCurTime;
}
void StartAll()
{
m_MonitorDlg.Start();
m_BalanceDlg.Start();
m_DataMgr.StartAll();
}
void StopAll()
{
m_MonitorDlg.Stop();
m_BalanceDlg.Stop();
m_DataMgr.StopAll();
}
private void cbStart_CheckedChanged(object sender, EventArgs e)
{
if (cbStart.Checked == true)
{
if (ULUtil.IsConnected() == false)
ULUtil.Reset();
if (ULUtil.IsConnected() == false)
{
cbStart.Checked = false;
MessageBox.Show("Cybos Plus를 실행해주세요");
return;
}
m_DataMgr.Init();
StartAll();
}
else
{
StopAll();
}
}
private void AddTrace(string strCode)
{
if (m_TraceList.Contains(strCode) == true)
return;
m_TraceList.Add(strCode);
}
private void btApply_Click(object sender, EventArgs e)
{
try
{
m_DataMgr.m_Setting.m_fSearchMin = float.Parse(tbSearchMin.Text.Replace("%", ""))/100;
m_DataMgr.m_Setting.m_fSearchMax = float.Parse(tbSearchMax.Text.Replace("%", ""))/100;
m_DataMgr.m_Setting.m_fBidMin = float.Parse(tbBidMin.Text.Replace("%", ""))/100;
m_DataMgr.m_Setting.m_fBidMax = float.Parse(tbBidMax.Text.Replace("%", ""))/100;
m_DataMgr.m_Setting.m_fBidAmount = float.Parse(tbBidAmount.Text);
m_DataMgr.m_Setting.m_fTimeout = float.Parse(tbTimeout.Text);
m_DataMgr.m_Setting.m_fTrailing = float.Parse(tbTrailing.Text.Replace("%", ""))/100;
m_DataMgr.m_Setting.m_fLossCut = float.Parse(tbLossCut.Text.Replace("%", ""))/100;
btCancel_Click(null, null);
}
catch(Exception ex)
{
ULUtil.Trace(ex.ToString());
}
}
private void btCancel_Click(object sender, EventArgs e)
{
tbSearchMin.Text = (m_DataMgr.m_Setting.m_fSearchMin*100).ToString("0.0") + "%";
tbSearchMax.Text = (m_DataMgr.m_Setting.m_fSearchMax*100).ToString("0.0") + "%";
tbBidMin.Text = (m_DataMgr.m_Setting.m_fBidMin*100).ToString("0.0") + "%";
tbBidMax.Text = (m_DataMgr.m_Setting.m_fBidMax*100).ToString("0.0") + "%";
tbBidAmount.Text = m_DataMgr.m_Setting.m_fBidAmount.ToString("###,###,###,###,###");
tbTimeout.Text = m_DataMgr.m_Setting.m_fTimeout.ToString("0.###");
tbTrailing.Text = (m_DataMgr.m_Setting.m_fTrailing*100).ToString("0.0") + "%";
tbLossCut.Text = (m_DataMgr.m_Setting.m_fLossCut*100).ToString("0.0") + "%";
}
private void btCybos5_Click(object sender, EventArgs e)
{
string strappname = @"C:\DAISHIN\STARTER\ncStarter.exe";
Process.Start(strappname);
}
private void btCybosPlus_Click(object sender, EventArgs e)
{
string strappname = @"C:\DAISHIN\STARTER\ncStarter.exe";
Process.Start(strappname, @"/prj:cp");
}
private void btTimeSync_Click(object sender, EventArgs e)
{
ULUtil.SyncServerTime();
}
struct chart_data
{
public chart_data(int iTime, int iPrice)
{
this.iTime = iTime;
this.iPrice = iPrice;
}
public int iTime;
public int iPrice;
override public string ToString() { return string.Format("[{0]] {{1}}", iTime, iPrice); }
}
private void btMATest_Click(object sender, EventArgs e)
{
Console.WriteLine("시뮬레이션 시작");
List<string> aCodeList = new List<string> {
"A064240",
"A090410",
"A208860",
"A044180",
"A127160",
"A123570",
"A039420",
"A015020",
"A090850",
"A007660",
"A017180",
"A036810",
"A049950",
"A044480",
"A047310",
"A115610",
"A086060",
"A118000",
"A037400",
"A027580",
"A100090",
"A103130",
"A032790",
"A226350",
"A024800",
"A002630",
"A109740",
"A077970",
"A040350",
"A092870",
"A001140",
"A065130",
"A043340",
"A038010",
"A099410",
"A115440",
"A115960",
"A098120",
"A004380",
"A007120",
"A025820",
"A005980",
"A011810",
"A131100",
"A059090",
"A083470",
"A051170",
"A096350",
"A131400",
"A122800",
"A043910",
"A089590",
"A067990",
"A091970",
"A058450",
"A104040",
"A003070",
};
string strPrevDate = "20160801";
string strDate = "20160802";
int iTotalProfit = 0;
foreach (string code in aCodeList)
{
string strCode = code[0] == 'A' ? code : "A"+code;
string strCodeName = ULUtil.GetCodeName(strCode);
Console.WriteLine("{0}({1})", strCodeName, strCode);
List<chart_data> DataList = new List<chart_data>();
CPSYSDIBLib.StockChart stockChart = new CPSYSDIBLib.StockChart();
stockChart.SetInputValue(0, strCode);
stockChart.SetInputValue(1, '1');
stockChart.SetInputValue(2, strPrevDate);
stockChart.SetInputValue(3, strPrevDate);
stockChart.SetInputValue(4, 1);
stockChart.SetInputValue(5, new int[] { 0, 1, 2, 3, 4, 5, 6, 10, 37 });
stockChart.SetInputValue(6, 'T');
ULUtil.BlockRequest(stockChart);
int iTimeTest = (int)stockChart.GetDataValue(1, 0);
int iPrevClosing = stockChart.GetDataValue(5, 0);
stockChart.SetInputValue(0, strCode);
stockChart.SetInputValue(1, '1');
stockChart.SetInputValue(2, strDate);
stockChart.SetInputValue(3, strDate);
stockChart.SetInputValue(4, 0);
stockChart.SetInputValue(5, new int[] { 0, 1, 2, 3, 4, 5, 6, 10, 37 });
stockChart.SetInputValue(6, 'T');
ULUtil.BlockRequest(stockChart);
int iFieldCnt = stockChart.GetHeaderValue(1);
string[] astrFieldName = stockChart.GetHeaderValue(2);
while (true)
{
int iCnt = (int)stockChart.GetHeaderValue(3);
for (int i = 0; i < iCnt; i++)
{
int iTime = (int)stockChart.GetDataValue(1, i);
iTime *= 100;
int iCurPrice = (int)stockChart.GetDataValue(5, i);
int iVolume = (int)stockChart.GetDataValue(5, i);
DataList.Add(new chart_data(iTime, iCurPrice));
}
if(stockChart.Continue == 1)
ULUtil.BlockRequest(stockChart);
else
break;
}
int iTotalBidPrice = 0;
int iTotalAskPrice = 0;
ULWatchItem WatchItem = new ULWatchItem();
WatchItem.m_strCode = strCode;
WatchItem.m_strCodeName = strCodeName;
WatchItem.m_iCurPrice = 0;
WatchItem.m_iPrevClosing = 0;
ULBalanceDlg.OWN_ITEM OwnItem = new ULBalanceDlg.OWN_ITEM();
DataList.Reverse();
foreach (chart_data data in DataList)
{
int iTime = data.iTime;
int iCurPrice = data.iPrice;
if (WatchItem.m_iPrevClosing == 0)
WatchItem.m_iPrevClosing = iPrevClosing;
WatchItem.m_iCurPrice = iCurPrice;
WatchItem.InsertPriceNode(iTime, iCurPrice);
if (OwnItem.m_iUnitBEP != 0)
OwnItem.m_iMaxPriceAfterBid = Math.Max(iCurPrice, OwnItem.m_iMaxPriceAfterBid);
float fCompRate = WatchItem.m_iCurPrice / (float)WatchItem.m_iPrevClosing - 1.0f;
if (fCompRate >= m_DataMgr.m_Setting.m_fBidMin && fCompRate <= m_DataMgr.m_Setting.m_fBidMax)
{
m_DataMgr.AddAvailableItem(strCode);
if (m_DataMgr.IsInPostponeList(iTime, strCode) == true)
{
//Console.WriteLine("[{0}] 조건 매수 실패. black list {1}원 ({2})", item.m_strCodeName, item.m_iCurPrice, fCompRate.ToString("0.00%"));
continue;
}
else if(m_DataMgr.IsInBlackList(strCode) == true)
{
continue;
}
float f5MASlope = WatchItem.GetPrev5MASlope(iTime);
if(f5MASlope < 0.002f)
{
//Console.WriteLine("[{0}] 조건 매수 실패. 5ma 상승하지 않음 {1}원 ({2})", item.m_strCodeName, item.m_iCurPrice, fCompRate.ToString("0.00%"));
continue;
}
// bid and add to black list
Console.WriteLine("[{0}] [{1}] 조건 매수 {2}원 ({3}) (5MA slop:{4})", iTime, WatchItem.m_strCodeName, WatchItem.m_iCurPrice, fCompRate.ToString("0.00%"), f5MASlope.ToString("0.00%"));
ULUtil.TraceCSV(iTime, "[시뮬레이션] 조건 매수", WatchItem.m_strCodeName, WatchItem.m_iCurPrice, fCompRate.ToString("0.00%"), f5MASlope.ToString("0.00%"));
m_DataMgr.AddBidLog(strCode, WatchItem.m_strCodeName, iTime, WatchItem.m_iCurPrice, f5MASlope, false);
int iBidCnt = (int)m_DataMgr.m_Setting.m_fBidAmount / iCurPrice;
iTotalBidPrice += iCurPrice* iBidCnt;
OwnItem.m_iUnitBEP = (OwnItem.m_iUnitBEP * OwnItem.m_iConclusionBalanceCnt + iCurPrice * iBidCnt) / (OwnItem.m_iConclusionBalanceCnt + iBidCnt);
OwnItem.m_iConclusionBalanceCnt += iBidCnt;
OwnItem.m_strCodeName = WatchItem.m_strCodeName;
//m_DataMgr.GetTrader().Buy(strCode, item.m_iCurPrice, (int)m_DataMgr.m_Setting.m_fBidAmount);
m_DataMgr.AddPostphoneItem(iTime, strCode);
}
if (OwnItem.m_iUnitBEP > 0)
{
// loss cut
if (iCurPrice <= OwnItem.m_iUnitBEP * (1.0f - m_DataMgr.m_Setting.m_fLossCut))
{
m_DataMgr.AddLosscutItem(strCode);
int iProfit = iCurPrice - (int)OwnItem.m_iUnitBEP;
float fProfitRate = (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f);
Console.WriteLine("[{0}] [{1}] 손절 {2}원 ({3}:{4})", iTime, OwnItem.m_strCodeName, iCurPrice, iProfit, fProfitRate.ToString("0.00%"));
ULUtil.TraceCSV(iTime, "[시뮬레이션] 손절", OwnItem.m_strCodeName, iCurPrice, fProfitRate.ToString("0.00%"));
m_DataMgr.AddAskLog(strCode, WatchItem.m_strCodeName, iTime, iCurPrice, float.NaN, true, iProfit, fProfitRate, false);
iTotalAskPrice += iCurPrice * OwnItem.m_iConclusionBalanceCnt;
OwnItem.m_iUnitBEP = 0;
OwnItem.m_iConclusionBalanceCnt = 0;
//m_DataMgr.GetTrader().SellCurPrice(OwnItem.m_strCode, OwnItem.m_iPayBalance);
//m_OwnList.Remove(OwnItem);
//m_DataMgr.RemoveWatch(strCode);
// own에서 삭제하고 미체결 리스트에 넣고, watch에서도 뺀다
// 미체결 잔량 취소
}
// trailing
else if (iCurPrice <= OwnItem.m_iMaxPriceAfterBid - OwnItem.m_iUnitBEP * m_DataMgr.m_Setting.m_fTrailing)
{
float f5MASlope = WatchItem.GetPrev5MASlope(iTime);
if (float.IsNaN(f5MASlope) || f5MASlope > -0.0100f)
{
//Console.WriteLine("[{0}] [{1}] 트레일링 매도 대기. 5ma 상승 중 {2}원 ({3})", iTime, OwnItem.m_strCodeName, iCurPrice, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"));
continue;
}
int iProfit = iCurPrice - (int)OwnItem.m_iUnitBEP;
float fProfitRate = (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f);
Console.WriteLine("[{0}] [{1}] 트레일링 매도 {2}원 ({3}:{4}) (5MA slop:{5})", iTime, OwnItem.m_strCodeName, iCurPrice, iProfit, fProfitRate.ToString("0.00%"), f5MASlope.ToString("0.00%"));
ULUtil.TraceCSV(iTime, "[시뮬레이션] 트레일링 매도", OwnItem.m_strCodeName, iCurPrice, iProfit, fProfitRate.ToString("0.00%"), f5MASlope.ToString("0.00%"));
m_DataMgr.AddAskLog(strCode, WatchItem.m_strCodeName, iTime, iCurPrice, f5MASlope, false, iProfit, fProfitRate, false);
iTotalAskPrice += iCurPrice * OwnItem.m_iConclusionBalanceCnt;
OwnItem.m_iUnitBEP = 0;
OwnItem.m_iConclusionBalanceCnt = 0;
//m_DataMgr.GetTrader().SellCurPrice(OwnItem.m_strCode, OwnItem.m_iPayBalance);
//m_OwnList.Remove(OwnItem);
//m_DataMgr.RemoveWatch(strCode);
}
//// steadiness
//else if (WatchItem.GetAvgDiff(iTime) < WatchItem.m_iPrevClosing*0.01)
//{
// //m_DataMgr.GetTrader().SellCurPrice(OwnItem.m_strCode, OwnItem.m_iPayBalance);
// //m_OwnList.Remove(OwnItem);
// //m_DataMgr.RemoveWatch(strCode);
// Console.WriteLine("[{0}] [{1}] 보합 처리 {2}원 ({3}:{4}) {5}",
// iTime,
// OwnItem.m_strCodeName,
// WatchItem.m_iCurPrice,
// WatchItem.m_iCurPrice - OwnItem.m_iUnitBEP,
// (WatchItem.m_iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"),
// WatchItem.m_iHighestPrice);
// ULUtil.TraceCSV("[시뮬레이션]", "보합 처리", OwnItem.m_strCodeName, WatchItem.m_iCurPrice, WatchItem.m_iCurPrice - OwnItem.m_iUnitBEP, (WatchItem.m_iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"), WatchItem.m_iHighestPrice);
// OwnItem.m_iUnitBEP = 0;
//}
}
}
if (OwnItem.m_iConclusionBalanceCnt > 0)
{
iTotalAskPrice += WatchItem.FinalPrice() * OwnItem.m_iConclusionBalanceCnt;
OwnItem.m_iUnitBEP = 0;
OwnItem.m_iConclusionBalanceCnt = 0;
}
Console.WriteLine("Profit : {0}/{1} ({2}:{3:0.00%})", iTotalBidPrice, iTotalAskPrice, iTotalAskPrice - iTotalBidPrice, iTotalAskPrice / (float)iTotalBidPrice - 1.0f);
Console.WriteLine("\n");
iTotalProfit += (iTotalAskPrice - iTotalBidPrice);
//WatchItem.PrintChart();
}
Console.WriteLine("total : {0}", iTotalProfit);
Console.WriteLine("시뮬레이션 끝");
}
private void btLogDump_Click(object sender, EventArgs e)
{
m_DataMgr.DumpLog(true);
}
private void button1_Click(object sender, EventArgs e)
{
m_DataMgr.DumpLog(false);
}
}
}