support get huge volume by different window sizes
This commit is contained in:
parent
ca2efb002e
commit
5bc9b2b8c7
|
|
@ -70,6 +70,8 @@ MONITOR_CONFIG = {
|
|||
}
|
||||
}
|
||||
|
||||
WINDOW_SIZE = {"window_sizes":[50, 80, 100, 120]}
|
||||
|
||||
BAR_THRESHOLD = {
|
||||
"5m": 1000 * 60 * 5,
|
||||
"15m": 1000 * 60 * 15,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class DBHugeVolumeData:
|
|||
self.columns = [
|
||||
"symbol",
|
||||
"bar",
|
||||
"window_size",
|
||||
"timestamp",
|
||||
"date_time",
|
||||
"open",
|
||||
|
|
@ -74,6 +75,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None,
|
||||
additional_conditions: Optional[List[str]] = None
|
||||
|
|
@ -82,6 +84,7 @@ class DBHugeVolumeData:
|
|||
构建查询条件
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param start: 开始时间
|
||||
:param end: 结束时间
|
||||
:param additional_conditions: 额外的查询条件
|
||||
|
|
@ -96,7 +99,9 @@ class DBHugeVolumeData:
|
|||
if bar:
|
||||
conditions.append("bar = :bar")
|
||||
condition_dict["bar"] = bar
|
||||
|
||||
if window_size:
|
||||
conditions.append("window_size = :window_size")
|
||||
condition_dict["window_size"] = window_size
|
||||
# 处理时间参数
|
||||
start_timestamp = self._process_time_parameter(start)
|
||||
end_timestamp = self._process_time_parameter(end)
|
||||
|
|
@ -166,53 +171,57 @@ class DBHugeVolumeData:
|
|||
|
||||
self.db_manager.insert_data_to_mysql_simple(df)
|
||||
|
||||
def query_latest_data(self, symbol: str, bar: str) -> Optional[Dict[str, Any]]:
|
||||
def query_latest_data(self, symbol: str, bar: str, window_size: int) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
查询最新巨量交易数据
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:return: 最新数据记录或None
|
||||
"""
|
||||
sql = """
|
||||
SELECT * FROM crypto_huge_volume
|
||||
WHERE symbol = :symbol AND bar = :bar
|
||||
WHERE symbol = :symbol AND bar = :bar AND window_size = :window_size
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 1
|
||||
"""
|
||||
condition_dict = {"symbol": symbol, "bar": bar}
|
||||
condition_dict = {"symbol": symbol, "bar": bar, "window_size": window_size}
|
||||
return self.db_manager.query_data(sql, condition_dict, return_multi=False)
|
||||
|
||||
def query_data_by_symbol_bar_timestamp(self, symbol: str, bar: str, timestamp: int) -> Optional[Dict[str, Any]]:
|
||||
def query_data_by_symbol_bar_window_size_timestamp(self, symbol: str, bar: str, window_size: int, timestamp: int) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
根据交易对、K线周期和时间戳查询巨量交易数据
|
||||
根据交易对、K线周期, 窗口大小和时间戳查询巨量交易数据
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param timestamp: 时间戳
|
||||
:return: 数据记录或None
|
||||
"""
|
||||
sql = """
|
||||
SELECT * FROM crypto_huge_volume
|
||||
WHERE symbol = :symbol AND bar = :bar AND timestamp = :timestamp
|
||||
WHERE symbol = :symbol AND bar = :bar AND window_size = :window_size AND timestamp = :timestamp
|
||||
"""
|
||||
condition_dict = {"symbol": symbol, "bar": bar, "timestamp": timestamp}
|
||||
condition_dict = {"symbol": symbol, "bar": bar, "window_size": window_size, "timestamp": timestamp}
|
||||
return self.db_manager.query_data(sql, condition_dict, return_multi=False)
|
||||
|
||||
def query_huge_volume_data_by_symbol_bar(
|
||||
def query_huge_volume_data_by_symbol_bar_window_size(
|
||||
self,
|
||||
symbol: str,
|
||||
bar: str,
|
||||
window_size: int,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
"""
|
||||
根据交易对和K线周期查询巨量交易数据
|
||||
根据交易对、K线周期和窗口大小查询巨量交易数据
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param start: 开始时间
|
||||
:param end: 结束时间
|
||||
:return: 数据记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(symbol, bar, start, end)
|
||||
conditions, condition_dict = self._build_query_conditions(symbol, bar, window_size, start, end)
|
||||
|
||||
where_clause = " AND ".join(conditions) if conditions else "1=1"
|
||||
sql = f"""
|
||||
|
|
@ -227,6 +236,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
|
|
@ -234,12 +244,13 @@ class DBHugeVolumeData:
|
|||
查询巨量交易记录(只返回huge_volume=1的记录)
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param start: 开始时间
|
||||
:param end: 结束时间
|
||||
:return: 巨量交易记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(
|
||||
symbol, bar, start, end, additional_conditions=["huge_volume = 1"]
|
||||
symbol, bar, window_size, start, end, additional_conditions=["huge_volume = 1"]
|
||||
)
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
|
@ -255,6 +266,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
|
|
@ -262,12 +274,13 @@ class DBHugeVolumeData:
|
|||
查询80/20量价尖峰记录(只返回volume_80_20_price_spike=1的记录)
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param start: 开始时间
|
||||
:param end: 结束时间
|
||||
:return: 80/20量价尖峰记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(
|
||||
symbol, bar, start, end, additional_conditions=["volume_80_20_price_spike = 1"]
|
||||
symbol, bar, window_size, start, end, additional_conditions=["volume_80_20_price_spike = 1"]
|
||||
)
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
|
@ -283,6 +296,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
|
|
@ -290,12 +304,13 @@ class DBHugeVolumeData:
|
|||
查询90/10量价尖峰记录(只返回volume_90_10_price_spike=1的记录)
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param start: 开始时间
|
||||
:param end: 结束时间
|
||||
:return: 90/10量价尖峰记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(
|
||||
symbol, bar, start, end, additional_conditions=["volume_90_10_price_spike = 1"]
|
||||
symbol, bar, window_size, start, end, additional_conditions=["volume_90_10_price_spike = 1"]
|
||||
)
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
|
@ -311,6 +326,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
|
|
@ -318,12 +334,13 @@ class DBHugeVolumeData:
|
|||
查询价格达到80%分位数高点的记录(只返回price_80_high=1的记录)
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param start: 开始时间
|
||||
:param end: 结束时间
|
||||
:return: 价格80%分位数高点记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(
|
||||
symbol, bar, start, end, additional_conditions=["price_80_high = 1"]
|
||||
symbol, bar, window_size, start, end, additional_conditions=["price_80_high = 1"]
|
||||
)
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
|
@ -339,6 +356,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
|
|
@ -351,7 +369,7 @@ class DBHugeVolumeData:
|
|||
:return: 价格20%分位数低点记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(
|
||||
symbol, bar, start, end, additional_conditions=["price_20_low = 1"]
|
||||
symbol, bar, window_size, start, end, additional_conditions=["price_20_low = 1"]
|
||||
)
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
|
@ -367,6 +385,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
|
|
@ -379,7 +398,7 @@ class DBHugeVolumeData:
|
|||
:return: 价格90%分位数高点记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(
|
||||
symbol, bar, start, end, additional_conditions=["price_90_high = 1"]
|
||||
symbol, bar, window_size, start, end, additional_conditions=["price_90_high = 1"]
|
||||
)
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
|
@ -395,6 +414,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
|
|
@ -407,7 +427,7 @@ class DBHugeVolumeData:
|
|||
:return: 价格10%分位数低点记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(
|
||||
symbol, bar, start, end, additional_conditions=["price_10_low = 1"]
|
||||
symbol, bar, window_size, start, end, additional_conditions=["price_10_low = 1"]
|
||||
)
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
|
@ -423,6 +443,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
|
|
@ -430,11 +451,12 @@ class DBHugeVolumeData:
|
|||
获取巨量交易统计摘要
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param start: 开始时间
|
||||
:param end: 结束时间
|
||||
:return: 统计摘要或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(symbol, bar, start, end)
|
||||
conditions, condition_dict = self._build_query_conditions(symbol, bar, window_size, start, end)
|
||||
|
||||
where_clause = " AND ".join(conditions) if conditions else "1=1"
|
||||
sql = f"""
|
||||
|
|
@ -461,17 +483,19 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
limit: int = 10
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
"""
|
||||
获取成交量尖峰最高的记录
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param limit: 返回记录数量
|
||||
:return: 成交量尖峰记录列表或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(
|
||||
symbol, bar, additional_conditions=["huge_volume = 1"]
|
||||
symbol, bar, window_size, additional_conditions=["huge_volume = 1"]
|
||||
)
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
|
@ -489,6 +513,7 @@ class DBHugeVolumeData:
|
|||
self,
|
||||
symbol: Optional[str] = None,
|
||||
bar: Optional[str] = None,
|
||||
window_size: Optional[int] = None,
|
||||
start: Optional[Union[str, int]] = None,
|
||||
end: Optional[Union[str, int]] = None
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
|
|
@ -496,11 +521,12 @@ class DBHugeVolumeData:
|
|||
获取分位数统计信息
|
||||
:param symbol: 交易对
|
||||
:param bar: K线周期
|
||||
:param window_size: 窗口大小
|
||||
:param start: 开始时间
|
||||
:param end: 结束时间
|
||||
:return: 分位数统计信息或None
|
||||
"""
|
||||
conditions, condition_dict = self._build_query_conditions(symbol, bar, start, end)
|
||||
conditions, condition_dict = self._build_query_conditions(symbol, bar, window_size, start, end)
|
||||
|
||||
where_clause = " AND ".join(conditions) if conditions else "1=1"
|
||||
sql = f"""
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ class HugeVolume:
|
|||
|
||||
# 按时间戳排序
|
||||
data = data.sort_values(by="timestamp", ascending=True).copy()
|
||||
data["window_size"] = window_size
|
||||
|
||||
# 计算移动窗口的成交量均值和标准差
|
||||
data["volume_ma"] = (
|
||||
|
|
@ -159,7 +160,7 @@ class HugeVolume:
|
|||
end_date = re.sub(r"[\:\-\s]", "", str(end_date))
|
||||
symbol = data["symbol"].iloc[0]
|
||||
bar = data["bar"].iloc[0]
|
||||
file_name = f"volume_spike_{symbol}_{bar}_{start_date}_{end_date}.xlsx"
|
||||
file_name = f"volume_spike_{symbol}_{bar}_{window_size}_{start_date}_{end_date}.xlsx"
|
||||
try:
|
||||
with pd.ExcelWriter(
|
||||
os.path.join(self.output_folder, file_name)
|
||||
|
|
@ -173,6 +174,7 @@ class HugeVolume:
|
|||
def next_periods_rise_or_fall(
|
||||
self,
|
||||
data: pd.DataFrame,
|
||||
window_size: int = 50,
|
||||
periods: List[int] = [3, 5],
|
||||
output_excel: bool = False
|
||||
) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
||||
|
|
@ -280,6 +282,7 @@ class HugeVolume:
|
|||
{
|
||||
"symbol": data["symbol"].iloc[0] if len(data) > 0 else "",
|
||||
"bar": data["bar"].iloc[0] if len(data) > 0 else "",
|
||||
"window_size": window_size,
|
||||
"huge_volume": 1,
|
||||
"price_type": price_type,
|
||||
"next_period": period,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from core.db_huge_volume_data import DBHugeVolumeData
|
|||
from core.utils import timestamp_to_datetime
|
||||
from market_data_main import MarketDataMain
|
||||
import logging
|
||||
from config import MONITOR_CONFIG, MYSQL_CONFIG
|
||||
from config import MONITOR_CONFIG, MYSQL_CONFIG, WINDOW_SIZE
|
||||
from datetime import datetime
|
||||
import pandas as pd
|
||||
import os
|
||||
|
|
@ -16,7 +16,7 @@ logging.basicConfig(
|
|||
|
||||
|
||||
class HugeVolumeMain:
|
||||
def __init__(self, window_size: int = 50, threshold: float = 2.0):
|
||||
def __init__(self, threshold: float = 2.0):
|
||||
mysql_user = MYSQL_CONFIG.get("user", "xch")
|
||||
mysql_password = MYSQL_CONFIG.get("password", "")
|
||||
if not mysql_password:
|
||||
|
|
@ -29,22 +29,21 @@ class HugeVolumeMain:
|
|||
self.huge_volume = HugeVolume()
|
||||
self.db_market_data = DBMarketData(self.db_url)
|
||||
self.db_huge_volume_data = DBHugeVolumeData(self.db_url)
|
||||
self.monitor_main = MarketDataMain()
|
||||
self.window_size = window_size
|
||||
self.market_data_main = MarketDataMain()
|
||||
self.threshold = threshold
|
||||
|
||||
self.output_folder = "./output/huge_volume_statistics/"
|
||||
os.makedirs(self.output_folder, exist_ok=True)
|
||||
|
||||
def batch_initial_detect_volume_spike(self, start: str = None):
|
||||
for symbol in self.monitor_main.symbols:
|
||||
for bar in self.monitor_main.bars:
|
||||
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:
|
||||
start = MONITOR_CONFIG.get("volume_monitor", {}).get(
|
||||
"initial_date", "2025-05-01 00:00:00"
|
||||
)
|
||||
data = self.detect_volume_spike(
|
||||
symbol, bar, start, only_output_huge_volume=True, is_update=False
|
||||
symbol, bar, window_size, start, only_output_huge_volume=True, is_update=False
|
||||
)
|
||||
if data is not None and len(data) > 0:
|
||||
logging.info(f"此次初始化巨量交易数据: {len(data)}条")
|
||||
|
|
@ -55,6 +54,7 @@ class HugeVolumeMain:
|
|||
self,
|
||||
symbol: str = "XCH-USDT",
|
||||
bar: str = "5m",
|
||||
window_size: int = 50,
|
||||
start: str = "2025-05-01 00:00:00",
|
||||
end: str = None,
|
||||
only_output_huge_volume: bool = False,
|
||||
|
|
@ -66,16 +66,16 @@ class HugeVolumeMain:
|
|||
)
|
||||
if end is None:
|
||||
end = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
logging.info(f"开始处理巨量交易数据: {symbol} {bar} {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} {start} {end}")
|
||||
logging.warning(f"获取行情数据失败: {symbol} {bar} 窗口大小: {window_size} 从 {start} 到 {end}")
|
||||
return None
|
||||
else:
|
||||
if len(data) == 0:
|
||||
logging.warning(f"获取行情数据为空: {symbol} {bar} {start} {end}")
|
||||
logging.warning(f"获取行情数据为空: {symbol} {bar} 窗口大小: {window_size} 从 {start} 到 {end}")
|
||||
return None
|
||||
else:
|
||||
if isinstance(data, list):
|
||||
|
|
@ -84,7 +84,7 @@ class HugeVolumeMain:
|
|||
data = pd.DataFrame([data])
|
||||
data = self.huge_volume.detect_huge_volume(
|
||||
data=data,
|
||||
window_size=self.window_size,
|
||||
window_size=window_size,
|
||||
threshold=self.threshold,
|
||||
check_price=True,
|
||||
only_output_huge_volume=only_output_huge_volume,
|
||||
|
|
@ -94,8 +94,8 @@ class HugeVolumeMain:
|
|||
if is_update:
|
||||
for index, row in data.iterrows():
|
||||
exist_huge_volume_data = (
|
||||
self.db_huge_volume_data.query_data_by_symbol_bar_timestamp(
|
||||
symbol, bar, row["timestamp"]
|
||||
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:
|
||||
|
|
@ -113,16 +113,16 @@ class HugeVolumeMain:
|
|||
else:
|
||||
return None
|
||||
|
||||
def batch_update_volume_spike(self):
|
||||
for symbol in self.monitor_main.symbols:
|
||||
for bar in self.monitor_main.bars:
|
||||
self.update_volume_spike(symbol, bar)
|
||||
def batch_update_volume_spike(self, window_size: int = 50):
|
||||
for symbol in self.market_data_main.symbols:
|
||||
for bar in self.market_data_main.bars:
|
||||
self.update_volume_spike(symbol, bar, window_size)
|
||||
|
||||
def update_volume_spike(self, symbol: str, bar: str):
|
||||
def update_volume_spike(self, symbol: str, bar: str, window_size: int = 50):
|
||||
try:
|
||||
self.monitor_main.update_data(symbol, bar)
|
||||
self.market_data_main.update_data(symbol, bar)
|
||||
latest_huge_volume_data = self.db_huge_volume_data.query_latest_data(
|
||||
symbol, bar
|
||||
symbol, bar, window_size
|
||||
)
|
||||
if latest_huge_volume_data is None or len(latest_huge_volume_data) == 0:
|
||||
self.detect_volume_spike(symbol, bar, only_output_huge_volume=True)
|
||||
|
|
@ -132,26 +132,27 @@ class HugeVolumeMain:
|
|||
earliest_timestamp = latest_huge_volume_data["timestamp"]
|
||||
seconds = self.get_seconds_by_bar(bar)
|
||||
earliest_timestamp = earliest_timestamp - (
|
||||
(self.window_size - 1) * seconds * 1000
|
||||
(window_size - 1) * seconds * 1000
|
||||
)
|
||||
earliest_date_time = timestamp_to_datetime(earliest_timestamp)
|
||||
|
||||
data = self.detect_volume_spike(
|
||||
symbol=symbol,
|
||||
bar=bar,
|
||||
window_size=window_size,
|
||||
start=earliest_date_time,
|
||||
only_output_huge_volume=True,
|
||||
is_update=True,
|
||||
)
|
||||
logging.info(
|
||||
f"更新巨量交易数据: {symbol} {bar} from {earliest_date_time}"
|
||||
f"更新巨量交易数据: {symbol} {bar} 窗口大小: {window_size} 从 {earliest_date_time} 到 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
)
|
||||
if data is not None and len(data) > 0:
|
||||
logging.info(f"此次更新巨量交易数据: {len(data)}条")
|
||||
else:
|
||||
logging.info(f"此次更新巨量交易数据为空")
|
||||
except Exception as e:
|
||||
logging.error(f"更新巨量交易数据失败: {symbol} {bar} {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):
|
||||
"""
|
||||
|
|
@ -201,6 +202,7 @@ class HugeVolumeMain:
|
|||
self,
|
||||
symbol: str,
|
||||
bar: str,
|
||||
window_size: int = 50,
|
||||
start: str = None,
|
||||
end: str = None,
|
||||
periods: list = [3, 5],
|
||||
|
|
@ -212,14 +214,14 @@ class HugeVolumeMain:
|
|||
)
|
||||
if end is None:
|
||||
end = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
logging.info(f"开始计算巨量出现后,之后3或5个周期,上涨或下跌的比例: {symbol} {bar} {start} {end}")
|
||||
logging.info(f"开始计算巨量出现后,之后3或5个周期,上涨或下跌的比例: {symbol} {bar} 窗口大小: {window_size} 从 {start} 到 {end}")
|
||||
huge_volume_data = (
|
||||
self.db_huge_volume_data.query_huge_volume_data_by_symbol_bar(
|
||||
symbol, bar, start, end
|
||||
self.db_huge_volume_data.query_huge_volume_data_by_symbol_bar_window_size(
|
||||
symbol, bar, window_size, start, end
|
||||
)
|
||||
)
|
||||
if huge_volume_data is None or len(huge_volume_data) == 0:
|
||||
logging.warning(f"获取巨量交易数据为空: {symbol} {bar} {start} {end}")
|
||||
logging.warning(f"获取巨量交易数据为空: {symbol} {bar} 窗口大小: {window_size} 从 {start} 到 {end}")
|
||||
return None
|
||||
else:
|
||||
if isinstance(huge_volume_data, list):
|
||||
|
|
@ -230,7 +232,7 @@ class HugeVolumeMain:
|
|||
symbol, bar, start, end
|
||||
)
|
||||
if market_data is None or len(market_data) == 0:
|
||||
logging.warning(f"获取行情数据为空: {symbol} {bar} {start} {end}")
|
||||
logging.warning(f"获取行情数据为空: {symbol} {bar} 窗口大小: {window_size} 从 {start} 到 {end}")
|
||||
return None
|
||||
else:
|
||||
if isinstance(market_data, list):
|
||||
|
|
@ -282,10 +284,12 @@ class HugeVolumeMain:
|
|||
)
|
||||
# 根据timestamp排序
|
||||
data = data.sort_values(by="timestamp", ascending=True)
|
||||
data["window_size"] = window_size
|
||||
data = data[
|
||||
[
|
||||
"symbol",
|
||||
"bar",
|
||||
"window_size",
|
||||
"timestamp",
|
||||
"date_time",
|
||||
"open",
|
||||
|
|
@ -303,12 +307,13 @@ class HugeVolumeMain:
|
|||
data = data.dropna()
|
||||
data = data.reset_index(drop=True)
|
||||
data, result_data = self.huge_volume.next_periods_rise_or_fall(
|
||||
data=data, periods=periods, output_excel=output_excel
|
||||
data=data, window_size=window_size, periods=periods, output_excel=output_excel
|
||||
)
|
||||
return data, result_data
|
||||
|
||||
def batch_next_periods_rise_or_fall(
|
||||
self,
|
||||
window_size: int = 50,
|
||||
start: str = None,
|
||||
end: str = None,
|
||||
periods: list = [3, 5],
|
||||
|
|
@ -322,10 +327,10 @@ class HugeVolumeMain:
|
|||
end = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
data_list = []
|
||||
result_data_list = []
|
||||
for symbol in self.monitor_main.symbols:
|
||||
for bar in self.monitor_main.bars:
|
||||
for symbol in self.market_data_main.symbols:
|
||||
for bar in self.market_data_main.bars:
|
||||
data, result_data = self.next_periods_rise_or_fall(
|
||||
symbol, bar, start, end, periods, output_excel
|
||||
symbol, bar, window_size, start, end, periods, output_excel
|
||||
)
|
||||
data_list.append(data)
|
||||
result_data_list.append(result_data)
|
||||
|
|
@ -351,13 +356,27 @@ class HugeVolumeMain:
|
|||
return data, result_data
|
||||
|
||||
|
||||
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:
|
||||
window_sizes = [50, 80, 100, 120]
|
||||
huge_volume_main = HugeVolumeMain(threshold)
|
||||
for window_size in window_sizes:
|
||||
huge_volume_main.batch_initial_detect_volume_spike(
|
||||
window_size=window_size,
|
||||
start="2025-05-01 00:00:00",
|
||||
)
|
||||
|
||||
|
||||
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:
|
||||
window_sizes = [50, 80, 100, 120]
|
||||
huge_volume_main = HugeVolumeMain(threshold)
|
||||
for window_size in window_sizes:
|
||||
huge_volume_main.batch_update_volume_spike(window_size=window_size)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
huge_volume_main = HugeVolumeMain()
|
||||
# statistics_main.batch_initial_detect_volume_spike(
|
||||
# start="2025-05-01 00:00:00",
|
||||
# )
|
||||
huge_volume_main.batch_update_volume_spike()
|
||||
# huge_volume_main.batch_next_periods_rise_or_fall(
|
||||
# periods=[3, 5],
|
||||
# output_excel=True,
|
||||
# )
|
||||
# batch_initial_detect_volume_spike(threshold=2.0)
|
||||
batch_update_volume_spike(threshold=2.0)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
select * from crypto_market_data
|
||||
WHERE symbol='XCH-USDT' and bar='5m' #and date_time > '2025-07-26'
|
||||
order by timestamp desc;
|
||||
WHERE symbol='DOGE-USDT-SWAP' and bar='1D' #and date_time > '2025-07-01'
|
||||
order by timestamp;
|
||||
|
||||
delete FROM crypto_market_data where symbol != 'XCH-USDT';
|
||||
|
||||
select * from crypto_trade_data
|
||||
where date_time > '2025-05-03'
|
||||
order by ts, tradeId asc;
|
||||
where symbol='BTC-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'
|
||||
|
|
@ -18,3 +22,5 @@ select * from crypto_huge_volume
|
|||
WHERE symbol='BTC-USDT' and bar='5m'
|
||||
order by timestamp desc
|
||||
limit 10;
|
||||
|
||||
SHOW VARIABLES LIKE 'max_connections';
|
||||
|
|
@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS crypto_huge_volume (
|
|||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
symbol VARCHAR(50) NOT NULL COMMENT '交易对',
|
||||
bar VARCHAR(20) NOT NULL COMMENT 'K线周期',
|
||||
window_size INT NOT NULL COMMENT '窗口大小, 50, 80, 100, 120',
|
||||
timestamp BIGINT NOT NULL COMMENT '时间戳',
|
||||
date_time VARCHAR(50) NOT NULL COMMENT '日期时间',
|
||||
open DECIMAL(20,5) NOT NULL COMMENT '开盘价',
|
||||
|
|
@ -28,8 +29,8 @@ CREATE TABLE IF NOT EXISTS crypto_huge_volume (
|
|||
price_10_low TINYINT NOT NULL DEFAULT 0 COMMENT '价格是否达到10%分位数低点(0:否,1:是)',
|
||||
volume_90_10_price_spike TINYINT NOT NULL DEFAULT 0 COMMENT '是否出现90/10量价尖峰(0:否,1:是)',
|
||||
create_time VARCHAR(50) NOT NULL COMMENT '创建时间',
|
||||
UNIQUE KEY uniq_symbol_bar_timestamp (symbol, bar, timestamp),
|
||||
INDEX idx_symbol_bar (symbol, bar),
|
||||
UNIQUE KEY uniq_symbol_bar_window_size_timestamp (symbol, bar, window_size, timestamp),
|
||||
INDEX idx_symbol_bar_window_size (symbol, bar, window_size),
|
||||
INDEX idx_timestamp (timestamp),
|
||||
INDEX idx_huge_volume (huge_volume),
|
||||
INDEX idx_volume_80_20_price_spike (volume_80_20_price_spike),
|
||||
|
|
|
|||
Loading…
Reference in New Issue