diff --git a/.gitignore b/.gitignore index 2c62ef4..702116b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ obj/ log/ publish/ .vs/ +configure/code-duplicated.txt diff --git a/Config.cs b/Config.cs index 4cce9cf..b15b373 100644 --- a/Config.cs +++ b/Config.cs @@ -4,13 +4,14 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace NewsCrawler { static class Config { - static Dictionary m_Data = new Dictionary(); + static Dictionary m_Data = new Dictionary(); static Random m_Random = new Random(); static int m_iDartAPIKeyCnt = 0; @@ -18,11 +19,20 @@ namespace NewsCrawler public static void Init() { - m_Data.Add("manual-price", "100000"); - m_Data.Add("buy-price", "1000000"); - m_Data.Add("supply-contract-rate", "50.0"); - m_Data.Add("revenue-rate", "50.0"); + m_Data.Add("manual-price", 100000); + m_Data.Add("buy-price", 1000000); + m_Data.Add("ann-dart-api", true); + m_Data.Add("ann-supply-contract", true); + m_Data.Add("ann-supply-contract-rate", 50.0f); + m_Data.Add("ann-revenue", true); + m_Data.Add("ann-revenue-rate", 50.0f); + m_Data.Add("ann-rights-issue", true); + m_Data.Add("ann-patent", true); + m_Data.Add("ann-patent-search-string", new Regex("(미국|중국)")); + Load(); + Migration(); + Save(); int iIdx = 1; while(true) @@ -40,7 +50,7 @@ namespace NewsCrawler static void Load() { - string strPath = Util.GetConfigPath()+"/config.ini"; + string strPath = Util.GetConfigPath() + "/config.ini"; if(File.Exists(strPath) == false) return; @@ -54,18 +64,44 @@ namespace NewsCrawler if(aTokens.Length < 2) continue; - if(m_Data.ContainsKey(aTokens[0]) == true) - m_Data[aTokens[0]] = aTokens[1]; + if(aTokens[0] == "ann-patent-search-string") + { + m_Data[aTokens[0]] = new Regex(aTokens[1]); + } else - m_Data.Add(aTokens[0], aTokens[1]); + { + if(m_Data.ContainsKey(aTokens[0]) == true) + m_Data[aTokens[0]] = Convert.ChangeType(aTokens[1], m_Data[aTokens[0]].GetType()); + else + m_Data.Add(aTokens[0], aTokens[1]); + } + } + } + + static void Migration() + { + if(m_Data.ContainsKey("supply-contract-rate")) + { + float fValue; + float.TryParse((string)m_Data["supply-contract-rate"], out fValue); + m_Data["ann-supply-contract-rate"] = fValue; + m_Data.Remove("supply-contract-rate"); + } + + if(m_Data.ContainsKey("revenue-rate")) + { + float fValue; + float.TryParse((string)m_Data["revenue-rate"], out fValue); + m_Data["ann-revenue-rate"] = fValue; + m_Data.Remove("revenue-rate"); } } static void Save() { string strContents = ""; - foreach(KeyValuePair pair in m_Data) - strContents += pair.Key + "=" + pair.Value + Environment.NewLine; + foreach(KeyValuePair pair in m_Data) + strContents += pair.Key + "=" + pair.Value.ToString() + Environment.NewLine; string strPath = Util.GetConfigPath()+"/config.ini"; File.WriteAllText(strPath, strContents, new UTF8Encoding(true)); @@ -73,27 +109,23 @@ namespace NewsCrawler public static int GetManualPrice() { - int iPrice; - int.TryParse(m_Data["manual-price"], out iPrice); - return iPrice; + return (int)m_Data["manual-price"]; } public static void SetManualPrice(int iPrice) { - m_Data["manual-price"] = iPrice.ToString(); + m_Data["manual-price"] = iPrice; Save(); } public static int GetBuyPrice() { - int iPrice; - int.TryParse(m_Data["buy-price"], out iPrice); - return iPrice; + return (int)m_Data["buy-price"]; } public static void SetBuyPrice(int iPrice) { - m_Data["buy-price"] = iPrice.ToString(); + m_Data["buy-price"] = iPrice; Save(); } @@ -106,38 +138,12 @@ namespace NewsCrawler public static string GetAccount() { - return m_Data["account"]; + return (string)m_Data["account"]; } public static string GetSubAccount() { - return m_Data["sub-account"]; - } - - public static void SetSupplyContractRate(float fRate) - { - m_Data["supply-contract-rate"] = fRate.ToString(); - Save(); - } - - public static float GetSupplyContractRate() - { - float fRate; - float.TryParse(m_Data["supply-contract-rate"], out fRate); - return fRate; - } - - public static void SetRevenueRate(float fRate) - { - m_Data["revenue-rate"] = fRate.ToString(); - Save(); - } - - public static float GetRevenueRate() - { - float fRate; - float.TryParse(m_Data["revenue-rate"], out fRate); - return fRate; + return (string)m_Data["sub-account"]; } public static string GetDartAPIKey() @@ -152,19 +158,81 @@ namespace NewsCrawler while(iNum < 0 || m_abDartAPIKeyLimit[iNum-1] == true) iNum = m_Random.Next(0, 10000)%m_iDartAPIKeyCnt + 1; - return m_Data["dart-api-key"+iNum]; + return (string)m_Data["dart-api-key"+iNum]; } public static void SetDartAPIKeyLimit(string strKey) { - for(int i=0; i HtmlAgility\HtmlAgilityPack.dll + + ..\AutoSeller\packages\MaterialSkin.0.2.1\lib\MaterialSkin.dll + packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll True diff --git a/NewsForm.Designer.cs b/NewsForm.Designer.cs index 13e0db7..3b4cecc 100644 --- a/NewsForm.Designer.cs +++ b/NewsForm.Designer.cs @@ -55,6 +55,8 @@ this.btnConfig = new System.Windows.Forms.Button(); this.chBuy = new System.Windows.Forms.CheckBox(); this.cbPriceCheck = new System.Windows.Forms.CheckBox(); + this.materialContextMenuStrip1 = new MaterialSkin.Controls.MaterialContextMenuStrip(); + this.chCodeName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); @@ -68,9 +70,10 @@ this.chId, this.chTime, this.chResT, + this.chResponseT, this.chReference, this.chTitle, - this.chResponseT, + this.chCodeName, this.chPriceS, this.chPriceLow, this.chPriceLowP, @@ -98,7 +101,7 @@ // // chTime // - this.chTime.Text = "시간"; + this.chTime.Text = "기사 시간"; // // chResT // @@ -299,6 +302,18 @@ this.cbPriceCheck.Text = "가격 체크"; this.cbPriceCheck.UseVisualStyleBackColor = true; // + // materialContextMenuStrip1 + // + this.materialContextMenuStrip1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255))))); + this.materialContextMenuStrip1.Depth = 0; + this.materialContextMenuStrip1.MouseState = MaterialSkin.MouseState.HOVER; + this.materialContextMenuStrip1.Name = "materialContextMenuStrip1"; + this.materialContextMenuStrip1.Size = new System.Drawing.Size(61, 4); + // + // chCodeName + // + this.chCodeName.Text = "종목명"; + // // NewsForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); @@ -356,6 +371,8 @@ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel2; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel3; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel4; + private System.Windows.Forms.ColumnHeader chCodeName; + private MaterialSkin.Controls.MaterialContextMenuStrip materialContextMenuStrip1; } } diff --git a/NewsForm.cs b/NewsForm.cs index bf133ff..df2e2c2 100644 --- a/NewsForm.cs +++ b/NewsForm.cs @@ -21,10 +21,12 @@ namespace NewsCrawler { class NEWS_ITEM { - public NEWS_ITEM(int iID, string strTitle, string strName, string strCode, DateTime NewsTime, DateTime ResTime, string strRef, string strURL, float fElapseT) + 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; @@ -88,9 +90,6 @@ namespace NewsCrawler //ExcelHandler m_Excel = null; - float m_fSupplyContractRate; - float m_fRevenueRate; - object m_lvListLock = new object(); @@ -109,8 +108,6 @@ namespace NewsCrawler m_Condition = new TextCondition(); m_CybosHelper = new CybosHelper(this); m_Crawler = new Crawler(this); - m_fSupplyContractRate = Config.GetSupplyContractRate(); - m_fRevenueRate = Config.GetRevenueRate(); Util.Log(Util.LOG_TYPE.VERVOSE, "========== NewsCrawler 실행 =========="); @@ -227,70 +224,59 @@ namespace NewsCrawler void ProcessSearchAndBuy(NEWS_ITEM NewsItem) { - CodeList.CODE_VALUE Code = null; - if(NewsItem.m_strCode == "") - Code = m_CodeList.SearchCode(NewsItem.m_strTitle); - else - Code = m_CodeList.GetCode(NewsItem.m_strCode); - - if(Code == null) - return; - - NewsItem.m_Code = Code; - 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, Code.ToString())); + 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((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, Code.ToString())); - else if((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, Code.ToString())); - else if((Code.m_enType&CodeList.CODE_TYPE.MANUAL) == CodeList.CODE_TYPE.MANUAL) + 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, Code.ToString())); + 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, Code), Code); + NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code), NewsItem.m_Code); ManualPopup.TopMost = true; ManualPopup.Show(); } } else { - BuyItem(Code); - Util.Log(Util.LOG_TYPE.POSITIVE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, Code.ToString())); + 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(Code.m_strCode, Code.m_strName); + 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, Code.ToString())); + 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, Code), Code); + NewsItem.m_strRef, NewsItem.m_strTitle, MatchResult.m_strKeyword, NewsItem.m_Code), NewsItem.m_Code); ManualPopup.TopMost = true; ManualPopup.Show(); } - m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName); + 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, Code.ToString())); + Util.Log(Util.LOG_TYPE.DEBUG, string.Format("[NOT_MATCHED] [{0}] {1}({2})", NewsItem.m_strRef, NewsItem.m_strTitle, NewsItem.m_Code.ToString())); break; } @@ -306,9 +292,9 @@ namespace NewsCrawler return; } - if(fRate < m_fSupplyContractRate) + if(fRate < Config.GetSupplyContractRate()) { - Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][공급계약체결] 매출액 대비율 낮음({0}, {1}% / {2}%)", strCodeName, fRate, m_fSupplyContractRate)); + Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][공급계약체결] 매출액 대비율 낮음({0}, {1}% / {2}%)", strCodeName, fRate, Config.GetSupplyContractRate())); return; } @@ -351,9 +337,9 @@ namespace NewsCrawler return; } - if (fRate < m_fRevenueRate) + if (fRate < Config.GetRevenueRate()) { - Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][영업실적] 당기순이익률 낮음({0}, {1}% / {2}%)", strCodeName, fRate, m_fRevenueRate)); + Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][영업실적] 당기순이익률 낮음({0}, {1}% / {2}%)", strCodeName, fRate, Config.GetRevenueRate())); return; } @@ -426,16 +412,43 @@ namespace NewsCrawler m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName); } - public void OnSupplyContractRateChanged(float fRate) + public void OnReceivedPatent(string strCodeName) { - m_fSupplyContractRate = fRate; - Config.SetSupplyContractRate(fRate); - } + CodeList.CODE_VALUE Code = m_CodeList.GetCodeByName(strCodeName); + if(Code == null) + { + Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("[DartAPI][특허권취득] 종목을 찾을 수 없음({0})", strCodeName)); + return; + } - public void OnRevenueRateChanged(float fRate) - { - m_fRevenueRate = fRate; - Config.SetRevenueRate(fRate); + 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) @@ -462,16 +475,27 @@ namespace NewsCrawler int iID = lvList.Items.Count+1; + CodeList.CODE_VALUE Code = null; if(bInitial == false) - ProcessSearchAndBuy(new NEWS_ITEM(iID, strTitle, strName, strCode, time, ResTime, strRef, strURL, (float)dElapseT)); + { + 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, - string.Format("{0:n4} ms", dElapseT), + (Code != null) ? Code.m_strName : "", "", "", "", @@ -530,7 +554,8 @@ namespace NewsCrawler { m_Crawler.ReadKIND(); m_Crawler.ReadDart(); - m_Crawler.ReadDartAPI(); + if(Config.CheckDartAPI()) + m_Crawler.ReadDartAPI(); m_Crawler.ReadEtoday(); //m_Crawler.ReadEtoday2(); m_Crawler.ReadAsiaE(); @@ -647,14 +672,14 @@ namespace NewsCrawler 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_strRef, Data.m_NewsItem.m_strTitle, Data.m_NewsItem.m_fElapseT, - // 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) + //{ + // 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_strRef, Data.m_NewsItem.m_strTitle, Data.m_NewsItem.m_fElapseT, + // 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; diff --git a/NewsForm.resx b/NewsForm.resx index 87285cc..54ee05a 100644 --- a/NewsForm.resx +++ b/NewsForm.resx @@ -120,6 +120,9 @@ 17, 17 + + 119, 17 + 96 diff --git a/configure/config.ini b/configure/config.ini index a118352..779eade 100644 --- a/configure/config.ini +++ b/configure/config.ini @@ -1,7 +1,13 @@ manual-price=100000 buy-price=100000 -supply-contract-rate=15 -revenue-rate=35.5 +ann-dart-api=True +ann-supply-contract=True +ann-supply-contract-rate=15.4 +ann-revenue=True +ann-revenue-rate=35.5 +ann-rights-issue=True +ann-patent=True +ann-patent-search-string=(미국|중국) account=335261568 sub-account=10 dart-api-key1=840943e5370eb9037057beab35f4468fa9a6ce5c