金融量化学习---Python, MySQL, Pandas

这里用来记录一些在金融领域,尤其是银行相关的资金、债券、票据中应用到的数据管理与分析, 编程等心得或笔记,以及个人的一点小小兴趣(易经八卦、藏密禅修)等

导航

Streamlit

简介

Streamlit是第一个专门针对机器学习和数据科学团队的应用 开发框架,它是开发自定义机器学习工具的最快的方法,你可以认为 它的目标是取代 Flask 在机器学习项目中的地位,可以帮助机器学习工程师快速开发用户交互工具。Streamlit 的宗旨很明确,就是要让人只需要通过编写简单的 Python 代码,就可以完成构建应用的需求。它支持所见即所得的热更新,而且你不需要写一行 HTTP 请求代码及前端代码,你只需要一个 Python IDE 和一个浏览器,就能快速看到你自己构建的应用。

一个傻瓜式构建可视化web的程序
Streamlit库官方地址:https://streamlit.io/
API文档地址:https://docs.streamlit.io/
在线沙盘:https://samdobson-streamlit-sandbox-app-za85j0.streamlit.app/?ref=blog.streamlit.io#hello-there

安装:pip install streamlit
离线安装:https://pypi.org/project/streamlit/#files
安装完成之后运行:streamlit hello可是测试是否正确安装
正确安装后,运行时,可以在CMD或者Anaconda Powershell Prompt (Anaconda)下(推荐这种方式,可设置env)运行:
streamlit run myfile.py

Streamlit库基本介绍
Streamlit是一个基于 Python 的 Web 应用程序框架,致力于以更高效、更灵活的方式可视化数据,并分析结果。它是一个开源库,可以帮助数据科学家和学者在短时间内开发机器学习 (ML) 可视化仪表板。只需几行代码,我们就可以构建并部署强大的数据应用程序。其实就是用Python语言写一个本地Web,应用场景常常是机器学习可视化(当然也可做其他的图表分析等),不需要任何Web前后端开发经验。注意我们写出的Web只有本地可以访问,要接入互联网还需要其他进阶方法!
https://docs.streamlit.io/library/cheatsheet

优点和缺点(from Claude)

Streamlit 是一个用于构建数据应用程序的开源 Python 库,有以下优点和缺点:

优点:

  1. 简单易用:Streamlit 使用 Python 语法,非常容易掌握,可以快速构建数据应用程序。
  2. 美观大方:Streamlit 拥有漂亮的 UI 组件,可以构建出色观感的应用程序。
  3. 兼容性强:Streamlit 应用程序可以部署在任何地方 - 在本地运行,嵌入到Notebook中,部署在服务器上等等。
  4. 高度交互:Streamlit 支持许多 UI 组件,可以构建高度交互的应用程序。
  5. 开源免费:Streamlit 是免费开源的,有很大的社区支持。

缺点:

  1. 只适合简单应用:Streamlit 适合快速构建简单的应用程序,对于大型复杂的应用不太适用。
  2. 定制性略差:Streamlit 的 UI 组件定制性稍微差一些,样式不太方便调整。
  3. 部署依赖较多:部署 Streamlit 应用程序依赖较多,比较麻烦,不像传统 Python 应用那么简单。
  4. 社区较小:虽然 Streamlit 开源社区在增长,但相比其他 Web 框架,社区还是较小。
  5. 不支持前后端分离:Streamlit 不支持前后端分离开发,后端和前端高度耦合。
    所以,总体来说,Streamlit 是一个非常适合快速开发简单数据应用的工具,但对大型复杂应用和追求高定制性的项目,Streamlit 可能不太适用。但作为快速开发和原型构建,Streamlit 是一个很好的选择。 (已编辑)

命令

运行Streamlit的程序

CMD下运行

Another way of running Streamlit is to run it as a Python module. This can be useful when configuring an IDE like PyCharm to work with Streamlit:
Running
python -m streamlit run your_script.py

anaconda Powershell下运行

is equivalent to:
streamlit run your_script.py

You can also pass a URL to streamlit run! This is great when combined with GitHub Gists. For example:
streamlit run https://raw.githubusercontent.com/streamlit/streamlit_app.py

Step by step 学习

官方指引:https://docs.streamlit.io/library/get-started
在线学习:http://cw点hubwiz.com/card/c/streamlit-manual/
https://blog.streamlit.io/how-to-master-streamlit-for-data-science/

Streamlit has two easy ways to display information into your app, which should typically be the first thing you try: st.write and magic.

st.write and magic commands

魔法命令使用时,可以直接输入要输出的对象名称,不用再打st.write(),如下:

