使用Python實(shí)現(xiàn)構(gòu)建量化小程序
1 數(shù)據(jù)獲取
量化數(shù)據(jù)接口有很多,有tushare、alltick、xtquant等等。本文使用的是akshare庫(kù),它是開(kāi)源的財(cái)經(jīng)數(shù)據(jù)庫(kù),不僅包含股票、期貨、期權(quán)、外匯、基金等常見(jiàn)的金融數(shù)據(jù),還包括能源、事件、輿情和藝人指數(shù)這類(lèi)不常見(jiàn)但可能影響市場(chǎng)行為的其他數(shù)據(jù),可以說(shuō)是目前市面上免費(fèi)接口里最全的一個(gè)。
以獲取深市A股歷史日線數(shù)據(jù)為例,首先獲取深市A股的股票信息:
import akshare as ak
stock_info = ak.stock_info_sz_name_code()
stock_info.to_excel('stock_code.xlsx')
2 應(yīng)用架構(gòu)
本應(yīng)用基于dash框架、開(kāi)源組件庫(kù)feffery_antd_components與akshare金融數(shù)據(jù)接口開(kāi)發(fā)的輕量級(jí)應(yīng)用。app.py中進(jìn)行應(yīng)用對(duì)象的實(shí)例化,并構(gòu)建應(yīng)用的初始化頁(yè)面內(nèi)容;setting.css進(jìn)行前端界面樣式的調(diào)整;data儲(chǔ)存的是深交所A股信息。
- demo
- data
- stock_code.xlsx
- assets
- setting.css
- app.py
3 應(yīng)用啟動(dòng)
安裝好當(dāng)前項(xiàng)目依賴(lài)庫(kù),然后直接在終端執(zhí)行python app.py即可啟動(dòng)應(yīng)用,按照控制臺(tái)提示的信息,瀏覽器訪問(wèn)本地http://127.0.0.1:8050地址即可訪問(wèn)應(yīng)用。

