support draw chart

This commit is contained in:
blade 2025-08-01 16:18:36 +08:00
parent 4ee8658d89
commit 5a45449b87
5 changed files with 541 additions and 29 deletions

Binary file not shown.

View File

@ -0,0 +1,459 @@
from core.db.db_huge_volume_data import DBHugeVolumeData
from core.utils import timestamp_to_datetime, transform_date_time_to_timestamp
import matplotlib.pyplot as plt
import seaborn as sns
from openpyxl import Workbook
from openpyxl.drawing.image import Image
from PIL import Image as PILImage
import logging
from datetime import datetime
import pandas as pd
import os
import re
import openpyxl
from openpyxl.styles import Font
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
sns.set_theme(style="whitegrid")
# 设置中文
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
class HugeVolumeChart:
def __init__(
self,
data: pd.DataFrame,
output_folder: str = "./output/huge_volume_statistics/",
):
"""
初始化
data: 数据
data中的列名为
symbol: 币种
bar: 周期
window_size: 窗口大小
huge_volume: 是否巨量
volume_ratio_percentile_10: 10%分位数
volume_ratio_percentile_10_mean: 10%分位数平均值
price_type: 价格类型
next_period: 下一个周期
average_return: 平均回报
max_return: 最大回报
min_return: 最小回报
rise_count: 上涨次数
rise_ratio: 上涨比例
fall_count: 下跌次数
fall_ratio: 下跌比例
draw_count: 持平次数
draw_ratio: 持平比例
total_count: 总次数
output_folder: 输出文件夹
"""
self.data = data
# remove 1D bar
self.data = self.data[self.data["bar"] != "1D"]
self.data.reset_index(drop=True, inplace=True)
self.output_folder = output_folder
os.makedirs(self.output_folder, exist_ok=True)
self.temp_dir = os.path.join(self.output_folder, "temp")
os.makedirs(self.temp_dir, exist_ok=True)
self.symbol_list = self.data["symbol"].unique().tolist()
# sort symbol_list
self.symbol_list.sort()
self.bar_list = self.data["bar"].unique().tolist()
self.bar_list.sort()
self.window_size_list = self.data["window_size"].unique().tolist()
self.window_size_list.sort()
self.next_period_list = self.data["next_period"].unique().tolist()
self.next_period_list.sort()
self.volume_ratio_percentile_10_list = (
self.data["volume_ratio_percentile_10"].unique().tolist()
)
self.volume_ratio_percentile_10_list.sort()
self.price_type_list = self.data["price_type"].unique().tolist()
self.price_type_list.sort()
def plot_entrance(self, include_heatmap: bool = True, include_line: bool = True):
"""
绘制上涨下跌图入口
"""
charts_dict = {}
if include_heatmap:
heatmap_plot_dict = self.plot_heatmap_entrance()
if include_line:
line_plot_dict = self.plot_line_chart_entrance()
if include_line:
charts_dict.update(line_plot_dict)
if include_heatmap:
charts_dict.update(heatmap_plot_dict)
return charts_dict
def plot_line_chart_entrance(self):
"""
绘制折线图入口
"""
charts_dict = {}
# 根据price_type_list得到各个price_type的平均rise_ratio平均fall_ratio平均draw_ratio, 平均average_return
total_chart_path = self.plot_pice_rise_fall(data=self.data, prefix="总体")
charts_dict["总体"] = {"总体": total_chart_path}
self.plot_window_size_rise_fall(charts_dict=charts_dict)
self.plot_window_size_bar_rise_fall(charts_dict=charts_dict)
self.plot_window_size_bar_next_period_rise_fall(charts_dict=charts_dict)
self.plot_symbol_rise_fall(charts_dict=charts_dict)
self.plot_symbol_bar_rise_fall(charts_dict=charts_dict)
self.plot_symbol_bar_window_size_rise_fall(charts_dict=charts_dict)
self.plot_symbol_bar_window_size_next_period_rise_fall(charts_dict=charts_dict)
# self.plot_symbol_bar_window_size_volume_ratio_percentile_10_mean_rise_fall(charts_dict=charts_dict)
# self.plot_symbol_bar_window_size_volume_ratio_percentile_10_mean_next_period_rise_fall(charts_dict=charts_dict)
self.output_excel(chart_type="line_chart", charts_dict=charts_dict)
return charts_dict
def plot_heatmap_entrance(self):
"""
绘制热力图入口
"""
charts_dict = {}
self.plot_symbol_heatmap(charts_dict=charts_dict, ratio_column="rise_ratio", title=f"Rise Ratio Heatmap by Window Size and Bar")
self.plot_symbol_heatmap(charts_dict=charts_dict, ratio_column="fall_ratio", title=f"Fall Ratio Heatmap by Window Size and Bar")
self.plot_symbol_heatmap(charts_dict=charts_dict, ratio_column="average_return", title=f"Average Return Heatmap by Window Size and Bar")
self.output_excel(chart_type="heatmap_chart", charts_dict=charts_dict)
return charts_dict
def plot_symbol_heatmap(self,
charts_dict: dict,
ratio_column: str = "rise_ratio",
title: str = "Rise Ratio Heatmap by Window Size and Bar"
):
"""
绘制symbol热力图
"""
for symbol in self.symbol_list:
charts_dict[f"{symbol}_{ratio_column}_heatmap"] = {}
for price_type in self.price_type_list:
logging.info(f"绘制{symbol} {price_type} {ratio_column}热力图")
df = self.data[(self.data["symbol"] == symbol) & (self.data["price_type"] == price_type)]
pivot_table = df.pivot_table(values=ratio_column, index='window_size', columns='bar', aggfunc='mean')
plt.figure(figsize=(10, 6))
# 热力图以红色渐变为主,红色表示高,绿色表示低
sns.heatmap(pivot_table, annot=True, cmap='RdYlGn_r', fmt='.3f')
plt.xlabel('Period')
plt.ylabel('Window Size')
plt.title(f"{title} {price_type}")
# plt.show()
chart_path = os.path.join(self.temp_dir, f'{symbol}_{price_type}_{ratio_column}_heatmap.png')
plt.savefig(chart_path, bbox_inches='tight', dpi=100)
plt.close()
charts_dict[f"{symbol}_{ratio_column}_heatmap"][f"{symbol}_{price_type}_{ratio_column}_heatmap"] = chart_path
def plot_window_size_rise_fall(self, charts_dict: dict):
"""
不区分symbol, 绘制window_size上涨下跌图
"""
charts_dict["window_size"] = {}
for window_size in self.window_size_list:
data = self.data[self.data["window_size"] == window_size]
chart_path = self.plot_pice_rise_fall(data, prefix=f"window_size_{window_size}")
charts_dict["window_size"][f"window_size_{window_size}"] = chart_path
def plot_window_size_bar_rise_fall(self, charts_dict: dict):
"""
不区分symbol, 根据window_size绘制bar上涨下跌图
"""
charts_dict["window_size_bar"] = {}
for window_size in self.window_size_list:
for bar in self.bar_list:
data = self.data[
(self.data["window_size"] == window_size)
& (self.data["bar"] == bar)
]
chart_path = self.plot_pice_rise_fall(
data, prefix=f"window_size_{window_size}_bar_{bar}"
)
charts_dict["window_size_bar"][f"window_size_{window_size}_bar_{bar}"] = chart_path
def plot_window_size_bar_next_period_rise_fall(self, charts_dict: dict):
"""
不区分symbol, 根据window_size, bar, next_period上涨下跌图
"""
charts_dict["window_size_bar_period"] = {}
for window_size in self.window_size_list:
for bar in self.bar_list:
for next_period in self.next_period_list:
data = self.data[
(self.data["window_size"] == window_size)
& (self.data["bar"] == bar)
& (self.data["next_period"] == next_period)
]
chart_path = self.plot_pice_rise_fall(
data,
prefix=f"window_size_{window_size}_bar_{bar}_next_period_{next_period}"
)
charts_dict["window_size_bar_period"][f"window_size_{window_size}_bar_{bar}_next_period_{next_period}"] = chart_path
def plot_symbol_rise_fall(self, charts_dict: dict):
"""
区分symbol, 绘制symbol上涨下跌图
"""
for symbol in self.symbol_list:
charts_dict[f"{symbol}_总体"] = {}
data = self.data[self.data["symbol"] == symbol]
chart_path = self.plot_pice_rise_fall(data, prefix=symbol)
charts_dict[f"{symbol}_总体"][symbol] = chart_path
def plot_symbol_bar_rise_fall(self, charts_dict: dict):
"""
区分symbol, bar, 绘制symbol上涨下跌图
"""
for symbol in self.symbol_list:
charts_dict[f"{symbol}_bar"] = {}
for bar in self.bar_list:
data = self.data[
(self.data["symbol"] == symbol) & (self.data["bar"] == bar)
]
chart_path = self.plot_pice_rise_fall(data, prefix=f"{symbol}_{bar}")
charts_dict[f"{symbol}_bar"][f"{symbol}_{bar}"] = chart_path
def plot_symbol_bar_window_size_rise_fall(self, charts_dict: dict):
"""
区分symbol, bar, window_size, 绘制symbol上涨下跌图
"""
for symbol in self.symbol_list:
charts_dict[f"{symbol}_bar_window_size"] = {}
for bar in self.bar_list:
for window_size in self.window_size_list:
data = self.data[
(self.data["symbol"] == symbol)
& (self.data["bar"] == bar)
& (self.data["window_size"] == window_size)
]
chart_path = self.plot_pice_rise_fall(
data, prefix=f"{symbol}_{bar}_ws_{window_size}"
)
charts_dict[f"{symbol}_bar_window_size"][f"{symbol}_{bar}_ws_{window_size}"] = chart_path
def plot_symbol_bar_window_size_next_period_rise_fall(self, charts_dict: dict):
"""
区分symbol, bar, window_size, next_period, 绘制symbol上涨下跌图
"""
for symbol in self.symbol_list:
charts_dict[f"{symbol}_bar_ws_period"] = {}
for bar in self.bar_list:
for window_size in self.window_size_list:
for next_period in self.next_period_list:
data = self.data[
(self.data["symbol"] == symbol)
& (self.data["bar"] == bar)
& (self.data["window_size"] == window_size)
& (self.data["next_period"] == next_period)
]
chart_path = self.plot_pice_rise_fall(
data,
prefix=f"{symbol}_{bar}_ws_{window_size}_next_period_{next_period}"
)
charts_dict[f"{symbol}_bar_ws_period"][f"{symbol}_{bar}_ws_{window_size}_next_period_{next_period}"] = chart_path
def plot_symbol_bar_window_size_volume_ratio_percentile_10_mean_rise_fall(self, charts_dict: dict):
"""
区分symbol, bar, window_size, volume_ratio_percentile_10_mean, 绘制symbol上涨下跌图
"""
for symbol in self.symbol_list:
charts_dict[f"{symbol}_bar_window_size_vol_per"] = {}
for bar in self.bar_list:
for window_size in self.window_size_list:
for (
volume_ratio_percentile_10
) in self.volume_ratio_percentile_10_list:
data = self.data[
(self.data["symbol"] == symbol)
& (self.data["bar"] == bar)
& (self.data["window_size"] == window_size)
& (
self.data["volume_ratio_percentile_10"]
== volume_ratio_percentile_10
)
]
chart_path = self.plot_pice_rise_fall(
data,
prefix=f"{symbol}_{bar}_ws_{window_size}_vol_per_{volume_ratio_percentile_10}"
)
charts_dict[f"{symbol}_bar_window_size_vol_per"][f"{symbol}_{bar}_ws_{window_size}_vol_per_{volume_ratio_percentile_10}"] = chart_path
def plot_symbol_bar_window_size_volume_ratio_percentile_10_mean_next_period_rise_fall(
self,
charts_dict: dict,
):
"""
区分symbol, bar, window_size, volume_ratio_percentile_10_mean, next_period, 绘制symbol上涨下跌图
"""
for symbol in self.symbol_list:
charts_dict[f"{symbol}_bar_ws_vol_period"] = {}
for bar in self.bar_list:
for window_size in self.window_size_list:
for (
volume_ratio_percentile_10
) in self.volume_ratio_percentile_10_list:
for next_period in self.next_period_list:
data = self.data[
(self.data["symbol"] == symbol)
& (self.data["bar"] == bar)
& (self.data["window_size"] == window_size)
& (
self.data["volume_ratio_percentile_10"]
== volume_ratio_percentile_10
)
& (self.data["next_period"] == next_period)
]
chart_path = self.plot_pice_rise_fall(
data,
prefix=f"{symbol}_{bar}_ws_{window_size}_vol_per_{volume_ratio_percentile_10}_next_period_{next_period}"
)
charts_dict[f"{symbol}_bar_ws_vol_period"][f"{symbol}_{bar}_ws_{window_size}_vol_per_{volume_ratio_percentile_10}_next_period_{next_period}"] = chart_path
def plot_pice_rise_fall(self, data: pd.DataFrame, prefix: str = ""):
"""
绘制价格上涨下跌图
"""
logging.info(f"绘制价格上涨下跌图: {prefix}")
# 根据price_type_list得到各个price_type的平均rise_ratio平均fall_ratio平均draw_ratio, 平均average_return
price_type_data_dict = {}
for price_type in self.price_type_list:
filtered_data = data[data["price_type"] == price_type]
average_rise_ratio = filtered_data["rise_ratio"].mean()
average_fall_ratio = filtered_data["fall_ratio"].mean()
average_draw_ratio = filtered_data["draw_ratio"].mean()
average_average_return = filtered_data["average_return"].mean()
price_type_data_dict[price_type] = {
"average_rise_ratio": average_rise_ratio,
"average_fall_ratio": average_fall_ratio,
"average_draw_ratio": average_draw_ratio,
"average_average_return": average_average_return,
}
# 准备数据用于绘图
price_types = list(price_type_data_dict.keys())
rise_ratios = [
price_type_data_dict[pt]["average_rise_ratio"] for pt in price_types
]
fall_ratios = [
price_type_data_dict[pt]["average_fall_ratio"] for pt in price_types
]
draw_ratios = [
price_type_data_dict[pt]["average_draw_ratio"] for pt in price_types
]
avg_returns = [
price_type_data_dict[pt]["average_average_return"] for pt in price_types
]
# 创建子图保持2x2布局
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 12))
# 绘制上涨比例
bars1 = ax1.bar(price_types, rise_ratios, color="green", alpha=0.7)
ax1.set_title(f"{prefix}总体平均上涨比例")
ax1.set_ylabel("上涨比例")
ax1.tick_params(axis="x", rotation=0)
ax1.bar_label(bars1, fmt="%.2f")
# 绘制下跌比例
bars2 = ax2.bar(price_types, fall_ratios, color="red", alpha=0.7)
ax2.set_title(f"{prefix}平均下跌比例")
ax2.set_ylabel("下跌比例")
ax2.tick_params(axis="x", rotation=0)
ax2.bar_label(bars2, fmt="%.2f")
# 绘制持平比例
bars3 = ax3.bar(price_types, draw_ratios, color="gray", alpha=0.7)
ax3.set_title(f"{prefix}平均持平比例")
ax3.set_ylabel("持平比例")
ax3.tick_params(axis="x", rotation=0)
ax3.bar_label(bars3, fmt="%.2f")
# 绘制平均回报
bars4 = ax4.bar(price_types, avg_returns, color="blue", alpha=0.7)
ax4.set_title(f"{prefix}平均回报")
ax4.set_ylabel("平均回报")
ax4.tick_params(axis="x", rotation=0)
ax4.bar_label(bars4, fmt="%.2f")
# 调整布局增加底部空间和垂直间距以显示完整的x轴标签
plt.tight_layout()
plt.subplots_adjust(bottom=0.15, hspace=0.4)
# plt.show()
chart_path = os.path.join(self.temp_dir, f'{prefix}.png')
plt.savefig(chart_path, bbox_inches='tight', dpi=100)
plt.close()
return chart_path
def output_excel(self, chart_type: str, charts_dict: dict):
"""
输出Excel文件包含所有图表
charts_dict: 图表数据字典格式为
{
"sheet_name": {
"chart_name": "chart_path"
}
}
"""
logging.info(f"输出Excel文件包含所有{chart_type}图表")
file_name = f"huge_volume_{chart_type}_{datetime.now().strftime('%Y%m%d%H%M%S')}.xlsx"
file_path = os.path.join(self.output_folder, file_name)
# Create Excel file and worksheet
wb = Workbook()
wb.remove(wb.active) # Remove default sheet
for sheet_name, chart_data_dict in charts_dict.items():
try:
ws = wb.create_sheet(title=sheet_name)
row_offset = 1
for chart_name, chart_path in chart_data_dict.items():
# Load image to get dimensions
with PILImage.open(chart_path) as img:
width_px, height_px = img.size
# Convert pixel height to Excel row height (approximate: 1 point = 1.333 pixels, 1 row ≈ 15 points for 20 pixels)
pixels_per_point = 1.333
points_per_row = 15 # Default row height in points
pixels_per_row = (
points_per_row * pixels_per_point
) # ≈ 20 pixels per row
chart_rows = max(
10, int(height_px / pixels_per_row)
) # Minimum 10 rows for small charts
# Add chart title
# 支持中文标题
ws[f"A{row_offset}"] = chart_name.encode("utf-8").decode("utf-8")
ws[f"A{row_offset}"].font = openpyxl.styles.Font(bold=True, size=12)
row_offset += 2 # Add 2 rows for title and spacing
# Insert chart image
img = Image(chart_path)
ws.add_image(img, f"A{row_offset}")
# Update row offset (chart height + padding)
row_offset += chart_rows + 5 # Add 5 rows for padding between charts
except Exception as e:
logging.error(f"输出Excel Sheet {sheet_name} 失败: {e}")
continue
# Save Excel file
wb.save(file_path)
print(f"Excel file saved as {file_path}")
for sheet_name, chart_data_dict in charts_dict.items():
for chart_name, chart_path in chart_data_dict.items():
try:
os.remove(chart_path)
except Exception as e:
logging.error(f"删除临时文件失败: {e}")

