项目简介:运行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>
项目运行结果:
好了,记录以下,让我自己记得怎么搞!