連續兩天的選股實作圍繞著搜尋,今天把選股程式整合結果寫出來,然後為嘗試不同的搜尋方法起個頭。
結合前兩天的內容,今天把第一個完整的選股程式和結果分享出來。
利用兩個 MultiSearch 物件分別取回最新一筆盤後資訊與移動平均指標。
ms_daily = MultiSearch(using=es)
ms_sma = MultiSearch(using=es)
for stock_id in stock_id_list:
search_daily = Search(index='history-prices-daily').\
query("match", stock_id=stock_id).\
source(includes=['stock_id', 'date', 'close', 'volume']).\
sort({"date": {"order": "desc"}})
search_daily = search_daily[0:1]
ms_daily = ms_daily.add(search_daily)
search_sma = Search(index='tech-analysis-sma').\
query("match", stock_id=stock_id).\
source(includes=['stock_id', 'date', 'close_sma_100', 'volume_sma_20']).\
sort({"date": {"order": "desc"}})
search_sma = search_sma[0:1]
ms_sma = ms_sma.add(search_sma)
responses_daily = ms_daily.execute()
responses_sma = ms_sma.execute()
def response_to_dataframe(es_multi_responses):
doc_fields = {}
count = 0
for response in es_multi_responses:
count += 1
if not bool(response):
continue
source_data = response["hits"]["hits"][0]["_source"]
for key in source_data:
try:
doc_fields[key] = np.append(doc_fields[key], source_data[key])
except KeyError:
doc_fields[key] = np.array([source_data[key]])
return pd.DataFrame(doc_fields)
elastic_df_daily = response_to_dataframe(responses_daily)
elastic_df_sma = response_to_dataframe(responses_sma)
elastic_df_merge = pd.merge(elastic_df_daily, elastic_df_sma, on=['stock_id','date'])
選股邏輯為:收盤價大於 100 線,且成交量大於月均量 1.5 倍。
elastic_df_merge['Qualify'] = np.where(
(elastic_df_merge['volume'].astype(np.float) >= 1.5 * elastic_df_merge['volume_sma_20'].astype(np.float)) &
(elastic_df_merge['close'].astype(np.float) >=elastic_df_merge['close_sma_100'].astype(np.float)), True, False)
df_select = elastic_df_merge.loc[elastic_df_merge['Qualify'] == True]
print(df_select)
結果如下:
共找到 137 檔個股符合條件。
利用 Python client 的確可以達到我想要結果,但我不禁懷疑,是否可以把邏輯交給 ES 運算呢?經過一翻研究,我發現了 ES 提供 script query 的功能,也就是把 Script 寫在 Query DSL,就可以執行一些邏輯運算。以下的官方文件的一個範例:
GET /_search
{
"query": {
"bool": {
"filter": {
"script": {
"script": {
"source": "doc['num1'].value > 1",
"lang": "painless"
}
}
}
}
}
}
從上面的代碼,馬上就發現了要探索的新東西:"painless",我好興奮啊!
今天先到這了,明天開始繼續進化我的選股程式。