st.write()
st.write() 是一个泛型函数,根据传入对象不同采取不同的展示方式,比如传入 pandas.DataFrame 时,st.write(df) 默认调用 st.dataframe(),传入 markdown时,st.write(markdown) 默认调用 st.markdown()。可传入的对象有:

  • write(data_frame) : Displays the DataFrame as a table.
  • write(func) : Displays information about a function.
  • write(module) : Displays information about the module.
  • write(dict) : Displays dict in an interactive widget.
  • write(obj) : The default is to print str(obj).
  • write(mpl_fig) : Displays a Matplotlib figure.
  • write(altair) : Displays an Altair chart.
  • write(keras) : Displays a Keras model.
  • write(graphviz) : Displays a Graphviz graph.
  • write(plotly_fig) : Displays a Plotly figure.
  • write(bokeh_fig) : Displays a Bokeh figure.
  • write(sympy_expr) : Prints SymPy expression using LaTeX.
  • write(markdown): markdown text.

仅仅展示代码,而不执行,可以:

code = """
def sum_(x):
    return np.sum(x)
"""
st.code(code, language="python")

code = """
for (i i 1:10) {
    print(i)
}
"""
st.code(code, language="r")

st.markdown("""
​```python
print("hello")
""")

展示 Code,同时执行 Code;需要将code放入 st.echo() 内:

with st.echo():
    for i in range(5):
        st.write("hello")

文本原素(Text elements)

st.markdown

st.markdown('Streamlit is **_really_ cool**.')
st.markdown(”This text is :red[colored red], and this is **:blue[colored]** and bold.”)
st.markdown(":green[$\sqrt{x^2+y^2}=1$] is a Pythagorean identity. :pencil:")

st.title

st.title('This is a title')
st.title('A title with _italics_ :blue[colors] and emojis :sunglasses:')


st.header
st.subheader
st.caption
st.code
st.text
st.latex
st.divider

数据显示元素(Data display elements)

st.dataframe
st.table
st.metric
st.json

Chart elements

st.line_chart
st.area_chart
st.bar_chart
st.pyplot
st.altair_chart
st.vega_lite_chart
st.plotly_chart
st.bokeh_chart
st.pydeck_chart
st.graphviz_chart
st.map

Input widgets

st.button
st.experimental_data_editor
st.download_button
st.checkbox
st.radio
st.selectbox
st.multiselect
st.slider
st.select_slider
st.text_input
st.number_input
st.text_area
st.date_input
st.time_input
st.file_uploader
st.camera_input
st.color_picker

Media elements

remove
st.image
st.audio
st.video
Layouts and containers

st.sidebar
st.columns
st.tabs
st.expander
st.container
st.empty

Status elements

st.progress
st.spinner
st.balloons
st.snow
st.error
st.warning
st.info
st.success
st.exception

Control flow

st.stop
st.form
st.form_submit_button
st.experimental_rerun

Utilities

st.set_page_config
st.echo
st.help
st.experimental_show
st.experimental_get_query_params
st.experimental_set_query_params

Mutate charts

State management
Performance
Personalization

Connections and databases

st.experimental_connection
SQLConnection
SnowparkConnection
Connection base class

Advanced features

Command-line options
Configuration
Theming
Caching
Add statefulness to apps
Dataframes
Widget semantics
Pre-release features
Working with timezones
Static file serving
HTTPS support
Secrets management
Components
remove
Components API
Create a Component
Publish a Component
Component gallery
open_in_new
Roadmap
open_in_new

===========================================================================

st.button

st.button 会显示一个按钮组件。

应用功能:
默认情况下输出 Goodbye
一旦按下按钮,则会变为显示 Why hello there
st.button() 语句接收了一个值为 Say hello 的 label 参数,会作为显示在按钮上的文字。
st.write 命令被用作显示文字消息,取决于按钮是否按下,显示的要么是 Why hello there,要么是 Goodbye

import streamlit as st

st.header('st.button')

if st.button('Say hello'):
     st.write('Why hello there')
else:
     st.write('Goodbye')

st.write

st.write 能够在 Streamlit 应用中输出文字等内容。

