记录一次flask+plotly 如何刷新网页进行画图

项目简介:运行Dollarbar

首先按照100万美金ETH 现货进行Kline合成,然后进行画图。当然要先拿到binance的 eth spot 1s数据,然后进行Kline合成!

class DollarBar:
    def __init__(self, mongo_url, database_name, collection_name):
        self.client = MongoClient(mongo_url)
        self.db = self.client[database_name]
        self.collection = self.db[collection_name]
        self.dollar_bars = pd.DataFrame()
        self.tail_bar = pd.DataFrame()
        self.last_processed_time = None
        self.remain_data = pd.DataFrame()
        self.finanl_bars = pd.DataFrame()
        self.threshold = 1000000  # 1 million

    def initialize_data(self):
        recent_documents = self.collection.find().sort('end_time', -1).limit(5000)
        self.init_df = pd.DataFrame(list(recent_documents)).sort_values(by='end_time')
        self.init_df['sell_amount'] = self.init_df['amount'] - self.init_df['buy_amount']
        self.init_df = self.init_df.set_index('datetime')
        self.last_processed_time = self.init_df['end_time'].iloc[-1]  #整个tick 最后一个值


    def process_data(self, data):
        aggregated_data = []
        start_index = 0
        current_amount = 0

        for i in range(len(data)):
            current_amount += data.iloc[i]['amount']
            if current_amount >= self.threshold:
                bar_data = self.create_bar(data, start_index, i, current_amount)
                aggregated_data.append(bar_data)
                start_index = i + 1
                current_amount = 0

        # Check if there's any remaining data
        remaining_data = data.iloc[start_index:] if start_index < len(data) else pd.DataFrame()
     

        return  pd.DataFrame(aggregated_data), remaining_data

    def create_bar(self, data, start_index, end_index, amount):
        return {
            'datetime': data.index[start_index],
            'open': data.iloc[start_index]['open'],
            'close': data.iloc[end_index]['close'],
            'high': data.iloc[start_index:end_index+1]['high'].max(),
            'low': data.iloc[start_index:end_index+1]['low'].min(),
            'volume': data.iloc[start_index:end_index+1]['amount'].sum(),
            'buy_amount': data.iloc[start_index:end_index+1]['buy_amount'].sum(),
            'sell_amount': data.iloc[start_index:end_index+1]['sell_amount'].sum(),
            'amount': amount,
            'count': data.iloc[start_index:end_index+1]['count'].sum(),
            'end_time': data.iloc[end_index]['end_time']
        }

    def create_tail_bar(self, remaining_data):
        if not remaining_data.empty:
            return pd.DataFrame([self.create_bar(remaining_data, 0, len(remaining_data)-1, remaining_data['amount'].sum())])
        return pd.DataFrame()

    def create_initial_dollar_bars(self):
        self.dollar_bars, self.remain_data = self.process_data(self.init_df) # 预留下来的值是个tick 
        # print(f"初始化的remaindata{self.remain_data}")
        self.tail_bar = self.create_tail_bar(self.remain_data) # 这个生成可能有问题
       
        # print(f"初始化的tailbar:{self.tail_bar}")
        self.last_processed_time = self.init_df['end_time'].iloc[-1]  # 整个tick最后一根线

    def update_dollar_bars(self):
        new_data = self.fetch_new_data()
        if not new_data.empty:
            new_data = pd.concat([self.remain_data, new_data])
            self.tail_bar = pd.DataFrame()

            new_bars, self.remain_data = self.process_data(new_data)
            # print(f"更新的newbars{new_bars}")
            # print(f"更新的remaindata{self.remain_data}")
            if not new_bars.empty:
                self.dollar_bars = pd.concat([self.dollar_bars, new_bars]).reset_index(drop=True)
          
            self.tail_bar = self.create_tail_bar(self.remain_data)  #这个也可能有问题


            # print(f"更新的tailbar:{self.tail_bar}")
            self.last_processed_time = new_data['end_time'].iloc[-1]

    def fetch_new_data(self):
        new_documents = self.collection.find({'end_time': {'$gt': self.last_processed_time}}).sort('end_time', 1)
        new_df = pd.DataFrame(list(new_documents))
        if not new_df.empty:
            new_df['sell_amount'] = new_df['amount'] - new_df['buy_amount']
            new_df = new_df.set_index('datetime')
        # print(f"更新的tick_df:{new_df}")
        return new_df
    
    def data_plot(self):
            # 函数用于创建颜色编码的柱状图
        def color_coded_bar(df, y_column, row):
            return go.Bar(
                x=df.index,
                y=df[y_column],
                name=y_column,
                marker_color=df['color'],
                showlegend=False,
                width=20000  # 增加柱状图的宽度,单位是毫秒
            )
        df = self.finanl_bars
        # print(df)
        df['datetime'] = df['datetime'].apply(lambda t:datetime.strptime(t, '%Y-%m-%d_%H-%M-%S'))
        df['datetime'] = pd.to_datetime(df['datetime'], format='%Y-%m-%d_%H-%M-%S')
        df.set_index('datetime', inplace=True)
        df['delta'] = df['buy_amount'] - df['sell_amount']
        df['delta_cum'] = df['delta'].cumsum()
        df['speed'] = df['close'] - df['open']
        df['effect'] =  df['speed']*df['delta']

        df = df[-30:]
        # 计算涨跌
        df['price_change'] = df['close'] - df['close'].shift(1)
        df['color'] = np.where(df['price_change'] >= 0, 'green', 'red')
        print(df)
        # 创建一个带有六个子图的图表
        fig = make_subplots(rows=6, cols=1, 
                            shared_xaxes=True, 
                            vertical_spacing=0.02, 
                            subplot_titles=('Candlestick', 'Speed', 'Effect', 'Volume', 'Delta', 'Cumulative Delta'),
                            row_heights=[0.4, 0.1, 0.1, 0.1, 0.1, 0.1])

    # 添加K线图
        fig.add_trace(go.Candlestick(x=df.index,
                        open=df['open'],
                        high=df['high'],
                        low=df['low'],
                        close=df['close'],
                        name='Price'),
                        row=1, col=1)



        # 添加Speed图
        fig.add_trace(color_coded_bar(df, 'speed', 2), row=2, col=1)

        # 添加Effect图
        fig.add_trace(color_coded_bar(df, 'effect', 3), row=3, col=1)

        # 添加成交量图
        fig.add_trace(color_coded_bar(df, 'amount', 4), row=4, col=1)

        # 添加Delta图
        fig.add_trace(color_coded_bar(df, 'delta', 5), row=5, col=1)

        # 添加累计Delta图
        fig.add_trace(go.Scatter(x=df.index, y=df['delta_cum'], name='Cumulative Delta', line=dict(color='blue')),
                    row=6, col=1)

        # 更新布局
        fig.update_layout(
            title='ETH Price, Speed, Effect, Volume, Delta, and Cumulative Delta Chart',
            height=1200,
            width=1800,
            showlegend=False,
            xaxis_rangeslider_visible=False
        )

        # 更新y轴标题
        fig.update_yaxes(title_text="Price", row=1, col=1)
        fig.update_yaxes(title_text="Speed", row=2, col=1)
        fig.update_yaxes(title_text="Effect", row=3, col=1)
        fig.update_yaxes(title_text="Amount", row=4, col=1)
        fig.update_yaxes(title_text="Delta", row=5, col=1)
        fig.update_yaxes(title_text="Cumulative Delta", row=6, col=1)

        # 更新x轴,只在最底部的子图显示日期标签
        for i in range(1, 6):
            fig.update_xaxes(showticklabels=False, row=i, col=1)
        fig.update_xaxes(title_text="Date", row=6, col=1)
        return fig

    def run(self):
        self.initialize_data()
        self.create_initial_dollar_bars()
        self.update_dollar_bars()
        self.finanl_bars = pd.concat([self.dollar_bars, self.tail_bar]).reset_index(drop=True)
        return self.data_plot()


