diff --git a/MainForm.Designer.cs b/MainForm.Designer.cs index 111a088..6d41e54 100644 --- a/MainForm.Designer.cs +++ b/MainForm.Designer.cs @@ -169,7 +169,7 @@ this.tbTrailing.Name = "tbTrailing"; this.tbTrailing.Size = new System.Drawing.Size(100, 21); this.tbTrailing.TabIndex = 10; - this.tbTrailing.Text = "2.0%"; + this.tbTrailing.Text = "3.0%"; this.tbTrailing.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // label5 diff --git a/MainForm.cs b/MainForm.cs index 74ba47b..d44646b 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -275,10 +275,12 @@ namespace upper_limit_crawler private void btMATest_Click(object sender, EventArgs e) { - string strCode = "A010240"; - string strCodeName = "흥국"; - string strDate = "20160725"; - string strPrevDate = "20160722"; + Console.WriteLine("시뮬레이션 시작"); + + string strCode = "A096040"; + string strCodeName = "이트론"; + string strPrevDate = "20160725"; + string strDate = "20160726"; List DataList = new List(); @@ -331,11 +333,11 @@ namespace upper_limit_crawler - ULWatchItem item = new ULWatchItem(); - item.m_strCode = strCode; - item.m_strCodeName = strCodeName; - item.m_iCurPrice = 0; - item.m_iPrevClosing = 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(); @@ -345,16 +347,16 @@ namespace upper_limit_crawler int iTime = data.iTime; int iCurPrice = data.iPrice; - if (item.m_iPrevClosing == 0) - item.m_iPrevClosing = iPrevClosing; + if (WatchItem.m_iPrevClosing == 0) + WatchItem.m_iPrevClosing = iPrevClosing; - item.m_iCurPrice = iCurPrice; - item.InsertPriceNode(iTime, iCurPrice); + WatchItem.m_iCurPrice = iCurPrice; + WatchItem.InsertPriceNode(iTime, iCurPrice); if(OwnItem.m_iUnitBEP != 0) OwnItem.m_iMaxPrice = Math.Max(OwnItem.m_iMaxPrice, iCurPrice); - float fCompRate = item.m_iCurPrice / (float)item.m_iPrevClosing - 1.0f; + 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) { if (m_DataMgr.IsInBlackList(iTime, strCode) == true) @@ -363,7 +365,7 @@ namespace upper_limit_crawler continue; } - float f5MASlope = item.GetPrev5MASlope(iTime); + float f5MASlope = WatchItem.GetPrev5MASlope(iTime); if (f5MASlope <= 0) { //Console.WriteLine("[{0}] 조건 매수 실패. 5ma 상승하지 않음 {1}원 ({2})", item.m_strCodeName, item.m_iCurPrice, fCompRate.ToString("0.00%")); @@ -371,11 +373,13 @@ namespace upper_limit_crawler } // bid and add to black list - Console.WriteLine(string.Format("[{0}] [{1}] 조건 매수 {2}원 ({3}) (5MA slop:{4:0.00})", iTime, item.m_strCodeName, item.m_iCurPrice, fCompRate.ToString("0.00%"), f5MASlope)); - ULUtil.TraceCSV("조건 매수", item.m_strCodeName, item.m_iCurPrice, fCompRate.ToString("0.00%"), f5MASlope); + Console.WriteLine("[{0}] [{1}] 조건 매수 {2}원 ({3}) (5MA slop:{4:0.00})", iTime, WatchItem.m_strCodeName, WatchItem.m_iCurPrice, fCompRate.ToString("0.00%"), f5MASlope); + ULUtil.TraceCSV("조건 매수", WatchItem.m_strCodeName, WatchItem.m_iCurPrice, fCompRate.ToString("0.00%"), f5MASlope); - OwnItem.m_iUnitBEP = iCurPrice; - OwnItem.m_strCodeName = item.m_strCodeName; + OwnItem.m_iUnitBEP = (OwnItem.m_iUnitBEP*OwnItem.m_iConclusionBalanceCnt + iCurPrice)/ (OwnItem.m_iConclusionBalanceCnt+1); + OwnItem.m_iConclusionBalanceCnt++; + + OwnItem.m_strCodeName = WatchItem.m_strCodeName; //m_DataMgr.GetTrader().Buy(strCode, item.m_iCurPrice, (int)m_DataMgr.m_Setting.m_fBidAmount); m_DataMgr.AddBlackList(iTime, strCode); @@ -387,9 +391,10 @@ namespace upper_limit_crawler // loss cut if (iCurPrice <= OwnItem.m_iUnitBEP * (1.0f - m_DataMgr.m_Setting.m_fLossCut)) { - Console.WriteLine(string.Format("[{0}] [{1}] 손절 {2}원 ({3}:{4})", iTime, OwnItem.m_strCodeName, iCurPrice, iCurPrice - OwnItem.m_iUnitBEP, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"))); + Console.WriteLine("[{0}] [{1}] 손절 {2}원 ({3}:{4})", iTime, OwnItem.m_strCodeName, iCurPrice, iCurPrice - OwnItem.m_iUnitBEP, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%")); ULUtil.TraceCSV("손절", OwnItem.m_strCodeName, iCurPrice, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%")); OwnItem.m_iUnitBEP = 0; + OwnItem.m_iConclusionBalanceCnt = 0; //m_DataMgr.GetTrader().SellCurPrice(OwnItem.m_strCode, OwnItem.m_iPayBalance); //m_OwnList.Remove(OwnItem); @@ -402,28 +407,45 @@ namespace upper_limit_crawler // trailing else if (iCurPrice <= OwnItem.m_iMaxPrice - OwnItem.m_iUnitBEP * m_DataMgr.m_Setting.m_fTrailing) { - float f5MASlope = item.GetPrev5MASlope(iTime); + float f5MASlope = WatchItem.GetPrev5MASlope(iTime); if (f5MASlope > 0) { - //Console.WriteLine(string.Format("[{0}] [{1}] 트레일링 매도 대기. 5ma 상승 중 {2}원 ({3})", iTime, OwnItem.m_strCodeName, iCurPrice, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"))); + //Console.WriteLine("[{0}] [{1}] 트레일링 매도 대기. 5ma 상승 중 {2}원 ({3})", iTime, OwnItem.m_strCodeName, iCurPrice, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%")); continue; } - Console.WriteLine(string.Format("[{0}] [{1}] 트레일링 매도 {2}원 ({3}:{4}) (5MA slop:{5:0.00})", iTime, OwnItem.m_strCodeName, iCurPrice, iCurPrice- OwnItem.m_iUnitBEP, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"), f5MASlope)); + Console.WriteLine("[{0}] [{1}] 트레일링 매도 {2}원 ({3}:{4}) (5MA slop:{5:0.00})", iTime, OwnItem.m_strCodeName, iCurPrice, iCurPrice- OwnItem.m_iUnitBEP, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"), f5MASlope); ULUtil.TraceCSV("트레일링 매도", OwnItem.m_strCodeName, iCurPrice, iCurPrice - OwnItem.m_iUnitBEP, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"), f5MASlope); 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; + } } } - - - //item.PrintChart(); + Console.WriteLine("시뮬레이션 끝"); } } } diff --git a/ULBalanceDlg.cs b/ULBalanceDlg.cs index 8949638..a7e01c1 100644 --- a/ULBalanceDlg.cs +++ b/ULBalanceDlg.cs @@ -159,6 +159,7 @@ namespace upper_limit_crawler foreach (ListViewItem lvItem in lvBalance.Items) { string strCode = lvItem.SubItems[chCode.Index].Text; + int iTime = ULUtil.GetCurTimeInt(); if (WatchList.ContainsKey(strCode) == true) { @@ -202,12 +203,14 @@ namespace upper_limit_crawler // loss cut if (iCurPrice <= OwnItem.m_iUnitBEP * (1.0f - m_DataMgr.m_Setting.m_fLossCut)) { - ULUtil.Trace("[{0}] 손절 {1}원 ({2}) {3}", OwnItem.m_strCodeName, iCurPrice, (iCurPrice/(float)OwnItem.m_iUnitBEP-1.0f).ToString("0.00%"), WatchItem.m_iHighestPrice); - ULUtil.TraceCSV("손절", OwnItem.m_strCodeName, iCurPrice, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"), WatchItem.m_iHighestPrice); m_DataMgr.GetTrader().SellCurPrice(OwnItem.m_strCode, OwnItem.m_iPayBalance); m_OwnList.Remove(OwnItem); m_DataMgr.RemoveWatch(strCode); + ULUtil.Trace("[{0}] 손절 {1}원 ({2}) {3}", OwnItem.m_strCodeName, iCurPrice, (iCurPrice/(float)OwnItem.m_iUnitBEP-1.0f).ToString("0.00%"), WatchItem.m_iHighestPrice); + ULUtil.TraceCSV("손절", OwnItem.m_strCodeName, iCurPrice, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"), WatchItem.m_iHighestPrice); + + // own에서 삭제하고 미체결 리스트에 넣고, watch에서도 뺀다 // 미체결 잔량 취소 @@ -215,7 +218,6 @@ namespace upper_limit_crawler // trailing else if (iCurPrice <= OwnItem.m_iMaxPrice - OwnItem.m_iUnitBEP * m_DataMgr.m_Setting.m_fTrailing) { - int iTime = ULUtil.GetCurTimeInt(); float f5MASlope = WatchItem.GetPrev5MASlope(iTime); if (f5MASlope > 0) { @@ -223,6 +225,10 @@ namespace upper_limit_crawler continue; } + m_DataMgr.GetTrader().SellCurPrice(OwnItem.m_strCode, OwnItem.m_iPayBalance); + m_OwnList.Remove(OwnItem); + m_DataMgr.RemoveWatch(strCode); + ULUtil.Trace("[{0}] 트레일링 매도 {1}원 ({2}:{3}) (5MA slop:{4:0.00}) {5}", OwnItem.m_strCodeName, iCurPrice, @@ -231,12 +237,24 @@ namespace upper_limit_crawler f5MASlope, WatchItem.m_iHighestPrice); ULUtil.TraceCSV("트레일링 매도", OwnItem.m_strCodeName, iCurPrice, iCurPrice - OwnItem.m_iUnitBEP, (iCurPrice / (float)OwnItem.m_iUnitBEP - 1.0f).ToString("0.00%"), f5MASlope, WatchItem.m_iHighestPrice); - - m_DataMgr.GetTrader().SellCurPrice(OwnItem.m_strCode, OwnItem.m_iPayBalance); - m_OwnList.Remove(OwnItem); - m_DataMgr.RemoveWatch(strCode); } } + + // steadiness + 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); + + ULUtil.Trace("[{0}] 보합 처리 {1}원 ({2}:{3}) {4}", + 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); + } } } } diff --git a/ULDataMgr.cs b/ULDataMgr.cs index 9ae566c..b63af4b 100644 --- a/ULDataMgr.cs +++ b/ULDataMgr.cs @@ -115,14 +115,9 @@ namespace upper_limit_crawler m_BlackList.Add(black); } - bool IsIn5Min(int iTime1, int iTime2) - { - return DateTime.ParseExact(iTime1.ToString(), "HHmmss", null) > DateTime.ParseExact(iTime2.ToString(), "HHmmss", null) - TimeSpan.ParseExact("05", "mm", null); - } - public bool IsInBlackList(int iTime, string strCode) { - return m_BlackList.Any(r => r.m_strCode == strCode && IsIn5Min(r.m_iTime, iTime)); + return m_BlackList.Any(r => r.m_strCode == strCode && ULUtil.IsInTime(r.m_iTime, iTime, 5)); } public Dictionary GetWatchList() diff --git a/ULWatchItem.cs b/ULWatchItem.cs index 926439e..9595fbf 100644 --- a/ULWatchItem.cs +++ b/ULWatchItem.cs @@ -79,7 +79,7 @@ namespace upper_limit_crawler if(bMakeNew == true && m_1MinChart.Keys.Count >= 2) { int iTimeKey = m_1MinChart.Keys[m_1MinChart.Keys.Count-2]; - Insert5MinChart(iTimeKey); + Insert5MAChart(iTimeKey); } } @@ -202,36 +202,40 @@ namespace upper_limit_crawler } } - bool IsIn5Min(int iBaseKey, int iKeyCheck) - { - int iBaseIdx = m_1MinChart.IndexOfKey(iBaseKey); - int iIdxCheck = m_1MinChart.IndexOfKey(iKeyCheck); - - return (iIdxCheck > iBaseIdx - 5 && iIdxCheck <= iBaseIdx); - } - - void Insert5MinChart(int iTime) + void Insert5MAChart(int iTime) { int iHour = GetHour(iTime); int iMin = GetMinute(iTime); int iSec = GetSecond(iTime); - int iKey = GetTimeKey1Min(iHour, iMin, iSec); + int iInsertKey = GetTimeKey1Min(iHour, iMin, iSec); + + if(iMin == 0) + { + iHour--; + iMin = 59; + } + else + { + iMin--; + } + int iSearchtKey = GetTimeKey1Min(iHour, iMin, iSec); + MATick tick = null; - if (m_5MAChart.ContainsKey(iKey) == false) + if (m_5MAChart.ContainsKey(iInsertKey) == false) tick = new MATick(iTime, 0); else - tick = m_5MAChart[iKey]; + tick = m_5MAChart[iInsertKey]; - int iIdx = m_1MinChart.IndexOfKey(iKey); - IEnumerable> Search = m_1MinChart.Where(r => IsIn5Min(iKey, r.Key)); + int iIdx = m_1MinChart.IndexOfKey(iInsertKey); + IEnumerable> Search = m_1MinChart.Where(r => ULUtil.IsInTime(r.Key, iSearchtKey, 4)); float fMA = Search.Count() == 5 ? (float)Search.Average(r => r.Value.m_iEnd) : 0; tick.m_fMA = fMA; - if(m_5MAChart.ContainsKey(iKey) == true) - m_5MAChart[iKey] = tick; + if(m_5MAChart.ContainsKey(iInsertKey) == true) + m_5MAChart[iInsertKey] = tick; else - m_5MAChart.Add(iKey, tick); + m_5MAChart.Add(iInsertKey, tick); } public void MakeMAChart() @@ -252,7 +256,7 @@ namespace upper_limit_crawler tick = m_5MAChart[iKey]; int iIdx = m_1MinChart.IndexOfKey(iKey); - IEnumerable> Search = m_1MinChart.Where(r => IsIn5Min(iKey, r.Key)); + IEnumerable> Search = m_1MinChart.Where(r => ULUtil.IsInTime(iKey, r.Key, 5)); float fMA = Search.Count() == 5 ? (float)Search.Average(r => r.Value.m_iEnd) : 0; tick.m_fMA = fMA; @@ -320,5 +324,14 @@ namespace upper_limit_crawler return false; } + + public float GetAvgDiff(int iTime) + { + IEnumerable> itor = m_1MinChart.Where(r => ULUtil.IsInTime(r.Key, iTime, 5)); + + float fSum = itor.Sum(r => r.Value.m_iEnd); + fSum += itor.Sum(r => r.Value.m_iStart); + return fSum / (itor.Count()*2); + } } } diff --git a/UlUtil.cs b/UlUtil.cs index f4e3a08..28171ee 100644 --- a/UlUtil.cs +++ b/UlUtil.cs @@ -256,5 +256,21 @@ namespace upper_limit_crawler m_CPUtil = new CPUTILLib.CpCybos(); } + + public static bool IsInTime(int iTime1, int iTime2, int iMinDiff) + { + int iHour1 = iTime1 / 10000; + int iMin1 = (iTime1 / 100) % 100; + int iSec1 = iTime1 % 100; + + int iHour2 = iTime2 / 10000; + int iMin2 = (iTime2 / 100) % 100; + int iSec2 = iTime2 % 100; + + int iTotalSec1 = iHour1 * 60 * 60 + iMin1 * 60 + iSec1; + int iTotalSec2 = iHour2 * 60 * 60 + iMin2 * 60 + iSec2; + + return (iTotalSec2 >= iTotalSec1 && iTotalSec2 - iTotalSec1 <= iMinDiff * 60); + } } }