除了能够输出文字,st.write() 命令还能够输出...

  • 输出字符串,类似于 st.markdown()
  • 输出 Python 的 dict 字典对象
  • 输出 pandas DataFrame,将数据框显示为表格
  • 输出用 matplotlib、plotly、altair、graphviz、bokeh 等库所作的图表
  • 以及更多!(见 API 文档中对 st.write 的描述

代码
以下是如何使用 st.write 的代码:

import numpy as np
import altair as alt
import pandas as pd
import streamlit as st

st.header('st.write')

# 样例 1

st.write('Hello, *World!* :sunglasses:')

# 样例 2

st.write(1234)

# 样例 3

df = pd.DataFrame({
     'first column': [1, 2, 3, 4],
     'second column': [10, 20, 30, 40]
     })
st.write(df)

# 样例 4

st.write('Below is a DataFrame:', df, 'Above is a dataframe.')

# 样例 5

df2 = pd.DataFrame(
     np.random.randn(200, 3),
     columns=['a', 'b', 'c'])
c = alt.Chart(df2).mark_circle().encode(
     x='a', y='b', size='c', color='c', tooltip=['a', 'b', 'c'])
st.write(c)

逐行解释
创建 Streamlit 应用时要做的第一件事就是将 streamlit 库导入为 st:import streamlit as st
然后紧跟着的是应用的标题文字:st.header('st.write')

样例 1
st.write 的基本用法就是现实文字和使用 Markdown 语法的文本:
st.write('Hello, World! 😎')

样例 2
前面提到,st.write 还能够输出其他数据类型,比如数字:
st.write(1234)

样例 3
数据框也能够通过如下语句显示:
df = pd.DataFrame({
'first column': [1, 2, 3, 4],
'second column': [10, 20, 30, 40]
})
st.write(df)

样例 4
你也能传入多个参数,比如:
st.write('Below is a DataFrame:', df, 'Above is a dataframe.')

样例 5
最后,你也可以显示各种图表,只需传入图表对象即可:

df2 = pd.DataFrame(
np.random.randn(200, 3),
columns=['a', 'b', 'c'])
c = alt.Chart(df2).mark_circle().encode(
x='a', y='b', size='c', color='c', tooltip=['a', 'b', 'c'])
st.write(c)

代码示例

# -*- coding: utf-8 -*-
"""
# My first app
原文:https://blog.csdn.net/qq_44747847/article/details/116462041

You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
"""
import streamlit as st
import numpy as np
import pandas as pd

st.title("This is my first app")
st.write("你好")
st.write("Here's our first attempt at using data to create a table:")

#显示dataframe
df = pd.DataFrame({
  'first column': [5, 6, 7, 8],
  'second column': [50, 60, 70, 80]
})

st.write(pd.DataFrame({
    'first column': [1, 2, 3, 4],
    'second column': [10, 20, 30, 40]
}))
# 其中df定义的位置,并不影响最后的输出位置!
# 可参考https://docs.streamlit.io/library/get-started/main-concepts 中的use magic
df

#显示折线图
chart_data = pd.DataFrame(
     np.random.randn(20, 3),
     columns=['广州', '上海', '北京'])

st.line_chart(chart_data)

#显示地图
map_data = pd.DataFrame(
    np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4],
    columns=['lat', 'lon'])

st.map(map_data)


#发现地理位置不太满意,换成江苏南京!
smap_data = pd.DataFrame(
    np.random.randn(1000, 2) / [50, 50] + [32.37, 118.4],
    columns=['lat', 'lon'])

st.map(smap_data)


#显示单选框
if st.checkbox('Show dataframe'):
    chart_data = pd.DataFrame(
       np.random.randn(20, 3),
       columns=['a', 'b', 'c'])
    chart_data

option = st.selectbox(
    'Which number do you like best?',
     df['first column'])

'You selected: ', option

#显示按钮
left_column, right_column = st.columns(2)
pressed = left_column.button('Press me?')
if pressed:
    right_column.write("Woohoo!")

expander = st.expander("FAQ")
expander.write("Here you could put in some really, really long explanations...")

#添加一个时间进度条
import time
'Starting a long computation...'

# Add a placeholder
latest_iteration = st.empty()
bar = st.progress(0)

for i in range(100):
  # Update the progress bar with each iteration.
  latest_iteration.text(f'Iteration {i+1}')
  bar.progress(i + 1)
  time.sleep(0.1)

'...and now we\'re done!'

安全性

Web类型程序一定避不开安全性的问题,Streamlit不支持安全认证
即不提供用户名密码等基本的认证方式,查了官方的论坛,目前没有好的办法,官方后续有计划做,但是也是在For Team版本里面,开源版是不提供的。

解决办法:在程序前面加上一个nginx,利用nginx的basic_auth做认证,然后将请求转发给streamlit。这应该是最简单的办法了。
附上nginx的配置,有几个选项必须加,要不然会报ws错误
参考文档


