顯示具有 投機技術 標籤的文章。 顯示所有文章
顯示具有 投機技術 標籤的文章。 顯示所有文章

2026年4月15日 星期三

Market Microstructure in Practice

 

Market Microstructure in Practice(Charles-Albert Lehalle & Sophie Laruelle)

                     "Market Microstructure in Practice"是本結合研究與業界日常監控經驗的作品,一方面能為我們提供理解現代金融市場運作機制,執行成本建模及風險控制的鑰匙,另一方面也是我們前面基於高頻交易,訂單流知識的相關閱讀延伸.兩位作者是歐洲人,書中的舉例也多以歐洲的交易所為主.

                      為什麼要談"市場微結構"(Market Microstructure)?首先,它是價格形成的核心,市場微結構部分研究的重心在理解"價格形成過程"(Price Formation Process, PFP).價格形成是資本主義的核心,透過交易者間的買賣平衡供給與需求.形成反映資產價值的公允價格."價格形成過程"主要由"資訊"驅動,但裡頭卻存在一個"資訊悖論",理論上更多的透明資訊有助於公平價格形成,但實務上個別投資者卻擔心"資訊洩漏",有人會搶先獲得訊息,搶先交易,或因此產生過度的市場衝擊.而微結構研究讓交易者能透過量化數據,比如買賣差價,波動性,訂單簿深度來衡量並獲取真實的流動性,與它的動因.

2026年3月9日 星期一

Trading Order Flow: Understanding & Profiting From Market Generated Information As It Occurs

 

Trading Order Flow: Understanding & Profiting From Market Generated Information As It Occurs(Michael Valtos)

                       前面看"算法與高頻交易"量化的書籍時,其中分析主體是運用到Order Book的資料流作分析的基礎,從當下的觀點,不是什麼太新的東西,一切的概念源自一些從事當沖交易者看盤時的感受所觀察到的一種數據變化,但將感受化作能以數據處理,卻是近年的事情."Trading Order Flow"簡單翻譯是"訂單流交易",也是從這個上頭衍生而來.

                        所謂的Order Book就是我們在看盤軟體上,某檔商品的即時掛單與成交的交易數據狀態,最常見到的就是五檔報價表,通常它會包含兩個主要對稱的Column,左邊是委買,右邊是委賣,兩個Column各列出最佳的五檔報價,與相關的掛單量.隨著撮合交易的變化,這些報價的價量隨時都會變化,每一筆交易撮合成為一個tick,會產生成交量,與成交價.這個就是Order Book數據變化的狀態.平常沒真正看過盤的人,或者不是從事短線交易的人可能沒想過一個問題,比如委買最佳五檔掛價是95,94,93,92,91,委賣最佳五檔掛價是96,97,98,99,100.然後最新一個tick撮合成交價是96,成交量是3單位時,難道不曾懷疑,既然買方願意買進的最高出價95,賣方願意賣出的最低出價96,兩者有價差1元,怎麼說都不能撮合兩者交易成功吧,也就是説這種五檔掛單可以看出雙方其實應該不能成交,但此時明明就有那成交tick的96元 3單位,那這是怎麼產生的?

2026年2月12日 星期四

算法和高頻交易

 