View File

@ -1,4 +1,5 @@
from core.biz.huge_volume import HugeVolume
from core.biz.huge_volume_chart import HugeVolumeChart
from core.db.db_market_data import DBMarketData
from core.db.db_huge_volume_data import DBHugeVolumeData
from core.utils import timestamp_to_datetime, transform_date_time_to_timestamp
@ -35,7 +36,9 @@ class HugeVolumeMain:
self.output_folder = "./output/huge_volume_statistics/"
os.makedirs(self.output_folder, exist_ok=True)
def batch_initial_detect_volume_spike(self, window_size: int = 50, start: str = None):
def batch_initial_detect_volume_spike(
self, window_size: int = 50, start: str = None
):
for symbol in self.market_data_main.symbols:
for bar in self.market_data_main.bars:
if start is None:
@ -43,7 +46,12 @@ class HugeVolumeMain:
"initial_date", "2025-05-01 00:00:00"
)
data = self.detect_volume_spike(
symbol, bar, window_size, start, only_output_huge_volume=False, is_update=False
symbol,
bar,
window_size,
start,
only_output_huge_volume=False,
is_update=False,
)
if data is not None and len(data) > 0:
logging.info(f"此次初始化巨量交易数据: {len(data)}")
@ -66,16 +74,22 @@ class HugeVolumeMain:
)
if end is None:
end = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
logging.info(f"开始处理巨量交易数据: {symbol} {bar} 窗口大小: {window_size}{start}{end}")
logging.info(
f"开始处理巨量交易数据: {symbol} {bar} 窗口大小: {window_size}{start}{end}"
)
data = self.db_market_data.query_market_data_by_symbol_bar(
symbol, bar, start, end
)
if data is None:
logging.warning(f"获取行情数据失败: {symbol} {bar} 窗口大小: {window_size}{start}{end}")
logging.warning(
f"获取行情数据失败: {symbol} {bar} 窗口大小: {window_size}{start}{end}"
)
return None
else:
if len(data) == 0:
logging.warning(f"获取行情数据为空: {symbol} {bar} 窗口大小: {window_size}{start}{end}")
logging.warning(
f"获取行情数据为空: {symbol} {bar} 窗口大小: {window_size}{start}{end}"
)
return None
else:
if isinstance(data, list):
@ -93,10 +107,8 @@ class HugeVolumeMain:
if data is not None:
if is_update:
for index, row in data.iterrows():
exist_huge_volume_data = (
self.db_huge_volume_data.query_data_by_symbol_bar_window_size_timestamp(
symbol, bar, window_size, row["timestamp"]
)
exist_huge_volume_data = self.db_huge_volume_data.query_data_by_symbol_bar_window_size_timestamp(
symbol, bar, window_size, row["timestamp"]
)
if exist_huge_volume_data is not None:
# remove the exist_huge_volume_data from data
@ -152,7 +164,9 @@ class HugeVolumeMain:
else:
logging.info(f"此次更新巨量交易数据为空")
except Exception as e:
logging.error(f"更新巨量交易数据失败: {symbol} {bar} 窗口大小: {window_size}{earliest_date_time}{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: {e}")
logging.error(
f"更新巨量交易数据失败: {symbol} {bar} 窗口大小: {window_size}{earliest_date_time}{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: {e}"
)
def get_seconds_by_bar(self, bar: str):
"""
@ -214,26 +228,29 @@ class HugeVolumeMain:
if end is None:
end = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
periods_text = ", ".join([str(period) for period in periods])
logging.info(f"开始计算巨量出现后,之后{periods_text}个周期,上涨或下跌的比例: {symbol} {bar} 窗口大小: {window_size}{start}{end}")
logging.info(
f"开始计算巨量出现后,之后{periods_text}个周期,上涨或下跌的比例: {symbol} {bar} 窗口大小: {window_size}{start}{end}"
)
volume_statistics_data = (
self.db_huge_volume_data.query_huge_volume_data_by_symbol_bar_window_size(
symbol, bar, window_size, start, end
)
)
if volume_statistics_data is None or len(volume_statistics_data) == 0:
logging.warning(f"获取巨量交易数据为空: {symbol} {bar} 窗口大小: {window_size}{start}{end}")
logging.warning(
f"获取巨量交易数据为空: {symbol} {bar} 窗口大小: {window_size}{start}{end}"
)
return None
else:
if isinstance(volume_statistics_data, list):
volume_statistics_data = pd.DataFrame(volume_statistics_data)
elif isinstance(volume_statistics_data, dict):
volume_statistics_data = pd.DataFrame([volume_statistics_data])
if (
volume_statistics_data is not None
and len(volume_statistics_data) > 0
):
if volume_statistics_data is not None and len(volume_statistics_data) > 0:
# 根据timestamp排序
volume_statistics_data = volume_statistics_data.sort_values(by="timestamp", ascending=True)
volume_statistics_data = volume_statistics_data.sort_values(
by="timestamp", ascending=True
)
volume_statistics_data["window_size"] = window_size
volume_statistics_data = volume_statistics_data[
[
@ -279,7 +296,11 @@ class HugeVolumeMain:
huge_volume_data_list = []
result_data_list = []
window_size_list = WINDOW_SIZE.get("window_sizes", None)
if window_size_list is None or not isinstance(window_size_list, list) or len(window_size_list) == 0:
if (
window_size_list is None
or not isinstance(window_size_list, list)
or len(window_size_list) == 0
):
window_size_list = [50, 80, 100, 120]
for symbol in self.market_data_main.symbols:
@ -296,14 +317,14 @@ class HugeVolumeMain:
total_huge_volume_data = total_huge_volume_data.reset_index(drop=True)
total_result_data = total_result_data.reset_index(drop=True)
current_date = datetime.now().strftime("%Y%m%d%H%M%S")
file_name = (
f"next_periods_rise_or_fall_{current_date}.xlsx"
)
file_name = f"next_periods_rise_or_fall_{current_date}.xlsx"
try:
with pd.ExcelWriter(
os.path.join(self.output_folder, file_name)
) as writer:
total_huge_volume_data.to_excel(writer, sheet_name="details", index=False)
total_huge_volume_data.to_excel(
writer, sheet_name="details", index=False
)
total_result_data.to_excel(
writer, sheet_name="next_periods_statistics", index=False
)
@ -311,10 +332,29 @@ class HugeVolumeMain:
logging.error(f"导出Excel文件失败: {e}")
return total_huge_volume_data, total_result_data
def plot_huge_volume_data(
self,
data_file_path: str,
sheet_name: str = "next_periods_statistics",
output_folder: str = "./output/huge_volume_statistics/",
):
os.makedirs(output_folder, exist_ok=True)
huge_volume_data = pd.read_excel(data_file_path, sheet_name=sheet_name)
huge_volume_chart = HugeVolumeChart(huge_volume_data)
include_heatmap = True
include_line = False
huge_volume_chart.plot_entrance(
include_heatmap=include_heatmap, include_line=include_line
)
def batch_initial_detect_volume_spike(threshold: float = 2.0):
window_sizes = WINDOW_SIZE.get("window_sizes", None)
if window_sizes is None or not isinstance(window_sizes, list) or len(window_sizes) == 0:
if (
window_sizes is None
or not isinstance(window_sizes, list)
or len(window_sizes) == 0
):
window_sizes = [50, 80, 100, 120]
huge_volume_main = HugeVolumeMain(threshold)
for window_size in window_sizes:
@ -326,7 +366,11 @@ def batch_initial_detect_volume_spike(threshold: float = 2.0):
def batch_update_volume_spike(threshold: float = 2.0):
window_sizes = WINDOW_SIZE.get("window_sizes", None)
if window_sizes is None or not isinstance(window_sizes, list) or len(window_sizes) == 0:
if (
window_sizes is None
or not isinstance(window_sizes, list)
or len(window_sizes) == 0
):
window_sizes = [50, 80, 100, 120]
huge_volume_main = HugeVolumeMain(threshold)
for window_size in window_sizes:
@ -337,4 +381,12 @@ if __name__ == "__main__":
# batch_initial_detect_volume_spike(threshold=2.0)
# batch_update_volume_spike(threshold=2.0)
huge_volume_main = HugeVolumeMain(threshold=2.0)
huge_volume_main.batch_next_periods_rise_or_fall(output_excel=True)
# huge_volume_main.batch_next_periods_rise_or_fall(output_excel=True)
data_file_path = "./output/huge_volume_statistics/next_periods_rise_or_fall_stat_20250731200304.xlsx"
sheet_name = "next_periods_statistics"
output_folder = "./output/huge_volume_statistics/"
huge_volume_main.plot_huge_volume_data(
data_file_path=data_file_path,
sheet_name=sheet_name,
output_folder=output_folder,
)

View File

@ -4,3 +4,4 @@ requests>=2.25.0
sqlalchemy >= 2.0.41
pymysql >= 1.1.1
wechatpy >= 1.8.18
seaborn >= 0.13.2

View File

@ -1,18 +1,18 @@
select * from crypto_market_data
WHERE symbol='XCH-USDT-SWAP' and bar='5m' #and date_time > '2025-07-01'
WHERE symbol='XCH-USDT' and bar='5m' #and date_time > '2025-07-01'
order by timestamp desc;
delete FROM crypto_market_data where symbol != 'XCH-USDT';
select * from crypto_trade_data
where symbol='BTC-USDT'
where symbol='XCH-USDT'
order by ts desc;
select count(1) from crypto_trade_data;
select * from crypto_huge_volume
WHERE symbol='XCH-USDT' and bar='5m' and date_time > '2025-07-26'
order by timestamp desc;
WHERE symbol='XCH-USDT' and bar='5m' and window_size = 80 and date_time > '2025-07-26'
order by timestamp;
select * from crypto_huge_volume
WHERE symbol='XCH-USDT-SWAP' and bar='5m' and date_time > '2025-07-26'