server {
    listen       8501;
    server_name 0.0.0.0;
    location / {
       proxy_pass http://admin-web:8501;
       auth_basic "Please input password";
       auth_basic_user_file /etc/nginx/conf.d/password.db;
       proxy_set_header    Host             $host;
       proxy_set_header    X-Real-IP        $remote_addr;
       proxy_set_header    X-Forwarded-For  $proxy_add_x_forwarded_for;
       proxy_set_header   X-Forwarded-Proto $scheme;
       proxy_buffering    off;
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "upgrade";
       proxy_read_timeout 86400;
       proxy_redirect      default;
      }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

快捷打开方法

如果觉得上述访问的方法有点小麻烦,这里提供一种一键打开——一劳永逸的方法,其实就是将上面的指令打包成bat文件~
在py的文件夹(重要!)下新建一个txt文件,文件名任意,输入以下内容:

chcp 65001
@echo off
call activate
call conda activate 环境名
streamlit run 文件名.py
Pause

第一行的作用是让中文文件名也能被识别。
然后再把后缀改成.bat文件即可,这样双击它即可打开我们的网站。退出网站的方法也和刚才类似,只是如果Ctrl+C的话要多一步确认(直接关闭cmd最快!)。

在线学习&视频

YouTube tutorials
Here’s a list of these YouTube channels about Streamlit:

Streamlit. The official Streamlit YouTube channel with official announcements of the latest features.
Data Professor. My YouTube channel with videos on data science and bioinformatics and a growing playlist of 30 videos on Streamlit.
JCharisTech. Jesse’s YouTube channel with tutorial videos on Python and Streamlit and with a playlist of almost 70 videos on Streamlit.
1littlecoder. AbdulMajed’s YouTube channel with tutorial videos on Python and Streamlit and with a playlist of almost 20 videos on Streamlit.

实战案例

个人项目部署在Streamlit Cloud生成一个公网url随时访问

https://blog.csdn.net/sinat_39629323/article/details/121281071

一个外国人写的streamlit extras,里面有很多有用的小组件

https://extras.streamlit.app/
https://example-time-series-annotation.streamlit.app/

pypi上的streamlit相关的项目

https://pypi.org/search/?q=streamlit

Streamlit创建多页app(这怎么比我想象的要复杂?)

难度中等,较详细:https://www.jianshu.com/p/4af6dba83156
代码:https://github.com/YanAlmeida/streamlit-multipage-framework
https://pypi.org/project/multipage-streamlit/

创建多页--方法一:st-pages

pip install st-pages
https://pypi.org/project/st-pages/
https://github.com/blackary/st_pages

Basic example: https://st-pages.streamlit.app/
Example with sections: https://st-pages-sections.streamlit.app/

创建多页--方法二:定义函数,定义页面,创建导航

import streamlit as st

# 定义页面内容
def main_page():
    st.title("欢迎使用目录应用程序")
    st.write("这是主页。请选择一个选项以导航到其他页面。")

def page_page1():
    st.title("页面1")
    st.write("这是页面1的内容。")

def page_page2():
    st.title("页面2")
    st.write("这是页面2的内容。")

# 创建页面导航
pages = {
    "主页": main_page,
    "页面1": page_page1,
    "页面2": page_page2
}

# 创建侧边栏导航菜单
st.sidebar.title("导航菜单")
selection = st.sidebar.radio("跳转到:", list(pages.keys()))

# 根据选择的选项呈现页面内容
page = pages[selection]
page()

创建多页--方法三:定义主函数,main

import streamlit as st
from pages.page_1 import func_page_1
from pages.page_2 import func_page_2

def main():
    st.sidebar.subheader('Page selection')
    page_selection = st.sidebar.selectbox('Please select a page',
                                          ['Main Page', 'Page 1','Page 2'])
 
    pages_main = {
        'Main Page': main_page,
        'Page 1': run_page_1,
        'Page 2': run_page_2
    }
    # Run selected page
    pages_main[page_selection]()

def main_page():
    st.title('Main Page')
    
def run_page_1():
    func_page_1()
    
def run_page_2():
    func_page_2()
    
    
if __name__ == '__main__':
    main()

除此之外,还要创建两个函数,保存在文件里:
page_1.py:

import streamlit as st
def func_page_1():
   st.title('Page 1')

page_2.py:

import streamlit as st
def func_page_2():
   st.title('Page 2')

https://docs.streamlit.io/library/get-started/multipage-apps/create-a-multipage-app#run-the-multipage-app
https://www.codenong.com/e9759f1f2253f8106d78/
一个写的有点长的中文的多页面APP方法,难度一般
小图标emoji:
https://raw.githubusercontent.com/omnidan/node-emoji/master/lib/emoji.json

posted on 2023-04-27 12:31  chengjon  阅读(984)  评论(0编辑  收藏  举报