算法和高頻交易(Algorithmic and High-Frequency Trading(Álvaro Cartea  &  Sebastian Jaimungal  &José Penalva)

                       "高頻交易"(High-Frequency Trading, HFT) 是個奇特領域,它雖是金融交易的一小部分,但現實面純商學院畢業者鮮有人涉入,主因是看不懂,主流描繪方式是用數學語言,缺少通俗化用語在大眾間傳播,只有商管學院基本程度的微積分與統計學在這領域是不夠用的,學校裡也只有提供給專門的研究生課程才有機會接觸,國內出版目前完全沒有這個主題的中文書寫."算法與高頻交易"是個簡中譯本,書籍實際雖只涉及這領域的某一部分主題,但或者能對此領域有興趣者提供某種理解的開端.

                     高頻交易 (是一種利用極致的硬體速度與精密演算法,在微秒(百萬分之一秒,μs)等級內執行大量訂單的交易形式.它與一般交易最大的不同在於,一般交易者關注的是資產的"趨勢"與"基本面",試圖預測未來的漲跌.而高頻交易者則是在尋找市場的"微觀失衡"與"機率優勢".對高頻交易而言,利潤並不是來自長期持有的價差,而是來自於"極高勝率,極小利潤,極多次數"的累積. 這種交易模式的主要參與者經常是擁有強大技術儲備的專業機構,如造市商 (Market Makers))與量化避險基金.而他們之所採用高頻交易主要基於三種理由.第一個理由是賺取極短瞬間買賣之間的價差.交易者透過同時掛出買單與賣單,為市場提供流動性並以此獲利.第二個理由則是藉由延遲套利 (Latency Arbitrage)來取利.這種套利是利用不同交易所間微小的價格更新時差,搶先捕捉失效的報價.第三個理由則是為了優化交易(Execution Optimization).大型機構將巨量訂單拆解成無數小單,藉以隱藏交易企圖,利用背景雜訊的遮蔽以減少市場衝擊成本.所以本質上,高頻交易是將交易行為從"投資行為"轉化為一種"技術競賽"與"數據統計工程",它也有一種隱藏的假設,就是效率假說在極短的時間內可能不存在,而高頻交易就是利用這種瞬間失衡後又瞬間復原的間隙中取利.

2024年8月17日 星期六

市場的預兆:剖析股債動態、熱錢走向,揭露未來十年必勝的投資組合

 

市場的預兆:剖析股債動態、熱錢走向,揭露未來十年必勝的投資組合(  How to Listen When Markets Speak: Risks, Myths, and Investment Opportunities in a Radically Reshaped Economy,  Lawrence G. McDonald &.  James Patrick Robinson) 

          這本"市場的預兆"先是分不清是該列在"投資技術"類或是"經濟觀點"類,後來想想兩者互為因果,列哪裡也就沒那麼重要了.那這本書說的是什麼主題呢?簡單說就說作者認為自1990年代柏林圍牆倒塌之後,全球形成的大範圍通縮經濟環境經過了30年的發展.已經開始轉變為大範圍通脹的結構.在這種狀態下,過去是投資主流的成長股勢頭將轉弱,取而代之的將是價值股為基本的傳統能源股及因為新能源開發而發展向上的開採大宗物資礦業與稀土等產業,這是新的投資趨勢的轉變.

          那為何會有這樣的經濟結構背景的完全轉折呢?接著就將作者的邏輯,思維與觀察路徑做簡單的融合敘述.作者認為自1990年代起大環因爲在鐵幕被打破後,由美國一國獨大所形成的全球單極狀態已經結束,而正式邁入了一個新的多極化世界.單極化的消失產生了一個新的經濟環境,與不同的國際局勢與關係.原先在單極狀態的世界裡,是由美國來決定全球的國際秩序,美軍的航母,戰機在全球巡察,同時控制主要爭端的邊界安全,強大的單極力量保障了某種單一的安全秩序,降低了貿易與航運的風險.同時美國開始在政策上讓一些友邦進行基礎製造業的發展,產生了許多以外貿為主體的進口替代國.這使得一些國家,主要是東亞國家進入了低階製造業的領域,靠著生產商品,外銷美國來創造自身國家與人民財富.這些新興貿易出口國的人民收入增加時,也讓國家賺取了大量的美元,形成外匯同時也因為財富大增而讓國內資產需求得到爆炸性成長,相對的,各國在對美國貿易上的獲利為了不影響本國貨幣升值阻礙貿易成長持續,只好將賺得的美元變成長期留存在美國的貨幣資產,通常是以轉購買美國公債的方式留下,因此各國都累積了大量的美元資產,加上當時的美國與產油國家達成協議,以美元做為購買原由主要的油元,及多重的美元需求,致使強勢的美元成為當時的貨幣現象,加上各國樂於維持弱勢本幣來創造出口,而因此去化幫助了美國的藉由寬鬆貨幣政策融通財政赤字的壓力,而東亞與東歐提供低廉的勞動力與便宜的製成品,使得全球大多數地區普遍呈現因為通縮的擴散,而有大量低廉便宜的資金來進追逐實體資產,甚至更進一步追逐非實體性,這些資金進入主要的金融市場,房地產市場,使得股市,房市興興向榮,這便是單極世界的一個長期走勢及其循環狀態.於是美國就成了這樣的一種經濟形貌,強勢美元,通縮,利率偏低,貨幣寬鬆,當國內遭遇流動性風險則以QE,即所謂的量化寬鬆來解決問題,雖然因此有著大量外貿赤字,且低階製造業幾乎全數消失,單也因此讓金融業發達,在科技發展下,科技股得以成爲主流.而這種長期低利環境下,企業評估成長的收益現金價值的折現值會被高估,因此成長股在股市評價上會被賦予較高的現在,與未來本益比,也就是說在通縮環境下,投資人願意用較高的價格來買股,因為低利所評估的未來價值會更高,於是在這種樂觀氛圍下,金融業有機會獲得大量低利資金去投資所謂的未來成長,這讓傳統固守利差的金融業思維有了形變,樂於追逐投資勝於放貸,因此形成了金融業在投資上獨大的現象,而科技業也只有那些能夠享受股權化利益的管理高層能夠幅提高收入,但這種金融興興向榮對比大量因製造業外移而失去工作機會的低階工人,形成了社會的不平等現象的分歧狀態,也就是說單極的世界裡,美國在外固然威風凜凜,但也因此產生國內的偏態,包括製造業幾乎消失,生產外包,只能做低階生產綫上工作的人大比率找不到工作,金融業獨大,低利讓靠投機投資為生的人能較一般人容易致富成功,在美元需求無虞下,聯準會能更大膽的以超寬鬆的政策來應對景氣,融通財政,國家債務快速累積,量化寬鬆至美元數量與美債同步浮濫.在資金狂潮下,先是大多數的成長股,主要集中在科技類,網路類的股票上被賦予了較高的價格期待,股價持續維持較其它類股更高的本益比,資金狂潮下一些新興的投機商品比如虛擬貨幣也被吹捧衝高,大量的資金進入此領域,與新起的被動金融商品ETF上,形成了兩大投機領域的飆升現象.

           單極狀態改變之下會有甚麼轉變呢?改善外貿赤字,要提升自己的工業生產,讓製造業重回美國,首先便是原先的貿易優勢國要購買美國公債的錢將會開始減少,畢竟外貿盈餘會逐漸減少,美國的寬鬆貨幣政策供給將無法持續獲得這些外國對美元需求的去化,發行的公債價格避走低,也就是利率將會走高,其次,美國工人的工資遠高於進口替代,其三是因為美國成了主要的石油出口國,不再需要外購石油,也就沒有美元成為唯一全球通用貨幣角色需要,美元的需要再次減少,加上美國在過往的30年單極歲月裡,經常性的以金融懲罰方式來修理不聽話的國家,致使一些主要國家未來必定降低對於美元持有的依賴,因為他們不想再被一個不確定的因素給困擾,比如俄羅斯,中國,沙烏地,伊朗這些國家.不論是輸出能源大國,或是對美出超大國,他們必然會降低對於美元的過度需要.這些因素都使得聯準會美元寬鬆的政策將不再像過去那樣得到其它國家無條件或不得不的支持,因為需要,而形成強勢美元的必然因素.在需求減少下,一個需求弱勢的美元可能是未來非單極世界裡可以預期的存在,但是美國長年透過央行轉計貨幣的方式來掩護赤字預算的手段,必不可能在短期間取締美國公債,如此下來,為了去化過度發行的美國公債供給,必然需要尋找新的客戶,這只能寄情於美國國內自身的需求,而為了吸引國內投資人對於美國公債的需要,是必須要調整新發債券的利率,因此調高利率是必然的走向,甚至必須經常用調動此項利率的工具去進行調節,也就是說去單極化之下,勞動成本上升,終端產品價格因此提高,這些條件都形成通膨必然上升的推動力,加上國際能源的運輸,安全需要成本因為國際間的關係緊張就可能上升,加上非洲,東南亞許多國家的經濟已經開始脫離貧窮,未來對於傳統能源的需要都會使得國際的能源價格會逐漸上漲,美國又因自身的生產價格成本提高而不得不讓環境變成了一個通膨為常態的狀態,利率必然會比過去為高,因此資金成本必然也跟著水漲船高,所以維持一個通鵬環境的升息環境是必然的,而利率會受制於美國國債債務規模太大,利息負擔過重,必然會同步採取金融抑制手段,讓利率水準或變動略低於通膨,這樣既可避免利率拉升太高產生過度的國家利息債務壓力,一方面可以藉由通膨來消除債務的負擔,但是抬高的利率對於金融業的投資數額必然是有所抑制的,畢竟如果購買公債就能有5%的利息收入,人們將不太可能再隨意亂冒險去投資一些不確定又價格被高估的成長股或是未來不確定性高,週期波動大的科技股.而在這種環境下,作者們認為最好的投資標的便是一些價格被低估的價值股.而當下最具隱藏價值又不為大眾所見的便是能源股,而這樣的判斷固然有著對於未來能源需要的評估做依據,作者推論於此的一個依據便是1990年單極世界形成以前的冷戰時期的狀態.而今一個新的冷戰又隱隱成形,一方面新冠疫情改變了世界原先運作的慣常模式,俄烏戰爭又令能源價格抬高,而美國又想重組製造業而開始對中國,後續也必然回對其它的東亞國家施以更嚴厲的貿易壁壘或懲罰,這些都可能抬高物價,而地緣政治風險的提高,也形成了軍事上對商業活動的嚇阻,因為潛在的國際安全不穩問題有助提升能源,特別是原油的價格上升的動力,加速能源價格上漲的隱憂.而對1980年代之前的高油價通膨環境的回憶便進入了作者們的心中,當時確實是另一個非單極的二元對抗環境,美元是油元結算的唯一,美國當時能利用其需要,而這使得新的華盛頓共識的產生,那就是膨脹,貿易戰,製造業回流美國,並且以赤字來支應以上所需要的支出.

            也就是說作者論述的邏輯就是在1990之後,由中國與東歐大量廉價勞動力與低價產品所提供的通縮力道主導了過去30年的全球經濟環境與各國的政策調整的基調.但這種通縮效應已經因為美國退下了單極帝國王位寶座後,進入了一種新的經濟環境.那就是未來將是通膨,弱勢美元,利率高企為主要的常態經濟環境,而作者認為這種新的通膨環境,特別是當物價指數高於3%以上的通膨環境下,價值股的成長性將高於成長股,因此2020後在這種新的大環境下,投資人可以將目光轉向價值股.而這種新環境下,最可以提供直觀獲利的價值股有兩大類,一是傳統的原油能源開發相關企業的企業,另一為綠色能源為主體所衍生的新的大宗物資開採相關的企業,這些大宗物資包括發電衍生的銅,鋁,,核電相關的鈾,風電攸關的鋼鐵,鐵,太陽能相關矽與相關其他稀土.這是此本書關於投資的重點之一,另外一個本書相關投資議題的重點在於波動率的影響.這個波動率的影響主要探討在ETF的被動式基金,以及這些年相當流行受追捧,但作者認爲實際上沒有太多用途用意義的虛擬貨幣領域.這是因為在過去通縮的環境下,低利創造了資金氾濫,這種被動式的基金會因為資金流入創造出結構占比上原先排名靠前的股票會因為價格上升而被動式買入更多而價格上升波動更多,因為被動式基金是由比率自動調整連動,所以波動會提高.因此當資金行情受到了高利,通膨的環境下,如果有任何的弱勢修正,反向地的走勢波動可能也會因為被動式基金的特色而產生劇烈的影響.同樣的狀態也顯示在虛擬貨幣的市場中,這兩大領域的商品都明顯的有價格自我強化的現像隱藏在它的構成結構中,一旦自我強化的作用被點燃觸發,這些商品的價格波動會升至極大,可能會觸發難難以想像的價格狀態,這是在新的通膨環境下,投資人必須要留心的一種可能的被動式結構上的負面效應,也就是隨著被動式資產波動率的提高,黑天鵝事件被誘發的機率將比想像的稍高一點,而這種ETF結構化商品以及虛擬貨幣數量可以說在21世紀成長的非常快速,但它對於市場可能的影響卻尚未經歷考驗,是否可能因為連動性引發高波動性事件觸發某種危機臨界便是這個作者在探討環境結構轉變下所附帶想到市場系統的弱點問題,特別是當所謂的ETF的主要構成企業股票都是成長股類型的企業時,一旦市場修正,是否可能引起更大的結構性下挫問題,值得去探索.

            這本書的內容不少,探索的諸多問題稍嫌發散,我這裡是以自己的方式重整簡化說出了整書論述的核心.基本上因為書的內容有部分需要對於金融商品的構成,金融風險計算有點基礎的人才能理解,比如本書用了選擇權中的希臘字母delta,beta,gamma,vega等指標的變動來解釋投資波動狀態的自我強化作用,不理解這些純粹金融商品內容的人可能閱讀到這些內容時會卡關,加上需要一些根本的經濟變化的時態理解,所以這雖是一本看起來通俗易懂的大眾讀物,但實際上它是屬於需要有比對普通金融常識稍微多一點理解的才適合來閱讀.當然,你也可以不用理解那些,直接看我開頭列出的兩個重點即可,至於這種對於整體經濟與金融環境變遷的預言到底對不對,要不要信..?個人以為或許有某部分價值股未來確實可能形成這樣的趨勢走向,但應該也不用過度以二分法的態度就此認為成長股不行,而只投資價值股,畢竟個別企業的環境與受到的影響還是會有若干差異的,也因此會有不同的走向可能.以上.


2023年3月7日 星期二

精通機器學習|使用Scikit-Learn, Keras與TensorFlow +精通機器學習|使用Python

 




精通機器學習|使用Scikit-Learn, Keras與TensorFlow+精通機器學習|使用Python(Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow: Concepts, Tools, and Techniques to Build Intelligent Systems,Aurélien Géron +  Introduction to Machine Learning with Python,Sarah Guido & Andreas C. Mueller)

      雖然這邊列的是兩本書,原本重心在看第一本Scikit-learn,Keras,Tensorflow,畢竟我是基於在金融投機深度學習程式交易化上需求才學這個,目的是實作,但發現它程式碼技術實質內容不多,多數時是理論程序的漫談,並不能親自改為能執行的程式碼,所以有些乏味.所以還是把重心放在第二本機器學習的python實踐上,其中關於Scikit-Learn,Keras,Tensorflow的基礎基本在後面那本中沒有細談,這在前面那本中卻是重點,需要先經過這本的速覽才比較無礙的進入後一本,而後一本專攻python程式碼,內容集中在Scikit-learn,所以要用得對它的基本常識與用法有所了解.第一本不愧是重要概念書籍,很多內容說得非常明白清楚,是一本值得花時間去看的工具觀念書,雖然它也有python程式碼,但是那個比較像是在舉例如何用的手冊型介紹,並沒有能讓人親自寫一遍程式碼的空間,而關於keras,tensorflow的程式碼實踐就另外找專攻實作的案例或書籍來跑了.以"精通機器學習|使用Python"來說本身介紹的scikit-learn是Python中對於經典機器學習框架的集大成者,在NumPy和SciPy之後,在TensorFlow之前,這本書和它介紹的scikit-learn框架和經典機器學習算法的理論非常值得一讀.

      其實這兩本拖延了很長時間,主要原因倒不是在內容,而是之前的電腦執行速度相對深度學習需要的功能已經太慢,執行花太久時間,人都搞得不耐煩,想換個電腦.但那時卡在一個尷尬間,30系列顯卡的機器功效不明,耳聞配置40系列顯卡的電腦要出了,所以選擇先等待,暫停了一段時間.畢竟我是要實作的,單看書可不行.新的13代i9的cpu加上4090的顯卡組成的電腦主要目標竟是去跑電玩,時代變換也夠大的.遙想以前在學校跑SAS,只有80X86的選項,慢的受不了,現在新的電腦若給只有文書需求的人,效能竟然都遠遠過剩.之所以提到SAS,是因為經過理解這裡的Scikit-Learn,我才發現其實這些都內容,以前都學過,而且時間竟然是在上個世紀,而且從現在的眼光來看,個人的碩士論文其實就是直一個深度學習的實證案例而已.

       當初的做法其實用今日的眼光看其實很簡單,先找定一些標籤企業,這些企業可能因為研發,或是財務上的因素,被分成為若干類,比如以研發高低為標籤定義為高技術或高行銷類企業,或是以財務狀態,如是否列入全額交割股來分為有發生財務危機或無財務危機的企業,反正就是先幫企業建立一個類別標籤,可分成2個以上的類別,再找出足夠的選取樣本企業的歷年財報或經營數據,比如發生全額交割事件前的5年所有歷年的財報與財務數據,每年選擇20個財務比例為特徵值(變數),用這20個變數去構建一個新模式,這個新的模式同時依時間與變數分別各自建立歷年的預測模式,如此便可以用一個未知類別的企業數據投入模式來預測它未來財務發生問題的可能能性.以前只知道這個叫做多變量分析,但其實這個模式就是一個融合了非監督模式與監督模式的個案.首先得握法便是透過component reduction的概念去處理,常用的方式如主成分分析,因素分析去對原資料處理,目的是將原本20個變數的資料轉換成為具相關程度高解釋力的幾個成份,或因素,如此便能將原先要處理20個變數(特徵值)的工程簡化成只要集中處理3~5個重要的成份或因素即可.然後再根據這些降階後的3到5個主成份與主因素去進行建構監督化學習模式,比如線性回歸,或是區別分析(Discriminant Analysis),找出模型的相關係數後,然後便能用新的某些企業財報測試資料去做模型的精確度處理,看看預測能力,只是這整個處理,我們以前就是在多變量分析裡學過的,當時還沒有所謂的機器學習這樣的名詞概念,更別說監督學習,非監督學習的分類.

        我把"精通機器學習|使用Python"使用的鳶尾花的例子,加上第二章classification與regression的分類問題一鍵入python程式碼值計去跑才突然想到這跟以前所學根本是同一個東西,只是被機器學習的新名詞搞得有點玄幻了,其實都是舊東西呀,後面的k-means,cluster,其實記憶裡真的都學過了,突然間程式碼似乎都變得容易理解了,因為當時學這個目的就是針對於將要寫作的論文,所以可能重心就放在理解為主上,且當時的環境似乎深度學習還是機器學習都是屬於發展上的停滯期,似乎要10多年後才再有了新的東西.如果說這本書在執行上有甚麼問題,那應該就ˋ老問題了,書的程式碼是以預設在linux或unix的環境中執行的,我們使用pc上的Juputer來跑python,會有一些因為版本與環境問題的錯誤出現,但這些都是要執行者自己去摸索體會並修改成符合自身電腦環境需求的形式,有時會花一點時間,這也是沒有辦法的事情.

        以前學多變量分析的時候,雖然也會碰到數學上的問題,但是當時多以理解它的作用為主,比如所謂的將20個變數降階成3~5的主成分或是因素,或是cluster,依我們的能力根本不可能從數學上說明清楚它的導入,只知道它是一種靠著旋轉坐標軸,加上水平垂直來平移坐標軸.讓原來的樣本空間更容易被看出存在某忠特別的分類區塊,或是靠著投影的方式將一個空間中的點轉一個面或一條線上的點的意思.現在學機器學習則是同一項課題中內容太多且雜亂,容易搞錯,且因為沒有自己創設的資料例子,單看書上舉的例子或按照它的程式碼自行跑一遍,還是多少點隔靴搔癢,差點意思,我比較喜歡用自己想做的案例實作,這樣的理解會比較深入,運用時也不會太心虛.


2021年10月21日 星期四

Python演算法交易

 

Python演算法交易(Python for Algorithmic Trading: From Idea to Cloud Deployment,Yves Hilpisch)

      Hiplisch的書好幾本都是關於用Python來處理金融相關問題的,有些是關於金融模型,另一些是衍生性商品的.而這一本"Python演算法交易"應該是其中單純將焦點聚集在金融交易上的,用最簡單的方式來說,這一本的內容是來協助有興趣者自行開發自動化演算交易系統而寫的.

      開發個人的自動化交易系統,也俗稱程式交易,已經不是新穎的東西,很多人都在做,市面上也有已經成套軟體專門提供給需要者使用,如Multicharts,TradeStation,WeathLab,或是MT等等,因此實際上一般人並沒有必要特地去學Python寫自己的交易系統,那樣太麻煩,畢竟MC,TS等都寫好了除了交易邏輯程式碼以外的東西,以如產生繪圖,圖表,產生回測報告,連接下單機,自動功能等等.一些想要學Python來開發交易系統的人必須先評估自我的需要,其實多數人是沒必要這樣做的,特別是如果你的交易系統就是傳統均線穿越,指標,動量交易,均值回歸等方式,那麼你只要買市面上已有的軟體即可,因為那樣只要隨軟體的需要學習它內建的程式語言即可,這些程式語言通常使以C#,或.Pascal或VBS轉變的Script語言為主,因為這些程式語言的功能與範圍被設計成控制在一定範圍與目標內,所以並不複雜,除錯簡單,有明確簡單的手冊能一目了然,且能快速上手,加上它已經幫使用者開發的功能,其實對程式交易者而言是能被半功倍的好物,並不需要對其排斥.

     即使是用演算法來替代傳統的指標做為程式交易的內在邏輯,以上所述的市售軟體一樣能夠達到功能上的要求.畢竟所謂的演算法沒有限定或獨特的定義範圍,也不存在普遍的意義,在某種程度上,它指的就是以特定形式的演算法為基礎,針對特定的金融投資工具進行交易,而所謂的演算法指的就是以特定順序進行一整套數學上,技術上的操作,以達到特定的目標,所以像簡單的迴歸,方程計算,那些阮堤還是夠用的,只是稍嫌麻煩,但與自行開發要還要設計旁支的許多東西相比,還是買現成的最快.而現在的問題是演算法被引進金融交易的東西越來越多,加上資訊領域中的機器學習與深度學習的發展在電腦運行功能的突破下有了大進展,所以使用以處理大數據為主體功能的軟體來發展新的自動化交易系統必然會有新的進展.這本"Python演算法交易"便是以此為目標將自行開發時需要理解或使用到的部分逐章解釋並以範圍說明.

     這書分成幾部分,首先它針對處理關於系統必須使用的數據型態與來源做處理,這些內容在其他的Python書上應該都有,主要是針對Numpy,Pandas的數據型態與List,Matrix資料處理的對應,並對資料的來源,如是來自外部串流,其他單位提供的資料如何連接,轉換成CSV檔,與建立資料庫進行說明,這些內容只要根據書上這些範圍裡的程式碼鍵入執行過一次,應該就能完全理解了.這幅息完畢之後,作者直接引進了向量回測,並後續以常見的均線穿越,指標追擊,與均值回歸為例做交易系統,個寫下它們的程式碼,並以這各自的系統為主,寫出每個系統的迴測類別.為為每個範例的程式碼都獨立存在,讀者在參照它的邏輯開發出自己的需求的同時,也能夠直接就在自己的系統上Import它們來使用,其實還有投機偷懶的效果.最重要的運用機器學習與深度學習打造程式交易邏輯與回測系統的部分,書上列出了簡單的迴歸,羅吉式迴歸(logistic regression),複回歸還有分類(classification)問題並嘗試以Sklearn,Tensorflow,Keras等深度學習套件來開發預測系統,這部分內容雖不多,但已經足夠提供一個學習的開口,讓初次接觸者知道運用深度學習機器學習在交易上是怎麼一回事.最後作者引入了Oanda,FXSM等現存的交易商提供的看盤下單軟體,嘗試用Python引入這些存在的模組進行下單程式碼的設計,最終與回測系統共同組合成自己開發的自動交易系統.就架構來說已經很完備,但是個別主題的內容太少,有時甚至簡略,想要照本書程式碼一個個案例執行者還要留心有部分的外界連接已經與書中不同,必須自行改動才能讓程式碼執行完全,可能會引起一些無法操作的問題,但整體而言這本書對於有心開發自動交易者算是提供了一個還不錯的概念與架構的書籍,只是不夠詳盡,讀者必須自行研展腦補..

    從閱讀與實際執行本書上的範例程式,我以為有幾個可以有效運用的範圍可以做為有用的延伸,首先是這是本奠基於Python的架構,大數據與其延伸的機器學習與深度學習套件是它必然的重心,我們正可以運用此做為改善過往傳統程式交易方面的缺憾,首先我們以第七章的一個TickSever的程式為例:.

 

import zmq
import math
import time
import random
context = zmq.Context()
socket = context.socket(zmq.PUB)
#socket.bind('tcp://0.0.0.0:5555')(for linux)
scoket.bind('tcp://127.0.0.1:5555') #(for windows)
class InstrumentPrice(object): def __init__(self): self.symbol = 'SYMBOL' self.t = time.time() self.value = 100. self.sigma = 0.4 self.r = 0.01 def simulate_value(self): ''' Generates a new, random stock price. t = time.time() dt = (t - self.t) / (252 * 8 * 60 * 60) dt *= 500 self.t = t self.value *= math.exp((self.r - 0.5 * self.sigma ** 2) * dt + self.sigma * math.sqrt(dt) * random.gauss(0, 1)) return self.value ip = InstrumentPrice() while True: msg = '{} {:.2f}'.format(ip.symbol, ip.simulate_value()) print(msg) socket.send_string(msg) time.sleep(random.random() * 2) 

    這段程式碼很短,主要的功能是將金融商品價格採取模擬布朗運動的尤拉公式的方式來產生隨機的價格資料,程式根據隨機選取的間隔時間,可能是微秒,或幾秒鐘,再根據公式產生成交的tick價格資料,並且將此tcik資料以socket的方式傳播出去.做為對應的socket接收方程式,另有一個TickClietn程式.透過這兩個程式傳播與接收關係就形成模擬一個簡單的交易所搓合交易的server,與客戶端接收交易資訊的電腦間的關係.讀者如果只是單純將這段程式碼複製執行,可能就錯過了它的更大用途,特別是對於期指當沖者來說.要知道這是模擬一個tick資料伺服器,只要不中斷,它能持續不斷的一直生出成交價格,這特性正適合提供線上演算法的需要,畢竟傳統的程式交易系統需要測試時都是採取離線算法,用歷史資料去測試,基本上沒有即時的線上資料可以使用,即使採取真的即時價格資訊做模擬交易,它的可執行次數也是有限的,所以這個TickServer程式是一非常好的工具.以台期指為例,我們可以在此程式碼加上模擬起訖時間限制,即設定從早上的8:45到下午13:45,形成一個交易日的所有成交價格tick與它的成交時間.這樣就有了一個能夠供做測試的模擬日內成交資料,因為有了所有的tick自然可以根據時間的分隔自自動的歸類出1分鐘線,5分鐘線,乃至小時線,所以不論你的資料時間結構需求時怎樣的,tickserver模擬出的資料都能提供使用,而設計者也能以此隨時產生的模擬資料進行線上運算交易系統測試,而不是只用歷史資料.而既然能夠模擬出某一天的tick資料,我們就能模擬產生1000個,甚至100000個交易日的不同的日內tick資料,產生不同的日內資料,這樣就能以大數據的型態來做當沖系統測試.畢竟一年只有約240~250個交易日,30年的實際日資料不過約7500個交易日而已,TickServer模擬資料能夠突破這個限制,也許能有1萬個交易日資料提供測試,而結合了Python在串流函式上的支援,比起那些市售軟體彈性相對大,能夠結合的資源與做法就更多了,這是一個相對有利的發展,而本書在最終章的自動交易系統上也引用了以Oanda為範例來說明,如何發展出一個完全以雲端執行的字交易系統,就是將演算法交易系統放到遠端的伺服器中自動執行,然後透過日記達到記錄與監控的功能,實施真正的自動化交易,這部分內容雖然不多,卻是整本書希望讀者實作後最終能達成的目標.

   至於最終是否要採用Python發展出自己的交易系統,還是得依需求範圍的設定來決定,畢竟市售的軟體早已能滿足一般交易策略的需求,而使用Python是因為它能與機器學習深度學習套件連結,加上強大的數學,科學運算套件,若你的系統沒有要用到這些,那麼自然不需要多一舉放棄別人已經幫你設計好的輕便簡單的MC,WB,MT,TS等現成軟體,重複無用之功.至於那些交易邏輯與系統可能會涉及到使用這些套件,依個人的判斷,大概是牽涉的系統使用的規則用清楚,明顯,能明確定義的越不需要重複發展,使用現成軟體即可.而交易邏輯比較模寧兩可或說難以絕對規則界定的,模糊的則使用這些套件的機率會高些,這裡的模糊得意思用中文表達較不精確,應該是指Fuzzy這個意思,而這個詞很早就被引入了資訊領域,應該才是使用這工具的原因,亦即必須有真的將模糊系統,其實是複雜度高過去無法量化的交易系統才考慮使用這項工具,而不是純粹為追逐流行而使用.

   使用本書時會遇到許多問題,主要都是基於軟體套件發展快速變化的版本問題,致使許多書中的程式碼並不依定能完全按照設想的狀態成功執行,會產生許多錯誤訊息,在使用tensorflow,keras,Oanda,FXCM都遭遇過這樣的狀態,這只能透過google去網上找尋碰到相同問題的人測試出的結果來改變套件的版本,這是用python常遇的問題.所幸作者已經書裡的程式碼都公開在網上,不必真的逐字鍵入,省了麻煩,唯一要留心的是他是在linux下作業,要搬到windows上用Anaconda中的Syider使用有部分是使用者自己知道要改寫的,這就是個人經驗了.除這這些使用上的問題外,個人認為這本對於想自行開發交易系統者還是值得買來一讀的,儘管它尚不夠詳細完備,但已夠讓人折騰許久了.以上.


2021年8月29日 星期日

用Python預測玩轉股市高手精解+Python數據可視化之matplotlib實踐

 

用Python預測玩轉股市高手精解+Python數據可視化之matplotlib實踐(胡書敏,劉大成)

   基本上這種工具書是寫不了心得,因為你必須真的用了才行.所以這裡就以兩個實作替代,並提示一些在實作上遇到的關鍵問題所在..實作一的目標是建立一個台灣股市加權指數"每5秒委託成交統計"資料庫."每5秒委託成交統計"的日資料可以在證交所網站找到https://www.twse.com.tw/zh/page/trading/exchange/MI_5MINS.html,它是一張日報表,交易所提供這項資料是從2004/10/15開始,而我們的目標就是要將自2004/10/15到今天為止所有的資料都透過爬蟲與下載的方式抓回到自己的電腦上,並將其建立成資料庫.

   首先須釐清資料庫可能的大小,交易所在2004/10/15開始提供此項資料時,是以"每分鐘委託成交統計"開始,所以每日的資料從9:00到13:30共270分鐘,所以有271筆,但到了2011/1/16開始轉為""每15秒委託成交統計,所以單日的資料筆數增到1081筆,2014/02/23後改為每10秒,日資料筆變為1622筆,到了2015/1/1起正式改為每5秒揭露,日資料筆增為3241筆,若一年以240個交易日為平均,一年將會有78萬筆資料,所以採用資料庫是比較有利的蒐集資料的做法,因為交易所的資料只提供html與csv兩種形式,在處理單一交易日上或許簡便,要整體拿來用就麻煩多了.

   回到證交所網站"每5秒委託成交統計"頁面來看,它只提供使用者以下拉式選單變更日期來進行查詢,並以左上邊提供了"HTML"與"CSV下載"將資料下載回自己電腦,但是若想用人力在電腦上一張張下載回來這也未免太累,這種重複性的機械動作,使用程式代勞是較好的.以2021/08/31為例,看一下html,它的網址是(https://www.twse.com.tw/exchangeReport/MI_5MINS?response=html&date=20210831,你可以在該頁面上按滑鼠右鍵,選擇另存新檔,這樣資料就下載完成,或是將上述網址中的"?response=html"這這段中的html改為csv,即"https://www.twse.com.tw/exchangeReport/MI_5MINS?response=csv&date=20210831",就能下載該資料的csv檔,既然此我們何不透過利用程式調整這網址的date=20210831從date=2004/10/15一路到今天,這樣便能將所有交易日的csv檔給下載回來.python程式簡單結構如下:

from selenium import webdriver

from time import sleep

urltemp = 'https://www.twse.com.tw/exchangeReport/MI_5MINS?response=csv&date='

browser = webdriver.Chrome()

browser.maximize_window()

sleep(30)

yeartemp=""

monthtemp=""

daytemp=""

downtemp=""

url="" spa=" "

for i in range(2004,2022):

 for j in range(1,13):

  for k in range(1,32):

    product = i * j * k

    yeartemp=str(i)

    monthtemp=str(j)

    daytemp=str(k)

    if monthtemp=="1" : monthtemp="01"

    if monthtemp=="2" : monthtemp="02"

    if monthtemp=="3" : monthtemp="03"

    if monthtemp=="4" : monthtemp="04"

    if monthtemp=="5" : monthtemp="05"

    if monthtemp=="6" : monthtemp="06"

    if monthtemp=="7" : monthtemp="07"

    if monthtemp=="8" : monthtemp="08"

    if monthtemp=="9" : monthtemp="09"

    if daytemp=="1" : daytemp="01"

    if daytemp=="2" : daytemp="02"

    if daytemp=="3" : daytemp="03" 

    if daytemp=="4" : daytemp="04"

    if daytemp=="5" : daytemp="05"

    if daytemp=="6" : daytemp="06"

    if daytemp=="7" : daytemp="07"

    if daytemp=="8" : daytemp="08"

    if daytemp=="9" : daytemp="09"

    downtemp= yeartemp+monthtemp+daytemp

    url=urltemp+downtemp

    print("%2s" % (url), end=" ")

    browser.get(url)

    sleep(4) .

   這裡有一個小問題,就是有些日期非交易日,無資料,我在這裡並沒有處理,這是因為無資料的日期,證交所網站會下載的是執行此程式當天的csv,並不會出現任何其他訊息,所以乾脆忽略,因為這程式的目的只是要蒐集所有的"委託成交統計"csv檔,不需要計較輸出的型態.執行完畢後我們便能拿到乞今為止所有委託成交統計的csv,但這只是一堆雜亂無序的csv,要維護它太麻煩,所以我們將它全部匯入資料庫中.

   匯入資料庫,首先須選用哪種資料庫,可以是MS-SQL,可以是MYSQL,我們這裡使用的是Sqlite.其次檢視一下單一交易日的csv檔,會發現它有個煩人的問題,每張csv表有日期的表頭,加上有一個9列的表尾附註,而這是我們不要放進資料庫裡的東西.同陽的困擾,若我們採用手動匯入csv檔到資料庫未免太累,想想240交易日*17年,要匯入3360個csv檔,而且每一張csv你還得修正表頭與表尾,那不如就寫段程式讀入,程式碼如下:

import os.path

import pandas as pd

import sqlite3 conn = sqlite3.connect('twse5minall.sqlite') # 建立資料庫連線

cursor = conn.cursor() # 建立 cursor 物件 # 建立一個資料表

sqlstr='CREATE TABLE IF NOT EXISTS table1 \ ("num" INTEGER PRIMARY KEY NOT NULL ,"tel" TEXT)'

cursor.execute(sqlstr)

yeartemp=""

monthtemp=""

daytemp=""

downtemp=""

url=""

spa=" "

temp=""

sqlstr=""

mintemphead="c:/users/user/downloads/MI_5MINS_"

mintemptail='.csv'

total=0

dayno=0

for i in range(2004,2022):

 for j in range(1,13):

  for k in range(1,32):

   product = i * j * k

   #print("%d*%d*%d=%-2d " % (i, j, k, product), end="")

   yeartemp=str(i)

   monthtemp=str(j)

    daytemp=str(k)

    if monthtemp=="1" : monthtemp="01"

    if monthtemp=="2" : monthtemp="02"

    if monthtemp=="3" : monthtemp="03"

    if monthtemp=="4" : monthtemp="04"

    if monthtemp=="5" : monthtemp="05"

    if monthtemp=="6" : monthtemp="06"

    if monthtemp=="7" : monthtemp="07"

    if monthtemp=="8" : monthtemp="08"

    if monthtemp=="9" : monthtemp="09"

    if daytemp=="1" : daytemp="01"

    if daytemp=="2" : daytemp="02"

    if daytemp=="3" : daytemp="03"

    if daytemp=="4" : daytemp="04"

    if daytemp=="5" : daytemp="05"

    if daytemp=="6" : daytemp="06"

    if daytemp=="7" : daytemp="07"

    if daytemp=="8" : daytemp="08"

    if daytemp=="9" : daytemp="09"

    temp=yeartemp+'/'+monthtemp+'/'+daytemp

    downtemp= yeartemp+monthtemp+daytemp

    total=int(downtemp)

    #print(total)

    if total>20151001 : dayno=3242

    if (total<20150101 and="" total="">20140421) : dayno=1622

    if (total<20140224 and="" total="">20110930) : dayno=1082

    if (total<20110117 and="" total="">20071128) : dayno=272

    #print(dayno)

    url=mintemphead+downtemp+mintemptail

    print("%2s" % (url), end=" ")

     if os.path.exists(url):

      df=pd.read_csv(url,encoding='big5',parse_dates=True)

      m=1

      print(temp+"檔案存在")

      print(str(total)+"--"+str(dayno))

      while m<dayno:

        a=df.index[m][0]

        b=df.index[m][1]

        c=df.index[m][2]

        d=df.index[m][3]

        e=df.index[m][4]

        f=df.index[m][5]

        g=df.index[m][6]

        h=df.index[m][7]

        sqlstr="insert into table1 values ('{}','{}','{}','{}','{}','{}','{}','{}','{}')".format(temp,a,b,c,d,e,f,g,h)

        cursor.execute(sqlstr)

        conn.commit() # 主動更新

        m=m+1

    else:

       print(temp+"檔案不存在", end=" ")

conn.close() :

    這程式就分別了沒有交易日的資料就不處理的問題,其中留心原證交所的日資料是8欄,我們寫入資料庫時增加了一欄日期欄,成了9欄.但是光是如此只是將原資料insert資料庫是不夠的,因為原始資料是累積資料即 09:03:00的資料是從09:00:00到09:03:00的累積,而我們需要的是一單位內的資料,從早期每分鐘的增量,到近期每5秒的增量,不是累積量.所以我又寫如下的程式碼:

import os.path

import pandas as pd

import sqlite3

import locale

locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')

conn = sqlite3.connect('twse5min2011test.sqlite') # 建立資料庫連線

sqlstr="SELECT * from table1 '"

cursor=conn.execute(sqlstr) #cursor.commit()

temp=''

temp1=''

daytemp=''

daytemp1=''

dayint=0

tempchtime=''

rows=cursor.fetchall

i=0

a=0.0

b=0.0

c=0.0

d=0.0

e=0.0

f=0.0

g=0.0

tempa=0

tempb=0

tempc=0

tempd=0

tempe=0

tempf=0

tempg=0

dconn = sqlite3.connect('div2011.sqlite')

dcursor = dconn.cursor()

dsqlstr='CREATE TABLE IF NOT EXISTS table1 \ ("d1" INTEGER PRIMARY KEY NOT NULL ,"tel" TEXT)'

dcursor.execute(dsqlstr)

daytemp=""

daytemp1=''

yeartemp=""

monthtemp=""

atemp=""

strtemp=""

for y in range(2004,2022):

  for m in range(1,13):

    for d in range(1,32):

     #product = i * j * k

     #print("%d*%d*%d=%-2d " % (i, j, k, product), end="")

     yeartemp=str(y)

     monthtemp=str(m)

     datetemp=str(d)

     if monthtemp=="1" : monthtemp="01"

     if monthtemp=="2" : monthtemp="02"

     if monthtemp=="3" : monthtemp="03"

     if monthtemp=="4" : monthtemp="04"

     if monthtemp=="5" : monthtemp="05"

     if monthtemp=="6" : monthtemp="06"

     if monthtemp=="7" : monthtemp="07"

     if monthtemp=="8" : monthtemp="08"

     if monthtemp=="9" : monthtemp="09"

     if datetemp=="1" : datetemp="01"

     if datetemp=="2" : datetemp="02"

     if datetemp=="3" : datetemp="03"

     if datetemp=="4" : datetemp="04"

     if datetemp=="5" : datetemp="05"

     if datetemp=="6" : datetemp="06"

     if datetemp=="7" : datetemp="07"

     if datetemp=="8" : datetemp="08"

     if datetemp=="9" : datetemp="09"

     atemp=yeartemp+'/'+monthtemp+'/'+datetemp

     downtemp= yeartemp+monthtemp+datetemp

     total=int(downtemp)

     if total>20151001 : dayno=3242

     if (total<20150101 and="" total="">20140421) : dayno=1622

     if (total<20140224 and="" total="">20110930) : dayno=1082

     if (total<20110117 and="" total="">20070717) :

       strtemp= "SELECT * FROM table1 WHERE day='"+str(atemp)+"' "

       #print(strtemp)

       us_df = pd.read_sql(strtemp, conn)

       #print(us_df)

       if us_df.index.values !='[]' :

         for i in range(0,271):

          if i==0:

           daytemp=us_df.loc[i]["day"]

           daytemp1=daytemp[0:4]+"-"+daytemp[5:7]+"-"+daytemp[8:10]

           tempa= locale.atof(us_df.loc[0]["num1"])

           tempb= locale.atof(us_df.loc[0]["num2"])

           tempc= locale.atof(us_df.loc[0]["num3"])

           tempd= locale.atof(us_df.loc[0]["num4"])

           tempe= locale.atof(us_df.loc[0]["num5"])

           tempf= locale.atof(us_df.loc[0]["num6"])

           tempg= locale.atof(us_df.loc[0]["num7"])

           dsqlstr=" insert into table1 values ('{}','{}',{},{},{},{},{},{},{})".format(daytemp1,us_df.loc[i]["time"],tempa,tempb,tempc,tempd,tempe,tempf,tempg)

           dcursor.execute(dsqlstr)

           dconn.commit() # 主動更新

        else:

           daytemp=us_df.loc[i]["day"]

           daytemp1=daytemp[0:4]+"-"+daytemp[5:7]+"-"+daytemp[8:10]

           tempa=locale.atof(us_df.loc[i]["num1"])-locale.atof(us_df.loc[i-1]["num1"])

           tempb=locale.atof(us_df.loc[i]["num2"])-locale.atof(us_df.loc[i-1]["num2"])

           tempc=locale.atof(us_df.loc[i]["num3"])-locale.atof(us_df.loc[i-1]["num3"])

           tempd=locale.atof(us_df.loc[i]["num4"])-locale.atof(us_df.loc[i-1]["num4"])

           tempe=locale.atof(us_df.loc[i]["num5"])-locale.atof(us_df.loc[i-1]["num5"])

           tempf=locale.atof(us_df.loc[i]["num6"])-locale.atof(us_df.loc[i-1]["num6"])

           tempg=locale.atof(us_df.loc[i]["num7"])-locale.atof(us_df.loc[i-1]["num7"])

           dsqlstr=" insert into table1 values ('{}','{}',{},{},{},{},{},{},{})".format(daytemp1,us_df.loc[i]["time"],tempa,tempb,tempc,tempd,tempe,tempf,tempg)

           dcursor.execute(dsqlstr)

           dconn.commit()

           i=i+1

dconn.close() # 關閉資料庫 ,.

    經過以上的程式碼處理,我們得出以下的資料庫:
這資料庫超過500萬筆,看起來很大,其實就大數據來說並不多,當然這資料我們後續還有其他用處.

    接著我們做實作二,這個比較簡單,匯入2000到2021年台股期貨指數每分鐘的交易資料,並畫出它的k線圖,注意是每分鐘的.期指資料室從網上找來的,它也是csv檔,但結構簡單,一共3檔案,直接用sqlite中import即可,但這裡有一個問題.而這事涉在python中畫k線圖,問題就在Datetime的設定,早期想在python中畫k團使用的是mpl_finane這個套件,只要安裝pip install mpl_finance然後在實際的程式中import即可,但這個套件已經3,4年無人維護,以至於它被放棄了,目前新的套件是mplfinace,差別在沒有底線連接,但這個畫k線的方式與mpl_finance不同,其實比較直觀,簡單,但是它有一個資料結構的要求如果你畫的是日線圖,它腰的資料結構是 date open high low close volue,這6個欄位,其中date默認的日期結構是 xxxx-xx-xx,即如2021-08-31,你要是原始資料的時間結構不是這種的,執行程式畫k現時,會回報資料錯誤,比如2021/08/31就不能用,而若畫的是分鐘線,默認的資料結構是 xxxx-xx-xx **:**:**,即如 2021-08-31 09:00:00,這盎的型態.我們從網上找的資料並不是這種,所以我們在程式碼裡先修正後,然後用datetime的方法重新宣告後,再用mplfinace中的plot將k線圖畫出,程式碼如下:

import time

import pandas as pd

import matplotlib

import mplfinance as mpf

import matplotlib.pyplot as plt

import sqlite3

import datetime

import abstract

strtemp=""

str1=""

str3=""

str2=""

i=0

iday = []

conn = sqlite3.connect('indexfuturecom.sqlite') # 建立資料庫連線 0

strtemp= "select * from table1"

df = pd.read_sql(strtemp,conn,parse_dates=True)

df['Date'] = pd.to_datetime(df['Date'])

df.set_index('Date', inplace=True)

iday=df.loc['2001-01-02 08:46:00':'2021-07-31 13:45:00',:]

kwargs=dict(title='Candle plot',figratio=(15,10),figscale=5) mc=mpf.make_marketcolors(up='red',down='green',edge='i',wick='i',volume='in',inherit=True) s=mpf.make_mpf_style(gridaxis='both',gridstyle='-.',y_on_right=False,marketcolors=mc)

#print(iday)

mpf.plot(iday,**kwargs,type='candle',style =s,volume=True,addplot=[])

plt.show() ..,

   經過以上的執行,繪出的k線圖如下:
這裡面需要強調,畫出k線需要與python中的matplotlib的plot來搭配使用,這裡面可以用的功能較多,而"Python數據可視化之matplotlib實踐"這本書將這些講當相對簡單清楚,其中的程式碼從電子書copy進去Juputer執行可你說都沒問題,可以花個一天了解清楚.搭配上提供Python Guit程式的Tkinter套件裡的Canvas等繪圖功能,應該能完全提供給想要自製AI程式自動交易者的需求,畢竟都已經在Python中了,下來是要import Sklearn,Tensorflow,做成回歸.或SVM或是像我有其它的需求應該都是比較方便的.在這次的兩本書中"用Python預測玩轉股市高手精解"寫了許多如何從原始資料取得開始建立自己的交易系統的內容 可惜的是它用的多是對岸股市資料,本地的讀者可能需要自行找尋自己需要的部分,不過在資料結構,繪圖,系統指標的建立,到資料庫都有一些探索,是值得python有些基礎的人來看,唯其中的畫k線,它是用舊的mpl_finance,是無法使用的,想用新的mplfinace套件的可以參考網站"https://github.com/matplotlib/mplfinance"有相對較多的說明,而想配合發展Python Gui的可以參考Tkinter或PYQT5的專書,這本"用Python預測玩轉股市高手精解"雖有討論了TKinter的範例都內容不多,以上大概就是這兩本書使用下,透過實作台股資訊的兩個案例.以上.
 "此處的程式碼都是在下用最粗略直觀的方式是寫出來的,並沒有事前計畫,更未考慮效率與簡潔,主要都只是為產生可以供後續使用的原始資料,因此並不建議任何人取用它來工作,因為雖然程式碼都不長,但需要執行的時間都很久,這是必須說明的"

這裡有"Python數據可視化之matplotlib實踐的全部內容的epub檔"matplotlib實踐


    接下來就用Tkinter寫一個GUI將以上的K線圖包裝進去:

import time

import pandas as pd

import matplotlib

import mplfinance as mpf

import matplotlib.pyplot as plt

import sqlite3

import datetime

import abstract

import numpy as np

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg F

from tkinter import *

import tkinter as tk

win=tk.Tk()

win.geometry("850x750")

strtemp=""

str1=""

str3=""

str2=""

i=0

iday = []

conn = sqlite3.connect('indexfuturecom.sqlite') 

strtemp= "select * from table1"

df = pd.read_sql(strtemp,conn,parse_dates=True)

df['Date'] = pd.to_datetime(df['Date'])

df.set_index('Date', inplace=True)

iday=df.loc['2001-01-02 08:46:00':'2021-07-31 13:45:00',:]

fig = mpf.figure()

chart_canvas=tk.Canvas(win,background='white',width=600,height=200)

kwargs=dict(title='Candle plot',figratio=(3,2),figscale=5) mc=mpf.make_marketcolors(up='red',down='green',edge='i',wick='i',volume='in',inherit=True) s=mpf.make_mpf_style(gridaxis='both',gridstyle='-.',y_on_right=False,marketcolors=mc) fig,ax=mpf.plot(iday,type='candle',tight_layout=True,style=s, volume=True,returnfig = True)

chart_canvas = FigureCanvasTkAgg(fig,master=win)

chart_canvas.draw()

chart_canvas.get_tk_widget().place(relx = .01, rely=.05)

win.mainloop()



以上面的數據來跑簡單的SVM程式碼如下:

import time

import pandas as pd

import matplotlib

import mplfinance as mpf

import matplotlib.pyplot as plt

import sqlite3

import datetime

import abstract

import numpy as np

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

from tkinter import *

import tkinter as tk

import math

from sklearn import svm,preprocessing

import dataframe

strtemp=""

i=0

iday = []

iday1 = []

conn = sqlite3.connect('indexfuturecom.sqlite') # 建立資料庫連線

strtemp= "select * from table1"

origDF = pd.read_sql(strtemp,conn,parse_dates=True)

origDF['Date'] = pd.to_datetime(origDF['Date'])

origDF.set_index('Date', inplace=True)

iday=origDF.loc['2001-01-02 08:46:00':'2021-07-31 13:45:00',:]

iday['diff'] = iday["Close"]-iday["Close"].shift(1)

iday['diff'].fillna(0,inplace=True)

iday['up'] = iday['diff']

iday['up'][iday['diff']>0] = 1

iday['up'][iday['diff']<=0] = 0

iday['predictForUp'] = 0

target = iday['up']

length=len(iday)

trainNum=int(length*0.8)

predictnum=length-trainNum

feature=iday[['Close','High','Low','Open','Volume']]

feature=preprocessing.scale(feature)

featuretrain=feature[0:trainNum]

targettrain=target[0:trainNum]

svmTool=svm.SVC(kernel='linear')

svmTool.fit(featuretrain,targettrain)

predictedIndex=trainNum

while predictedIndex < length :

  testfeature=feature[predictedIndex:predictedIndex+1]

  predictForup=svmTool.predict(testfeature)

  iday.iloc[predictedIndex]['predictForUp']=predictForup

  predictedIndex = predictedIndex+1

dfwithpredicted = iday[trainNum:length]

figure=plt.figure()

(axClose,axUpordown) = figure.subplots(2, sharex=True)

dfwithpredicted['Close'].plot(ax=axClose)

dfwithpredicted['predictForUp'].plot(ax=axUpordown,color="red",label='predicted data') dfwithpredicted['up'].plot(ax=axUpordown,color="blue",label='real data')

plt.legend(loc='best')

plt.xticks()

plt.setp(plt.gca().get_xticklabels(), rotation=30)

plt.title("透過SVM預測期指漲跌情況")

plt.rcParams['font.sans-serif']=['SimHei']

plt.show() 





上個月的網頁瀏覽數次數