4 代碼
# app.py
import pandas as pd
import dash
from pyecharts import options as opts
import akshare as ak
from dash import Dash, html, dcc, callback, Output, Input, State
import dash_bootstrap_components as dbc
from pyecharts.charts import Kline
import feffery_antd_components as fac
# 應(yīng)用實(shí)例化
app = Dash(
__name__,
title='量化小應(yīng)用',
update_title='加載中...',
assets_url_path='assets/setting.css'
)
app.layout = fac.AntdSpace([
dcc.Store(storage_type='local', id='stock-code-store', data=pd.read_excel('data\stock_code.xlsx', dtype={'A股代碼': 'str'}).to_dict('records')),
fac.AntdFlex([
fac.AntdIcon(icon='antd-right', style={'color': '#0069d9'}),
fac.AntdText('股票歷史日線數(shù)據(jù)查詢(xún)', className='header')
]),
fac.AntdFlex([
fac.AntdFlex([
'股票代碼:',
dcc.Dropdown(
id='stock-dropdown',
multi=False,
searchable=True,
value='000001',
placeholder='股票代碼',
style={'width': '100px'}
),
], align='center', gap='small'),
fac.AntdFlex([
'日期:',
fac.AntdDateRangePicker(
placeholder=['選擇開(kāi)始日期', '選擇結(jié)束日期'],
id='stock-dropdown datepicker',
size='middle',
prefix=fac.AntdIcon(icon='antd-calendar')
),
], gap='small'),
fac.AntdButton(
'搜索',
type='primary',
id='stock-dropdown btn',
loadingChildren="查詢(xún)中",
),
], align='center', gap='large'),
fac.AntdCard(
title='收益概述',
headStyle={'background': 'rgba(0, 0, 0, 0.3)', 'text-align': 'left'},
id='card-content',
className='card'
),
], className='container')
@app.callback(
Output('stock-dropdown', 'options'),
Input('stock-code-store', 'data')
)
def code_info(data):
data = pd.DataFrame(data)
data['A股代碼'] = data['A股代碼'].astype('str')
options = [
{'label': x, 'value': 'sz' + y}
for x, y in zip(data['A股代碼'], data['A股代碼'])
]
return options
@app.callback(
Output('card-content', 'children'),
Input('stock-dropdown btn', 'nClicks'),
[State('stock-code-store', 'data'),
State('stock-dropdown', 'value'),
State('stock-dropdown datepicker', 'value')],
running=[(Output('stock-dropdown btn', "loading"), True, False)],
)
def update(nClicks, data, value, date):
stock_info = pd.DataFrame(data)
stock_info = stock_info[stock_info['A股代碼'] == value[2:]].to_dict('records')
title = stock_info[0]['A股簡(jiǎn)稱(chēng)'] + '(SZ:' + stock_info[0]['A股代碼'] + ')'
result = ak.stock_zh_a_daily(symbol=value, start_date=date[0], end_date=date[1])
result.rename(columns={'open': '開(kāi)盤(pán)價(jià)', 'close': '收盤(pán)價(jià)', 'low': '最低', 'high': '最高'}, inplace=True)
fig = (
Kline(init_opts=opts.InitOpts(width='1200px', height='300px'))
.add_xaxis(list(result['date']))
.add_yaxis(series_name='k線', y_axis=result[['開(kāi)盤(pán)價(jià)', '收盤(pán)價(jià)', '最低', '最高']].values.tolist(),
itemstyle_opts=opts.ItemStyleOpts(color='rgb(192, 51, 47)', color0='green'))
.set_global_opts(
title_opts=opts.TitleOpts(title=f'{date[0]}-{date[1]}日K線'),
yaxis_opts=opts.AxisOpts(name='單位凈值(元)', min_=result[['開(kāi)盤(pán)價(jià)', '收盤(pán)價(jià)', '最低', '最高']].min().min(), max_=result[['開(kāi)盤(pán)價(jià)', '收盤(pán)價(jià)', '最低', '最高']].max().max()),
tooltip_opts=opts.TooltipOpts(trigger='axis', axis_pointer_type='cross', formatter=': {c}', border_color='#ccc', background_color='rgba(245, 245, 245, 0.8)'),
datazoom_opts=opts.DataZoomOpts(is_show=True, range_start=result['date'].min(), range_end=result['date'].max()),
)
.set_series_opts(
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_='max', name='最高價(jià)', value=result['最高'].max()), opts.MarkPointItem(type_='min', name='最低價(jià)', value=result['最低'].min())], symbol='pin'),
splitline_opts=opts.SplitAreaOpts(is_show=True),
linestyle_opts=opts.LineStyleOpts(type_='dashed', color='lightgrey'),
)
)
fig.render('kline.html')
card_layout = [
fac.AntdRow(title, className='card-content title', wrap=True),
fac.AntdRow([
fac.AntdCol([
fac.AntdText('最高:', className='card-content index'),
fac.AntdText(result['最高'].max(), className='card-content value', style={'color': 'red'})
]),
fac.AntdCol([
fac.AntdText('最低:', className='card-content index'),
fac.AntdText(result['最低'].max(), className='card-content value', style={'color': 'green'})
]),
fac.AntdCol([
fac.AntdText(f'成交量:{str(result['volume'].sum())}手', className='card-content index'),]),
fac.AntdCol([
fac.AntdText(f'成交額:{str(result['amount'].sum())}元', className='card-content index'),]),
], gutter=20),
html.Iframe(
srcDoc=open('kline.html', 'r').read(),
style={
'height': 300,
'width': '100%',
'align': 'center'
}
)
]
return card_layout
if __name__ == '__main__':
app.run(debug=False)
/* setting.css*/
html,body {
background-color: #ffffff;
color: #000000;
text-align: center !important;
margin: 1%;
padding: 1%;
font-family: 'Sans ser-if';
}
.container {
display: grid;
width: 1200px;
}
/* 標(biāo)題樣式 */
.header {
font-size: 18px;
font-weight: bold;
}
/* 卡片樣式 */
.card {
width: 1400px;
}
.ant-card-body {
display: flex;
flex-direction: column;
}
.card-content {
}
.title {
font-size: 24px;
font-weight: bold;
}
.index {
font-size: 12px;
font-weight: bold;
}
.value {
font-weight: bold;
}
5 優(yōu)化方向
由于本文涉及的數(shù)據(jù)交互與計(jì)算較少,歷史數(shù)據(jù)獲取的方式是直接調(diào)用akshare庫(kù),而該庫(kù)有的數(shù)據(jù)不能頻繁獲取。若數(shù)據(jù)量增多,為提高系統(tǒng)效率與性能,需要采取適當(dāng)?shù)姆绞?,將?shù)據(jù)持久化保存到本地。
構(gòu)建成多頁(yè)面應(yīng)用,一個(gè)頁(yè)面存放一個(gè)指標(biāo)
到此這篇關(guān)于使用Python實(shí)現(xiàn)構(gòu)建量化小程序的文章就介紹到這了,更多相關(guān)Python構(gòu)建量化程序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python實(shí)現(xiàn)域名系統(tǒng)(DNS)正向查詢(xún)的方法
這篇文章主要介紹了python實(shí)現(xiàn)域名系統(tǒng)(DNS)正向查詢(xún)的方法,結(jié)合實(shí)例形式分析了Python使用socket模塊下getaddrinfo方法進(jìn)行域名查詢(xún)的具體技巧,需要的朋友可以參考下2016-04-04
基于python分享一款地理數(shù)據(jù)可視化神器keplergl
這篇文章主要介紹了分享一款地理數(shù)據(jù)可視化神器keplergl,keplergl是由Uber開(kāi)源的一款地理數(shù)據(jù)可視化工具,通過(guò)keplergl我們可以在Jupyter?notebook中使用,下文分享需要的小伙伴可以參考一下2022-02-02
Python警察與小偷的實(shí)現(xiàn)之一客戶(hù)端與服務(wù)端通信實(shí)例
這篇文章主要介紹了Python警察與小偷的實(shí)現(xiàn)之一客戶(hù)端與服務(wù)端通信實(shí)例,并附有難點(diǎn)及易錯(cuò)點(diǎn)的分析與說(shuō)明,需要的朋友可以參考下2014-10-10
初步介紹Python中的pydoc模塊和distutils模塊
這篇文章主要介紹了Python中的pydoc模塊和distutils模塊,本文來(lái)自于IBM官方開(kāi)發(fā)者技術(shù)文檔,需要的朋友可以參考下2015-04-04
利用Python實(shí)現(xiàn)崗位的分析報(bào)告
這篇文章主要為大家詳細(xì)介紹了如何利用Python實(shí)現(xiàn)崗位的分析報(bào)告,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03

