using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace NewsCrawler { public partial class NewsForm : Form { class NEWS_ITEM { public NEWS_ITEM(int iID, string strTitle, string strCode, CodeList.CODE_VALUE Code, DateTime NewsTime, DateTime ResTime, string strRef, string strURL, float fElapseT) { m_iID = iID; m_strCode = strCode; m_Code = Code; m_NewsTime = NewsTime; m_ResTime = ResTime; m_strRef = strRef; m_strTitle = strTitle; m_strURL = strURL; m_fElapseT = fElapseT; } public int m_iID; public string m_strCode; public CodeList.CODE_VALUE m_Code = null; public DateTime m_NewsTime; public DateTime m_ResTime; public string m_strRef; public string m_strTitle; public string m_strURL; public float m_fElapseT; } class PRICE_CHECK_DATA { public int m_iID; public CodeList.CODE_VALUE m_Code; public int m_iPriceStart = 0; public int m_iPriceLow = 0; public int m_iPriceHigh = 0; public DateTime m_StartTime; public int m_iTryCnt = 0; public bool m_bLog = false; public NEWS_ITEM m_NewsItem; } CybosHelper m_CybosHelper = null; CodeList m_CodeList = null; TextCondition m_Condition = null; ConfigForm m_ConfigForm = null; DateTime m_StartTime; DateTime m_EndTime; System.Timers.Timer m_CrawlTimer = new System.Timers.Timer(); int m_iCrawlInterval = 500; bool m_bBuy = false; List m_URLs = new List(); System.Timers.Timer m_SystemTimer = new System.Timers.Timer(); ConcurrentQueue m_PriceCheckList = new ConcurrentQueue(); System.Timers.Timer m_PriceCheckTimer = new System.Timers.Timer(); delegate void InsertListView(string strTitle, string strName, string strCode, DateTime time, DateTime ResTime, string strURL, string strRef, double responseT, bool bInitial); InsertListView m_InsertListViewDelegate = null; Crawler m_Crawler = null; ExcelHandler m_Excel = null; object m_lvListLock = new object(); public NewsForm() { InitializeComponent(); m_StartTime = DateTime.ParseExact("09:00", "HH:mm", CultureInfo.CurrentCulture); m_EndTime = DateTime.ParseExact("15:30", "HH:mm", CultureInfo.CurrentCulture); Config.Init(); Util.SetLogView(tbLog); m_CodeList = new CodeList(); m_Condition = new TextCondition(); m_CybosHelper = new CybosHelper(this); m_Crawler = new Crawler(this); Util.Log(Util.LOG_TYPE.VERVOSE, "========== NewsCrawler 실행 =========="); //MessageBox.Show("Keywords : \n\n" + m_Condition.GetKeywordsCnt()); m_InsertListViewDelegate = new InsertListView(this.InsertItem); m_Crawler.ReadKIND(true); m_Crawler.ReadDart(true); m_Crawler.ReadEtoday(true); //m_Crawler.ReadEtoday2(true); m_Crawler.ReadAsiaE(true); m_Crawler.ReadEdaily(true); m_Crawler.ReadMoneyToday(true); m_Crawler.ReadFinancialNews(true); lvList.Columns[chTime.Index].TextAlign = HorizontalAlignment.Right; lvList.Columns[chResponseT.Index].TextAlign = HorizontalAlignment.Right; lvList.Columns[chResT.Index].TextAlign = HorizontalAlignment.Right; lvList.Columns[chId.Index].TextAlign = HorizontalAlignment.Right; lvList.Columns[chPriceS.Index].TextAlign = HorizontalAlignment.Right; lvList.Columns[chPriceLow.Index].TextAlign = HorizontalAlignment.Right; lvList.Columns[chPriceLowP.Index].TextAlign = HorizontalAlignment.Right; lvList.Columns[chPriceHigh.Index].TextAlign = HorizontalAlignment.Right; lvList.Columns[chPriceHighP.Index].TextAlign = HorizontalAlignment.Right; lvList.ListViewItemSorter = new ListViewItemComparer(chId.Index, SortOrder.Ascending); lvList.Sorting = SortOrder.Ascending; lvList.Sort(); if(lvList.Items.Count > 0) { lvList.Items[lvList.Items.Count - 1].Selected = true; lvList.Select(); if(lvList.SelectedItems.Count > 0) lvList.SelectedItems[0].EnsureVisible(); } //foreach(ColumnHeader col in lvList.Columns) //{ // if(!(col == chPriceS || col == chPriceLow || col == chPriceHigh)) // col.Width = -2; //} m_Excel = new ExcelHandler(Util.GetLogPath()+"/PriceCheck-"+DateTime.Now.ToString("yyyy-MM-dd")+".xlsx"); m_CrawlTimer.Elapsed+=CrawlTimer_Tick; m_CrawlTimer.Interval = m_iCrawlInterval; m_CrawlTimer.Start(); m_SystemTimer.Elapsed+=SystemTimer_Elapsed; m_SystemTimer.Interval=1000; m_SystemTimer.Start(); m_PriceCheckTimer.Interval = 5000; m_PriceCheckTimer.Elapsed += PriceCheckTimer_Elapsed; m_PriceCheckTimer.Start(); m_bBuy = true; Test(); } void Test() { if(Util.IsDebugging() == false) return; InsertItem("[test] 덕산하이메탈, 덕산네오룩스 66만여주 취득14:38", "", "", new DateTime(2016, 11, 30, 00, 00, 00), DateTime.Now, "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914371817318", "asiae", 0, false); InsertItem("[test] 자연과환경, 12월15일~22일 주주명부폐쇄14:19", "", "", new DateTime(2016, 11, 30, 00, 00, 00), DateTime.Now, "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914193170301", "asiae", 0, false); InsertItem("[test] 이엠코리아, 한국항공우주산업과 3억원 규모 공급계약14:06", "", "", new DateTime(2016, 11, 30, 00, 00, 00), DateTime.Now, "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914055964082", "asiae", 0, false); InsertItem("[test] [특징주] 진원생명과학, 국외 AI 인체감염증...", "", "", new DateTime(2016, 11, 30, 00, 00, 00), DateTime.Now, "http://www.etoday.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914055964082", "이투데이", 0, false); } private void BuyItem(CodeList.CODE_VALUE Code) { if(m_bBuy == false) return; if((Code.m_enType & CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DENIAL) { Util.Log(Util.LOG_TYPE.DENIAL, string.Format("거부종목 ({0})", Code)); return; } if((Code.m_enType & CodeList.CODE_TYPE.DUPLICATED) == CodeList.CODE_TYPE.DUPLICATED) { Util.Log(Util.LOG_TYPE.DUPLICATED, string.Format("중복종목 ({0})", Code)); return; } m_CybosHelper.Buy(Code, Config.GetBuyPrice()); m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName); } public void OnManualItemBuy(CodeList.CODE_VALUE Code) { BuyItem(Code); } void CheckPrice(NEWS_ITEM NewsItem) { if(DateTime.Now < m_StartTime || DateTime.Now >= m_EndTime) return; PRICE_CHECK_DATA CheckData = new PRICE_CHECK_DATA(); CheckData.m_iID = NewsItem.m_iID; CheckData.m_Code = NewsItem.m_Code; CheckData.m_StartTime = DateTime.Now; CheckData.m_NewsItem = NewsItem; m_PriceCheckList.Enqueue(CheckData); } void ProcessSearchAndBuy(NEWS_ITEM NewsItem) { TextCondition.RESULT MatchResult = m_Condition.Match(NewsItem.m_strTitle); switch(MatchResult.m_enType) { case TextCondition.TYPE.NEGATIVE: Util.Log(Util.LOG_TYPE.NEGATIVE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code.ToString())); break; case TextCondition.TYPE.POSITIVE: if((NewsItem.m_Code.m_enType&CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DENIAL) Util.Log(Util.LOG_TYPE.DENIAL, string.Format("[{0}] {1} (keyword:{2}, code:{3})", NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code.ToString())); else if((NewsItem.m_Code.m_enType&CodeList.CODE_TYPE.DUPLICATED) == CodeList.CODE_TYPE.DUPLICATED) Util.Log(Util.LOG_TYPE.DUPLICATED, string.Format("[{0}] {1} (keyword:{2}, code:{3})", NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code.ToString())); else if((NewsItem.m_Code.m_enType&CodeList.CODE_TYPE.MANUAL) == CodeList.CODE_TYPE.MANUAL) { Util.Log(Util.LOG_TYPE.MANUAL_CODE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code.ToString())); if(m_bBuy == true) { ModelessPopup ManualPopup = new ModelessPopup(this); ManualPopup.SetMessage(string.Format("{0}\n[{1}] {2}\n(keyword:{3}, code:{4})\n\n매수하시겠습니까?", DateTime.Now.ToString("[hh:mm:ss]"), NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code), NewsItem.m_Code); ManualPopup.TopMost = true; ManualPopup.Show(); } } else { BuyItem(NewsItem.m_Code); Util.Log(Util.LOG_TYPE.POSITIVE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code.ToString())); } m_CodeList.AddDuplicatedList(NewsItem.m_Code.m_strCode, NewsItem.m_Code.m_strName); break; case TextCondition.TYPE.MANUAL: Util.Log(Util.LOG_TYPE.MANUAL_KEYWORD, string.Format("[{0}] {1} (keyword:{2}, code:{3})", NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code.ToString())); if(m_bBuy == true) { ModelessPopup ManualPopup = new ModelessPopup(this); ManualPopup.SetMessage(string.Format("{0}\n[{1}] {2}\n(keyword:{3}, code:{4})\n\n매수하시겠습니까?", DateTime.Now.ToString("[hh:mm:ss]"), NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code), NewsItem.m_Code); ManualPopup.TopMost = true; ManualPopup.Show(); } m_CodeList.AddDuplicatedList(NewsItem.m_Code.m_strCode, NewsItem.m_Code.m_strName); break; case TextCondition.TYPE.NOT_MATCHED: Util.Log(Util.LOG_TYPE.DEBUG, string.Format("[NOT_MATCHED] [{0}] {1}({2})", NewsItem.m_strRef, NewsItem.m_strTitle, NewsItem.m_Code.ToString())); break; } CheckPrice(NewsItem); } public void OnReceivedSupplyContract(string strCodeName, float fRate) { CodeList.CODE_VALUE Code = m_CodeList.GetCodeByName(strCodeName); if(Code == null) { Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][공급계약체결] 종목을 찾을 수 없음({0}, {1}%", strCodeName, fRate)); return; } if(fRate < Config.GetSupplyContractRate()) { Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][공급계약체결] 매출액 대비율 낮음({0}, {1}% / {2}%)", strCodeName, fRate, Config.GetSupplyContractRate())); return; } string strRef = "DartAPI"; string strTitle = string.Format("공급계약체결 - {0} {1:n2}%", strCodeName, fRate); if((Code.m_enType&CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DENIAL) Util.Log(Util.LOG_TYPE.DENIAL, string.Format("[{0}] {1}", strRef, strTitle)); else if((Code.m_enType&CodeList.CODE_TYPE.DUPLICATED) == CodeList.CODE_TYPE.DUPLICATED) Util.Log(Util.LOG_TYPE.DUPLICATED, string.Format("[{0}] {1}", strRef, strTitle)); else if((Code.m_enType&CodeList.CODE_TYPE.MANUAL) == CodeList.CODE_TYPE.MANUAL) { Util.Log(Util.LOG_TYPE.MANUAL_CODE, string.Format("[{0}] {1}", strRef, strTitle)); if(m_bBuy == true) { ModelessPopup ManualPopup = new ModelessPopup(this); ManualPopup.SetMessage(string.Format("{0}\n[{1}] {2}\n\n매수하시겠습니까?", DateTime.Now.ToString("[hh:mm:ss]"), strRef, strTitle), Code); ManualPopup.TopMost = true; ManualPopup.Show(); } } else { BuyItem(Code); Util.Log(Util.LOG_TYPE.POSITIVE, string.Format("[{0}] {1}", strRef, strTitle)); } m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName); } public void OnReceivedRevenue(string strCodeName, float fRate) { CodeList.CODE_VALUE Code = m_CodeList.GetCodeByName(strCodeName); if (Code == null) { Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][영업실적] 종목을 찾을 수 없음({0}, {1}%", strCodeName, fRate)); return; } if (fRate < Config.GetRevenueRate()) { Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][영업실적] 당기순이익률 낮음({0}, {1}% / {2}%)", strCodeName, fRate, Config.GetRevenueRate())); return; } string strRef = "DartAPI"; string strTitle = string.Format("영업실적 - {0} {1:n2}%", strCodeName, fRate); if ((Code.m_enType & CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DENIAL) Util.Log(Util.LOG_TYPE.DENIAL, string.Format("[{0}] {1}", strRef, strTitle)); else if ((Code.m_enType & CodeList.CODE_TYPE.DUPLICATED) == CodeList.CODE_TYPE.DUPLICATED) Util.Log(Util.LOG_TYPE.DUPLICATED, string.Format("[{0}] {1}", strRef, strTitle)); else if ((Code.m_enType & CodeList.CODE_TYPE.MANUAL) == CodeList.CODE_TYPE.MANUAL) { Util.Log(Util.LOG_TYPE.MANUAL_CODE, string.Format("[{0}] {1}", strRef, strTitle)); if (m_bBuy == true) { ModelessPopup ManualPopup = new ModelessPopup(this); ManualPopup.SetMessage(string.Format("{0}\n[{1}] {2}\n\n매수하시겠습니까?", DateTime.Now.ToString("[hh:mm:ss]"), strRef, strTitle), Code); ManualPopup.TopMost = true; ManualPopup.Show(); } } else { BuyItem(Code); Util.Log(Util.LOG_TYPE.POSITIVE, string.Format("[{0}] {1}", strRef, strTitle)); } m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName); } public void OnReceivedRightsIssue(string strCodeName) { CodeList.CODE_VALUE Code = m_CodeList.GetCodeByName(strCodeName); if (Code == null) { Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][제3자배정증자] 종목을 찾을 수 없음({0})", strCodeName)); return; } string strRef = "DartAPI"; string strTitle = string.Format("제3자배정증자 - {0}", strCodeName); if ((Code.m_enType & CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DENIAL) Util.Log(Util.LOG_TYPE.DENIAL, string.Format("[{0}] {1}", strRef, strTitle)); else if ((Code.m_enType & CodeList.CODE_TYPE.DUPLICATED) == CodeList.CODE_TYPE.DUPLICATED) Util.Log(Util.LOG_TYPE.DUPLICATED, string.Format("[{0}] {1}", strRef, strTitle)); else if ((Code.m_enType & CodeList.CODE_TYPE.MANUAL) == CodeList.CODE_TYPE.MANUAL) { Util.Log(Util.LOG_TYPE.MANUAL_CODE, string.Format("[{0}] {1}", strRef, strTitle)); if (m_bBuy == true) { ModelessPopup ManualPopup = new ModelessPopup(this); ManualPopup.SetMessage(string.Format("{0}\n[{1}] {2}\n\n매수하시겠습니까?", DateTime.Now.ToString("[hh:mm:ss]"), strRef, strTitle), Code); ManualPopup.TopMost = true; ManualPopup.Show(); } } else { BuyItem(Code); Util.Log(Util.LOG_TYPE.POSITIVE, string.Format("[{0}] {1}", strRef, strTitle)); } m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName); } public void OnReceivedPatent(string strCodeName) { CodeList.CODE_VALUE Code = m_CodeList.GetCodeByName(strCodeName); if(Code == null) { Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][특허권취득] 종목을 찾을 수 없음({0})", strCodeName)); return; } string strRef = "DartAPI"; string strTitle = string.Format("특허권취득 - {0}", strCodeName); if((Code.m_enType & CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DENIAL) Util.Log(Util.LOG_TYPE.DENIAL, string.Format("[{0}] {1}", strRef, strTitle)); else if((Code.m_enType & CodeList.CODE_TYPE.DUPLICATED) == CodeList.CODE_TYPE.DUPLICATED) Util.Log(Util.LOG_TYPE.DUPLICATED, string.Format("[{0}] {1}", strRef, strTitle)); else if((Code.m_enType & CodeList.CODE_TYPE.MANUAL) == CodeList.CODE_TYPE.MANUAL) { Util.Log(Util.LOG_TYPE.MANUAL_CODE, string.Format("[{0}] {1}", strRef, strTitle)); if(m_bBuy == true) { ModelessPopup ManualPopup = new ModelessPopup(this); ManualPopup.SetMessage(string.Format("{0}\n[{1}] {2}\n\n매수하시겠습니까?", DateTime.Now.ToString("[hh:mm:ss]"), strRef, strTitle), Code); ManualPopup.TopMost = true; ManualPopup.Show(); } } else { BuyItem(Code); Util.Log(Util.LOG_TYPE.POSITIVE, string.Format("[{0}] {1}", strRef, strTitle)); } m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName); } public bool IsDuplicatedURL(string strURL) { if(strURL == "") return false; lock(m_URLs) return m_URLs.Any(s => s == strURL); } public void InsertItem(string strTitle, string strName, string strCode, DateTime time, DateTime ResTime, string strURL, string strRef, double dElapseT, bool bInitial) { try { if(this.InvokeRequired) { this.Invoke(m_InsertListViewDelegate, strTitle, strName, strCode, time, ResTime, strURL, strRef, dElapseT, bInitial); } else { if(IsDuplicatedURL(strURL) == true) return; int iID = lvList.Items.Count+1; CodeList.CODE_VALUE Code = null; if(bInitial == false) { if(strCode == "") Code = m_CodeList.SearchCode(strTitle); else Code = m_CodeList.GetCode(strCode); if(Code != null) ProcessSearchAndBuy(new NEWS_ITEM(iID, strTitle, strCode, Code, time, ResTime, strRef, strURL, (float)dElapseT)); } lvList.Items.Add(new ListViewItem(new string[] { iID.ToString(), time.ToString("HH:mm:ss"), ResTime.ToString("HH:mm:ss:fff"), string.Format("{0:n3} ms", dElapseT), strRef, strTitle, (Code != null) ? Code.m_strName : "", "", "", "", "", "", strURL })); if(lvList.Items.Count == 0) { foreach (ColumnHeader col in lvList.Columns) { if (!(col == chPriceS || col == chPriceLow || col == chPriceHigh)) col.Width = -2; } } lock(m_URLs) m_URLs.Add(strURL); if(bInitial == false) lvList.Sort(); } } catch(Exception ex) { Util.Log(Util.LOG_TYPE.ERROR, ex.Message + Environment.NewLine + ex.StackTrace); } } private void SystemTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if(statusBar.InvokeRequired) { statusBar.BeginInvoke((MethodInvoker)delegate () { statusBar.Items[3].Text = DateTime.Now.ToString("HH:mm:ss"); statusBar.Items[2].Text = m_CybosHelper.GetLimitRemainCountRQ().ToString(); statusBar.Items[0].Text = m_CybosHelper.IsConnected() ? "연결됨" : "연결끊김"; }); } else { statusBar.Items[3].Text = DateTime.Now.ToString("HH:mm:ss"); statusBar.Items[2].Text = m_CybosHelper.GetLimitRemainCountRQ().ToString(); statusBar.Items[0].Text = m_CybosHelper.IsConnected() ? "연결됨" : "연결끊김"; } } private void CrawlTimer_Tick(object sender, EventArgs e) { m_CrawlTimer.Stop(); if(chAutoReload.Checked == true) { m_Crawler.ReadKIND(); m_Crawler.ReadDart(); if(Config.CheckDartAPI()) m_Crawler.ReadDartAPI(); m_Crawler.ReadEtoday(); //m_Crawler.ReadEtoday2(); m_Crawler.ReadAsiaE(); m_Crawler.ReadEdaily(); m_Crawler.ReadMoneyToday(); m_Crawler.ReadFinancialNews(); } m_CrawlTimer.Interval = m_iCrawlInterval; m_CrawlTimer.Start(); } private void UpdateStartPrice(int iID, int iPrice) { if(lvList.InvokeRequired) { lvList.BeginInvoke((MethodInvoker)delegate () { ListViewItem item = lvList.Items.Cast().FirstOrDefault(s => s.SubItems[chId.Index].Text == iID.ToString()); item.SubItems[chPriceS.Index].Text = iPrice.ToString("n0"); lvList.Columns[chPriceS.Index].Width = -1; }); } else { ListViewItem item = lvList.Items.Cast().FirstOrDefault(s => s.SubItems[chId.Index].Text == iID.ToString()); item.SubItems[chPriceS.Index].Text = iPrice.ToString("n0"); lvList.Columns[chPriceS.Index].Width = -1; } } private void UpdateLowHighPrice(PRICE_CHECK_DATA Data) { if(lvList.InvokeRequired) { lvList.BeginInvoke((MethodInvoker)delegate () { ListViewItem item = lvList.Items.Cast().FirstOrDefault(s => s.SubItems[chId.Index].Text == Data.m_iID.ToString()); item.SubItems[chPriceLow.Index].Text = string.Format("{0:n0}", Data.m_iPriceLow); float fLowRate = (Data.m_iPriceLow-Data.m_iPriceStart)*100/(float)Data.m_iPriceStart; item.UseItemStyleForSubItems = false; item.SubItems[chPriceLowP.Index].Text = string.Format("{0:n}", fLowRate); if(fLowRate > 0) item.SubItems[chPriceLowP.Index].ForeColor = Color.Red; else if(fLowRate < 0) item.SubItems[chPriceLowP.Index].ForeColor = Color.Blue; item.SubItems[chPriceHigh.Index].Text = string.Format("{0:n0}", Data.m_iPriceHigh); float fLowHigh = (Data.m_iPriceHigh-Data.m_iPriceStart)*100/(float)Data.m_iPriceStart; item.SubItems[chPriceHighP.Index].Text = string.Format("{0:n}", fLowHigh); if(fLowHigh > 0) item.SubItems[chPriceHighP.Index].ForeColor = Color.Red; else if(fLowHigh < 0) item.SubItems[chPriceHighP.Index].ForeColor = Color.Blue; lvList.Columns[chPriceHighP.Index].Width = -1; lvList.Columns[chPriceLowP.Index].Width = -1; }); } else { ListViewItem item = lvList.Items.Cast().FirstOrDefault(s => s.SubItems[chId.Index].Text == Data.m_iID.ToString()); item.SubItems[chPriceLow.Index].Text = string.Format("{0:n0}", Data.m_iPriceLow); float fLowRate = (Data.m_iPriceLow-Data.m_iPriceStart)*100/(float)Data.m_iPriceStart; item.SubItems[chPriceLowP.Index].Text = string.Format("{0:n}", fLowRate); item.UseItemStyleForSubItems = false; if(fLowRate > 0) item.SubItems[chPriceLowP.Index].ForeColor = Color.Red; else if(fLowRate < 0) item.SubItems[chPriceLowP.Index].ForeColor = Color.Blue; item.SubItems[chPriceHigh.Index].Text = string.Format("{0:n0}", Data.m_iPriceHigh); float fLowHigh = (Data.m_iPriceHigh-Data.m_iPriceStart)*100/(float)Data.m_iPriceStart; item.SubItems[chPriceHighP.Index].Text = string.Format("{0:n}", fLowHigh); if(fLowHigh > 0) item.SubItems[chPriceHighP.Index].ForeColor = Color.Red; else if(fLowHigh < 0) item.SubItems[chPriceHighP.Index].ForeColor = Color.Blue; lvList.Columns[chPriceHighP.Index].Width = -1; lvList.Columns[chPriceLowP.Index].Width = -1; } } private void PriceCheckTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if(cbPriceCheck.Checked == false) return; m_PriceCheckTimer.Enabled = false; DateTime CurTime = DateTime.Now; foreach(PRICE_CHECK_DATA data in m_PriceCheckList) { if(data.m_iPriceStart == 0) { data.m_iPriceStart = m_CybosHelper.GetCurPrice(data.m_Code); UpdateStartPrice(data.m_iID, data.m_iPriceStart); } else if(data.m_iPriceHigh == 0 && (CurTime - data.m_StartTime).Minutes >= 5) { m_CybosHelper.GetLowHighPrice(data.m_Code, data.m_StartTime, 5, out data.m_iPriceLow, out data.m_iPriceHigh); data.m_iTryCnt++; if(data.m_iPriceHigh > 0) UpdateLowHighPrice(data); } } while(m_PriceCheckList.Count > 0) { PRICE_CHECK_DATA Data; if(m_PriceCheckList.TryPeek(out Data) == false) break; if(Data.m_iTryCnt < 3 && Data.m_iPriceHigh == 0) break; if(Data.m_bLog == false) { Data.m_bLog = m_Excel.AddRow(Data.m_NewsItem.m_NewsTime.ToString("HH:mm:ss:fff"), Data.m_NewsItem.m_ResTime.ToString("HH:mm:ss:fff"), Data.m_NewsItem.m_fElapseT, Data.m_NewsItem.m_strRef, Data.m_NewsItem.m_strTitle, Data.m_NewsItem.m_Code.m_strName, Data.m_iPriceStart, Data.m_iPriceLow, (Data.m_iPriceLow-Data.m_iPriceStart)*100/(float)Data.m_iPriceStart, Data.m_iPriceHigh, (Data.m_iPriceHigh-Data.m_iPriceStart)*100/(float)Data.m_iPriceStart, Data.m_NewsItem.m_strURL); } if(Data.m_bLog == false) break; m_PriceCheckList.TryDequeue(out Data); } m_PriceCheckTimer.Enabled = true; } private void tbInterval_KeyPress(object sender, KeyPressEventArgs e) { if(e.KeyChar == Convert.ToChar(Keys.Enter)) { m_iCrawlInterval = (int)(float.Parse(Regex.Replace(tbInterval.Text, @"\D\.", "")) * 1000); if(m_iCrawlInterval < 1) m_iCrawlInterval = 500; tbInterval.Text = (m_iCrawlInterval / (float)1000).ToString("##0.0") + "초"; } } private void lvList_ColumnClick(object sender, ColumnClickEventArgs e) { SortOrder Order = (lvList.Sorting == SortOrder.Descending || lvList.Sorting == SortOrder.None) ? SortOrder.Ascending : SortOrder.Descending; lvList.ListViewItemSorter = new ListViewItemComparer(e.Column, Order); lvList.Sorting = Order; lvList.Sort(); } private void lvList_DoubleClick(object sender, EventArgs e) { if(lvList.SelectedItems.Count < 1) return; string strLink = lvList.SelectedItems[0].SubItems[chLink.Index].Text; try { System.Diagnostics.Process.Start(strLink); } catch { } } private void btnConfig_Click(object sender, EventArgs e) { if(m_ConfigForm == null) m_ConfigForm = new ConfigForm(this); FormCollection OpenForms = Application.OpenForms; bool bOpen = false; foreach(Form form in OpenForms) { if(form == m_ConfigForm) { bOpen = true; break; } } if(bOpen == false) { m_ConfigForm.Show(); } else { m_ConfigForm.BringToFront(); } } public void OnConfigFormClosing() { m_ConfigForm = null; } public void OnManualCodeClick(int iPrice) { m_CodeList.MakeManualList(iPrice); } public void ApplyDenialCode() { m_CodeList.LoadDenialList(); } public void ApplyDuplicatedCode() { m_CodeList.LoadDuplicatedList(); } public void ApplyPositive() { m_Condition.LoadPositive(); } public void ApplyManual() { m_Condition.LoadManual(); } public void ApplyNegative() { m_Condition.LoadNegative(); } public void ApplySynonym() { m_CodeList.LoadSynonym(); } private void NewsForm_FormClosing(object sender, FormClosingEventArgs e) { Util.Clear(); } private void chBuy_CheckedChanged(object sender, EventArgs e) { m_bBuy = chBuy.Checked; if(m_bBuy == true && Config.GetAccount() == "") { chBuy.Checked = false; MessageBox.Show("계좌를 선택해주시기 바랍니다"); return; } if(m_bBuy == true) Util.Log(Util.LOG_TYPE.VERVOSE, "매수 시작"); else Util.Log(Util.LOG_TYPE.VERVOSE, "매수 취소"); } public string[] GetAccounts() { return m_CybosHelper.GetAccounts(); } public void ApplyAccount(string strAccount, string strAccountSub) { Config.SetAccount(strAccount, strAccountSub); } } class ListViewItemComparer : IComparer { int m_iColumn = 0; SortOrder m_Order = SortOrder.Ascending; public ListViewItemComparer(int column, SortOrder Order) { m_iColumn = column; m_Order = Order; } public int Compare(object x, object y) { ListViewItem item1 = (ListViewItem)x; ListViewItem item2 = (ListViewItem)y; double num1; double num2; if(double.TryParse(item1.SubItems[m_iColumn].Text, out num1) && double.TryParse(item2.SubItems[m_iColumn].Text, out num2)) { return (num1>num2)?1:-1; } else { if(m_Order == SortOrder.Ascending) return string.Compare(item1.SubItems[m_iColumn].Text, item2.SubItems[m_iColumn].Text); else return string.Compare(item2.SubItems[m_iColumn].Text, item1.SubItems[m_iColumn].Text); } } } }