dollar_bar = DollarBar(mongo_url, database_name, collection_name)

def update_fig():
    fig = dollar_bar.run()
    return fig.to_json()

def periodic_update(interval):
    while True:
        graph_html = update_fig()
        with open('temp.html', 'w') as f:
            f.write(graph_html)
        time.sleep(interval)


@app.route('/get_chart')
def get_chart():
    return update_fig()

@app.route('/')
def home():
    # 读取临时 HTML 文件并传递给模板
    with open('temp.html', 'r') as f:
        graph_html = f.read()
    return render_template('index.html', graph_html=graph_html)


if __name__ == '__main__':
    update_interval = 0.5
    # 创建并启动定时器线程
    thread = Thread(target=periodic_update, args=(update_interval,))
    thread.daemon = True
    thread.start()
    # 运行 Flask 应用
    app.run(host='0.0.0.0', port=5000, threaded=True)

index.html 如何设置,自动更新?

经过100次的调试和chatgpt,终于搞好了,谁叫我前端不懂呢,哈哈?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Plotly Chart</title>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <script>
        function updateChart() {
            fetch('/get_chart')
                .then(response => response.json())
                .then(chartData => {
                    Plotly.react('plotly-chart', chartData.data, chartData.layout);
                })
                .catch(error => console.error('Error fetching chart:', error));
        }

        document.addEventListener('DOMContentLoaded', function() {
            // Initialize the chart
            const initialData = JSON.parse(document.getElementById('initial-data').textContent);
            Plotly.newPlot('plotly-chart', initialData.data, initialData.layout);
            
            // Set timer to update the chart every 3 seconds
            setInterval(updateChart, 500);
        });
    </script>
</head>
<body>
    <h1>My Plotly Chart</h1>
    <div id="plotly-chart"></div>
    <script id="initial-data" type="application/json">
        {{ graph_html|safe }}
    </script>
</body>
</html>

项目运行结果:

可自动刷新的Dollarbar,更看得清楚多空了
好了,记录以下,让我自己记得怎么搞!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值