據(jù)可視化與推薦系統(tǒng)實戰(zhàn):從K線到智能選股)
1. 為什么要做可視化推薦二合一畢設(shè)選題的切入點與整體技術(shù)選型先說個很現(xiàn)實的問題市面上用Python做股票數(shù)據(jù)分析的項目一抓一大把但大多數(shù)都停留在拉數(shù)據(jù)、畫K線、算個均線的層面功能上很像一個加強版Excel。而單純做推薦系統(tǒng)又往往脫離真實場景用戶根本不知道推薦的依據(jù)是什么。這個課題比較聰明的點在于把兩塊需求擰在一起先讓用戶看得懂行情再根據(jù)看得懂的數(shù)據(jù)給出有依據(jù)的推薦。數(shù)據(jù)可視化解決的是信息過載的問題——幾千只股票、幾十個指標(biāo)光靠人眼盯盤根本篩不過來推薦系統(tǒng)解決的是選擇困難的問題——盯盤盯出來了候選池但選哪只、為什么選需要一套可解釋的邏輯來輔助決策。先說技術(shù)選型。我默認這個項目面向的是課程設(shè)計或者本科畢設(shè)技術(shù)棧選擇必須兼顧三點難度適中、有東西可寫、答辯時講得清楚。推薦使用Python 3.8 Pandas Matplotlib Pyecharts Scikit-learn SQLite。不要一上來就上什么深度學(xué)習(xí)和LSTM那是給自己挖坑。大多數(shù)情況下K線形態(tài)識別加簡單的協(xié)同過濾加一個技術(shù)面評分卡已經(jīng)足夠撐起一個完整閉環(huán)而且每一步都能在白板上畫出來。模塊劃分也要符合設(shè)計與實現(xiàn)這個題目氣質(zhì)。我當(dāng)時把系統(tǒng)切成四層數(shù)據(jù)層、計算層、可視化層、推薦層。數(shù)據(jù)層負責(zé)從公開數(shù)據(jù)源拉取行情并做清洗入庫計算層負責(zé)技術(shù)指標(biāo)計算和特征工程可視化層做交互式圖表和看板推薦層基于用戶的瀏覽/收藏行為做策略推薦。四層各干各的聯(lián)調(diào)時才不會互相牽制。架構(gòu)設(shè)計圖我不知道你打算怎么畫但建議畫一張四層結(jié)構(gòu)加數(shù)據(jù)流向的圖。注意答辯老師最愛問的就是數(shù)據(jù)流是怎么走的——從原始數(shù)據(jù)變成最終推薦結(jié)果中間每一步都要能說清楚。2. 數(shù)據(jù)獲取與預(yù)處理90%的坑都埋在這層股票數(shù)據(jù)可視化項目第一個繞不開的問題是數(shù)據(jù)從哪來。這是個比寫代碼更磨人的環(huán)節(jié)。常見的公開數(shù)據(jù)源包括Tushare、AkShare、Yahoo Finance美股、東方財富的公開接口等。我比較推薦用AkShare原因是免費、無需token、接口豐富A股、港股、美股都能覆蓋而且返回的就是Pandas DataFrame代碼上非常順手。不過AkShare有幾個使用細節(jié)你需要提前知道一天內(nèi)頻繁調(diào)用接口容易觸發(fā)對方的風(fēng)控建議爬取做節(jié)流每次請求后sleep 0.3到0.5秒數(shù)據(jù)偶爾會返回空值或復(fù)權(quán)因子不一致必須做數(shù)據(jù)清洗。數(shù)據(jù)清洗不是簡單地dropna要分情況處理日行情數(shù)據(jù)缺失的常用方案是前值填充ffill但前值填充對收盤價只是權(quán)宜之計如果連續(xù)缺失超過三天建議直接剔除該時間段數(shù)據(jù)避免生成錯誤的均線和指標(biāo)。入庫方案我用的是SQLite因為整個項目體量不大不需要上MySQL。建表結(jié)構(gòu)建議至少兩張表stock_price存行情快照字段包括code、date、open、high、low、close、volume、amountstock_info存股票基礎(chǔ)信息包括code、name、industry、list_date。兩張表通過code關(guān)聯(lián)。所有數(shù)據(jù)寫入之前先做去重以code, date作為聯(lián)合主鍵后寫入的覆蓋先寫入的防止反復(fù)爬取產(chǎn)生臟數(shù)據(jù)。這里有一個實操中的關(guān)鍵經(jīng)驗建議先拉5年以上的日線數(shù)據(jù)存到本地再啟動可視化應(yīng)用。我見過太多人做項目時圖表畫到一半就空白排查半天發(fā)現(xiàn)是網(wǎng)絡(luò)斷了或接口限了流。數(shù)據(jù)落地到本地后整個開發(fā)調(diào)試不需要聯(lián)網(wǎng)穩(wěn)得多。如果你要復(fù)現(xiàn)這個項目先跑一個月數(shù)據(jù)的demo再拉全量別一上來就貪多。提示不要在這個環(huán)節(jié)過分糾纏實時數(shù)據(jù)。實時行情需要WebSocket申請授權(quán)、處理推送緩沖區(qū)、應(yīng)對斷線重連復(fù)雜度會直接爆炸。實時推送針對畢設(shè)是加分可選項不是必選項。先把日線級別的歷史數(shù)據(jù)做成穩(wěn)定閉環(huán)再做實時擴展層層遞進風(fēng)險小得多。3. 可視化模塊的核心實現(xiàn)K線圖的坑、指標(biāo)疊加的邏輯和交互設(shè)計可視化模塊是看起來最值錢的部分。如果你用Matplotlib畫普通折線圖雖然也能展示但大概率會被打回重做——太像上課練習(xí)了。建議用Pyecharts 1.x 版本做交互式圖表。它生成的是HTML格式瀏覽器直接打開支持鼠標(biāo)懸停、縮放、平移演示效果比靜態(tài)Matplotlib高出不止一個檔次。K線圖是可視化模塊的核心。Pyecharts里K線用Kline組件實現(xiàn)數(shù)據(jù)格式是[open, close, low, high]注意順序和你在其他平臺看到的OHLC不同。我當(dāng)時在這塊踩了個大坑文檔里寫的是[open, close, lowest, highest]沒仔細看文檔直接按常規(guī)OHLC傳數(shù)據(jù)結(jié)果K線的實體方向全畫反了陽線陰線完全顛倒。視覺上看起來好像也能用但嚴(yán)重誤導(dǎo)判斷。K線之上疊加均線是另一個常見需求。MA5、MA10、MA20三條均線是標(biāo)配。Pyecharts中可以用Line組件和Kline做overlap層疊但疊的時候有個重要參數(shù)不能漏overlap之后的坐標(biāo)軸類型要統(tǒng)一且均線的數(shù)據(jù)長度要和K線完全對齊否則尾部錯位。更穩(wěn)妥的做法是在K線圖里加dataZoom縮放組件讓用戶滑動查看特定時間窗口而不是一屏塞所有數(shù)據(jù)。除了K線推薦系統(tǒng)決策的依據(jù)還需要幾個副圖指標(biāo)。成交量是必須的MACD或RSI可以選一個其中RSI相對容易解釋——它的計算不涉及復(fù)雜的EMA遞歸對答辯更友好。我當(dāng)時實現(xiàn)的是成交量柱狀圖 RSI副圖作為附在圖下方的第二和第三個區(qū)域。這里分享一個布局層面的心得用Pyecharts的Grid組件實現(xiàn)多圖拼接時每個子圖占位比例要調(diào)好K線主體占60%以上RSI占20%成交量占20%不然視覺上主次不分。還有一點容易被低估數(shù)據(jù)是按證券代碼分文件存還是統(tǒng)一存一張表后用字段過濾這直接決定加載性能。如果用一張表存所有數(shù)據(jù)date字段建索引查詢單只股票時走索引返回很快如果按代碼分文件保存讀取時邏輯簡單但文件數(shù)量會很多。我實測下來SQLite單表加索引的方式綜合性能更好因為一個連接搞定所有查詢不用頻繁打開關(guān)閉文件。提示股票可視化項目的交互不止是圖表的hover。你要讓用戶能輸入股票代碼切換標(biāo)的、選擇時間范圍、切換指標(biāo)組合推薦結(jié)果要能聯(lián)動到對應(yīng)K線視圖。這種輸入→展示→互動→推薦的閉環(huán)才是答辯時老師眼中系統(tǒng)完整度的關(guān)鍵評判點。4. 推薦系統(tǒng)怎么做才有說服力三路策略與特征相關(guān)性分析推薦系統(tǒng)是這個項目的理論高地和得分點。但股票推薦和電商推薦邏輯上有所不同電商推薦可以基于買過A的人還會買B這種協(xié)同過濾而股票推薦需要結(jié)合相似K線形態(tài)和技術(shù)指標(biāo)共振來做更解釋得通的推薦。我實際采用的是三路推薦策略最終結(jié)果按加權(quán)融合輸出。第一路是相似度推薦基于協(xié)同過濾思想不過不是算用戶相似度而是算股票在特征空間的距離。特征怎么選用相對變化量而不用絕對價格這一點至關(guān)重要——直接把收盤價丟進歐氏距離計算是沒有意義的因為高價股和低價股天然差很多量綱完全不同。我選擇了近20日收益率、近5日波動率、RSI值、成交量變化率這幾個特征做Z-score標(biāo)準(zhǔn)化隨機森林Random Forest中常用的特征重要性方法可以用來給每個特征賦初始權(quán)重再用K近鄰KNN找出距離最近的Top-N只股票。第二路是技術(shù)面共振推薦規(guī)則引擎的設(shè)計思路。設(shè)置幾條可解釋的規(guī)則例如MA5上穿MA10且RSI在50~70之間且成交量放量1.5倍以上條件全部滿足就標(biāo)記為共振信號候選。這一路的價值在于可解釋性強每條推薦理由都能對應(yīng)到具體指標(biāo)特征。第三路是用戶偏好協(xié)同過濾?;谟脩舻臍v史瀏覽/收藏/買入行為記錄構(gòu)建行為矩陣。用戶A瀏覽了某只股票系統(tǒng)在推薦時統(tǒng)計該股票被類似用戶偏好集中的行為進一步生成推薦候選池。這里的類似用戶通過行為記錄的余弦相似度計算。這三路需要做數(shù)據(jù)融合。我當(dāng)時用的策略是加權(quán)排序相似度推薦權(quán)重在0.5形態(tài)共振在0.3協(xié)同過濾在0.2。各路的輸出還是候選集合并集取得分最高的Top-3作為最終結(jié)果。為什么是Top-3列表太長會分散用戶注意力而且推薦系統(tǒng)的評測指標(biāo)中Top-3的精確率遠比Top-10更直觀、更容易在答辯時解釋。這里要回答一個常見問題為什么不做嚴(yán)格的收益率預(yù)測模型因為那是另一個研究問題涉及時序平穩(wěn)性、滑點、手續(xù)費、過擬合等一系列復(fù)雜工程在課程設(shè)計的時間框架內(nèi)很難做得嚴(yán)謹(jǐn)。而推薦系統(tǒng)的定位是輔助決策工具它的評估指標(biāo)是推薦列表中候選股票池與歷史強勢股的命中率我建議采用命中率N做評估推薦Top-5中包含未來20日漲幅前10%的股票算一次命中最終統(tǒng)計整體命中率。這個指標(biāo)實現(xiàn)簡單、表達清晰、答辯時也拿得出手。5. 系統(tǒng)整體聯(lián)調(diào)時的三個大坑與最終版本的處理方式設(shè)計文檔寫得再漂亮聯(lián)調(diào)才能發(fā)現(xiàn)真問題。這個項目我印象最深的是三個坑寫出來供你參考。第一個坑是中文編碼。Pyecharts在HTML中默認輸出UTF-8一般沒問題。但如果股票名稱中含有繁體字或者特殊字符如ST和退標(biāo)志在文件名、命令行輸出、日志打印時極易出現(xiàn)UnicodeEncodeError。我的處理方式是在項目啟動入口處設(shè)置sys.stdout.reconfigure(encodingutf-8)并在所有文件寫入操作中顯式指定編碼方式。這個坑雖小但足以讓演示現(xiàn)場直接崩潰。第二個坑是推薦結(jié)果的時間穿越。這是最容易被忽視的邏輯漏洞用今天的數(shù)據(jù)算出的特征去匹配包含未來數(shù)據(jù)的樣本得出的相似股票純屬作弊。處理方式是數(shù)據(jù)切分必須嚴(yán)格按時間切——訓(xùn)練推薦模型的KNN只使用截止到某個交易日的歷史數(shù)據(jù)對某一天的推薦只允許使用這一天之前的數(shù)據(jù)。代碼上只需要對特征矩陣做時間過濾即可但很多人就是沒做。第三個坑是SQLite并發(fā)讀寫。如果用Flask做Web界面可能同時多個請求訪問數(shù)據(jù)庫。SQLite默認同一時刻只允許一個進程寫庫并發(fā)高時會出現(xiàn)database is locked。我建議連接時設(shè)置timeout10并把高頻讀操作做成緩存。另一個更省事的方案是所有查詢接口加一個統(tǒng)一緩存裝飾器短期數(shù)據(jù)用字典存內(nèi)存過期時間設(shè)置為5分鐘。這樣不僅能解決鎖問題響應(yīng)速度還快了很多。最終版本的實現(xiàn)效果我用一句話概括用戶在系統(tǒng)頁輸入股票代碼和時間范圍系統(tǒng)展示K線和指標(biāo)副圖用戶點擊相似股票按鈕生成推薦候選并按得分排序每條推薦右側(cè)顯示推薦理由標(biāo)簽用戶可以將推薦結(jié)果標(biāo)注為感興趣/不感興趣行為數(shù)據(jù)回流數(shù)據(jù)庫供后續(xù)協(xié)同過濾更新。6. 文檔與PPT的內(nèi)容編排答辯視角下的側(cè)重優(yōu)化項目代碼寫完了只是完成50%。課程設(shè)計的另一半是文檔和PPT而這兩樣?xùn)|西決定了答辯老師第一印象。文檔我建議分成五章緒論、需求分析、系統(tǒng)設(shè)計架構(gòu)數(shù)據(jù)庫設(shè)計、系統(tǒng)實現(xiàn)界面截圖核心代碼片段、系統(tǒng)測試功能測試用例表推薦命中率結(jié)果分析。如果學(xué)校要求設(shè)計與實現(xiàn)這個標(biāo)題章節(jié)命名直接對應(yīng)標(biāo)題邏輯最穩(wěn)。需要注意不要事無巨細把所有源碼都貼進去核心類和數(shù)據(jù)流圖才是老師最想看的。關(guān)于PPT我強烈建議控制在15到20頁以內(nèi)。結(jié)構(gòu)設(shè)計注意突出數(shù)據(jù)流向這條主線數(shù)據(jù)從哪來處理過后長什么樣特征如何構(gòu)建推薦如何計算用戶如何看到結(jié)果。每頁只放一個核心圖寧可少講不要堆砌。答辯演示環(huán)節(jié)先演示一個完整流程輸入股票代碼→展示K線→點擊推薦→展示Top-3候選及推薦理由。這個流程走完再講解核心代碼片段和評估結(jié)果整個邏輯鏈清晰反而顯得研究得很透。一個加分的小設(shè)計在系統(tǒng)測試章節(jié)加入一個簡單的對比實驗表格對比隨機選股與推薦系統(tǒng)的命中率。我當(dāng)時實測的數(shù)據(jù)推薦Top-5在測試集上的命中率大約為27%到35%左右隨機選股基線只有4%。這個對比數(shù)據(jù)放在PPT里非常有力。別虛報數(shù)據(jù)真實測出來的就好老師更在意你是否理解評測方法。7. 源碼交付前最后該檢查的核心點項目的源碼要保證讓另一個同學(xué)拿到也能跑通。這一點在課程設(shè)計提交時特別重要因為有些老師本身不看代碼但會抽測運行。提交前檢查清單可以做得很簡潔首次運行是否會自動創(chuàng)建數(shù)據(jù)庫并拉取示例數(shù)據(jù)requirements.txt是否包含完整的第三方庫且版本號已鎖README是否寫清楚運行步驟建議三步走安裝依賴、運行初始化腳本、啟動主程序是否附帶一個演示用的數(shù)據(jù)集文件防止評審現(xiàn)場網(wǎng)絡(luò)連不上外部的數(shù)據(jù)源。其中演示用數(shù)據(jù)集文件可以重點加上。我當(dāng)時放了一份近兩年的日線數(shù)據(jù)CSV壓縮包README里寫明如網(wǎng)絡(luò)不可用可使用本地數(shù)據(jù)文件初始化數(shù)據(jù)庫。這個細節(jié)在答辯時遇到斷網(wǎng)環(huán)境簡直是救命稻草。還有一個細節(jié)是項目的目錄結(jié)構(gòu)要清晰data/、core/、visual/、recommender/、web/、docs/各歸其位入口文件放在根目錄下命名為main.py或app.py。不要把所有代碼堆在根目錄下這是代碼潔癖的問題。根據(jù)我這幾年看過各種課程設(shè)計的經(jīng)驗?zāi)苷嬲玫礁叻值捻椖坎灰欢ㄓ昧俗钋把氐募夹g(shù)但一定在數(shù)據(jù)鏈路完整、文檔邏輯清晰、代碼可直接運行這三個基本盤上做得扎實??梢暬K負責(zé)直觀展示你的工作量推薦模塊負責(zé)體現(xiàn)你的思考深度文檔和PPT負責(zé)讓這一切被看見。把這三件事做透這個課題拿高分并不難。