2
Seguir
319
Seguidores

Una breve discusión sobre el historial de desarrollo de un indicador de tendencia de criptomonedas

Creado el: 2025-06-23 16:08:06, Actualizado el: 2025-06-24 09:54:54
comments   0
hits   516

Una breve discusión sobre el historial de desarrollo de un indicador de tendencia de criptomonedas

En el campo del análisis técnico, identificar los cuatro patrones principales de la estructura de precios: máximos más altos (HH), mínimos más altos (HL), máximos más bajos (LH) y mínimos más bajos (LL), es fundamental para evaluar la dirección de la tendencia del mercado y los posibles puntos de reversión. Estos patrones revelan intuitivamente el equilibrio dinámico de la oferta y la demanda del mercado, así como el sentimiento dominante (alcista o bajista), lo que proporciona una base objetiva para las decisiones de trading.

Características principales de los mercados alcistas y bajistas

Una breve discusión sobre el historial de desarrollo de un indicador de tendencia de criptomonedas

Tendencia alcistaLos máximos y mínimos más altos son indicadores clave de una tendencia alcista. Los máximos más altos se producen cuando un pico de precio supera al pico anterior, lo que indica que los compradores están impulsando los precios al alza, lo que refleja la fortaleza del mercado. Los mínimos más altos se producen cuando una caída de precios se detiene en un nivel superior al de la caída anterior, lo que indica que el mercado mantiene su impulso alcista. En conjunto, estos patrones indican una fuerte tendencia alcista, identificada en el gráfico por una serie de picos y valles ascendentes.

Tendencia bajistaLos máximos y mínimos decrecientes indican una tendencia bajista. Los máximos decrecientes se forman cuando un pico de precio no alcanza el nivel del pico anterior, lo que indica una disminución de la presión de compra. Los mínimos decrecientes se forman cuando los precios caen por debajo del mínimo anterior, lo que refleja una mayor presión de venta y una debilidad del mercado. Estos patrones son esenciales para identificar tendencias bajistas, que se identifican en un gráfico de precios mediante una serie de picos y valles descendentes.

La necesidad de la identificación cuantitativa de tendencias

El mercado de criptomonedas se caracteriza por una alta volatilidad, operaciones 247 y tendencias significativas impulsadas por el sentimiento. En este entorno, es aún más importante identificar con precisión los patrones de tendencia. Al cuantificar la continuidad de “máximos más altos, mínimos más altos” o “máximos más bajos, mínimos más bajos”, las tendencias del mercado se pueden identificar con mayor precisión, proporcionando una base objetiva para las decisiones de trading.

¿Por qué elegir la plataforma FMZ?

La plataforma cuantitativa FMZ Inventor proporciona un entorno ideal para el desarrollo de dichos indicadores:

Ventaja de datos

  • Suministro gratuito de datos históricos de las principales bolsas
  • Datos completos de la línea K que cubren las principales criptomonedas
  • Calidad de datos confiable y actualizaciones oportunas

Entorno de desarrollo

  • Página de edición de código ligera y rápida
  • Admite múltiples lenguajes de programación como Python
  • Biblioteca de funciones de análisis técnico enriquecida incorporada

Prueba de conveniencia

  • Función completa de backtesting
  • Monitoreo y visualización en tiempo real
  • Conveniente para el análisis simultáneo de múltiples monedas

Basándose en estas ventajas, se eligió la plataforma FMZ para explorar los indicadores de tendencia de continuidad de precios altos y bajos.

Características del mercado de criptomonedas

Antes de diseñar un indicador, debemos considerar las diferencias entre el mercado de criptomonedas y el mercado de valores:

  • Negociación las 24 horas, sin cierres de mercado
  • La volatilidad es enorme y no es raro que el mercado suba o baje un 20% en un día.
  • Hay muchos inversores minoristas y el trading emocional es evidente
  • Los datos históricos no son largos, la mayoría de las monedas solo tienen unos pocos años.

En base a estas características el esquema de diseño es el siguiente:

  • El uso de datos diarios puede filtrar el ruido intradiario sin quedarse atrás
  • Establezca 3 días como período mínimo de confirmación para equilibrar la precisión y la puntualidad.
  • Monitorear varias monedas principales para verificación al mismo tiempo

Implementado en la plataforma FMZ

Diseño del algoritmo central

Tras una profunda reflexión, adoptamos un método de análisis basado en los datos completos de ayer para evitar errores de apreciación causados ​​por datos incompletos del día. La estructura principal de los datos es la siguiente:

# 每个币种的数据都单独存储
data = defaultdict(lambda: {
    "daily_records": [],  # 存储每日的昨天数据
    "trend_buffer": [],   # 当前趋势缓冲区
    "patterns": [],       # 完整的趋势模式
    "current_trend": None, # 当前趋势状态
    "last_processed_time": 0
})

La lógica central de la identificación de tendencias

Funciones clave para determinar tendencias:

def is_trend_continuing(self, buffer, trend_type):
    """检查趋势是否持续"""
    if len(buffer) < 2:
        return False
    
    curr = buffer[-1]
    prev = buffer[-2]
    
    if trend_type == "BULL":
        # 牛市:High和Low都上升
        return curr["High"] > prev["High"] and curr["Low"] > prev["Low"]
    elif trend_type == "BEAR":
        # 熊市:High和Low都下降
        return curr["High"] < prev["High"] and curr["Low"] < prev["Low"]
    
    return False

Gestión del estado de tendencias:

def analyze_trend_state(self, symbol):
    """分析趋势状态"""
    storage = data[symbol]
    buffer = storage["trend_buffer"]
    current_trend = storage["current_trend"]
    
    if current_trend is None:
        # 尝试检测新趋势
        new_trend = self.detect_new_trend(buffer)
        if new_trend:
            storage["current_trend"] = {
                "type": new_trend,
                "start_time": buffer[-2]["Time"],
                "start_price": buffer[-2]["Close"],
                "consecutive_days": 1
            }
    else:
        # 检查现有趋势是否继续
        if self.is_trend_continuing(buffer, current_trend["type"]):
            current_trend["consecutive_days"] += 1
        else:
            # 趋势中断,记录完整模式
            if current_trend["consecutive_days"] >= MIN_CONSECUTIVE:
                # 保存趋势记录
                self.save_pattern(symbol, current_trend, buffer)

La idea clave del diseño es requerir puntos altos y puntos bajos.al mismo tiempoCumplir con los cambios continuos y alcanzar un periodo mínimo de confirmación de 3 días puede reducir considerablemente los errores de juicio. Las estadísticas de la tasa de retorno se refieren al aumento o disminución desde el precio de apertura al inicio de la tendencia hasta el precio de cierre al final de la misma.

Resultados de operaciones reales y análisis de datos

Con base en el backtest de datos históricos de la plataforma FMZ desde 2020 hasta junio de 2025, el siguiente es el desempeño real de las tres monedas principales en los últimos 10 ciclos de tendencia completos:

Análisis de los resultados de las pruebas ETH

tipo fecha de inicio Fecha de finalización Duración Producir
Mercado bajista 2025-05-29 2025-06-01 3 -5.38%
Mercado alcista 2025-05-19 2025-05-22 3 6.73%
Mercado alcista 2025-05-06 2025-05-09 3 26.94%
Mercado alcista 2025-04-24 2025-04-27 3 -0.17%
Mercado bajista 2025-03-25 2025-03-30 5 -13.13%
Mercado alcista 2025-03-21 2025-03-24 3 5.04%
Mercado bajista 2025-01-06 2025-01-10 4 -10.86%
Mercado alcista 2025-01-01 2025-01-06 5 11.2%
Mercado bajista 2024-12-17 2024-12-20 3 -15.5%
Mercado bajista 2024-12-07 2024-12-10 3 -9.96%

Características de rendimiento de ETH

  • El desempeño más destacado fue el mercado alcista del 6 al 9 de mayo, que registró un aumento significativo del 26,94% en solo tres días.
  • El mercado alcista promedio dura 3,4 días, con un rendimiento promedio del 9,97%.
  • El mercado bajista promedio dura 3,6 días, con una caída promedio de -10,97%.
  • Extremadamente volátil, la más inestable de las tres monedas.

Análisis de los resultados de las pruebas de BTC

tipo fecha de inicio Fecha de finalización Duración Producir
Mercado alcista 2025-06-06 2025-06-11 5 7.78%
Mercado bajista 2025-06-03 2025-06-06 3 -0.78%
Mercado bajista 2025-05-27 2025-05-31 4 -4.37%
Mercado bajista 2025-05-22 2025-05-25 3 -2.63%
Mercado alcista 2025-05-06 2025-05-09 3 8.4%
Mercado bajista 2025-05-02 2025-05-05 3 -2.37%
Mercado alcista 2025-04-20 2025-04-23 3 10.07%
Mercado alcista 2025-04-09 2025-04-13 4 10.25%
Mercado bajista 2025-03-26 2025-03-29 3 -5.53%
Mercado bajista 2025-03-08 2025-03-11 3 -5.81%

Características de rendimiento de BTC

  • Los mercados bajistas dominan, y 6 de cada 10 ciclos son mercados bajistas.
  • El mercado alcista promedio dura 3,75 días, con un rendimiento promedio del 9,13%.
  • El mercado bajista promedio duró 3,17 días y la caída promedio fue de -3,58%.
  • El rendimiento general es relativamente equilibrado, con una volatilidad moderada.

Análisis de los resultados de la prueba BNB

tipo fecha de inicio Fecha de finalización Duración Producir
Mercado alcista 2025-06-06 2025-06-11 5 5.46%
Mercado bajista 2025-06-03 2025-06-06 3 -2.73%
Mercado alcista 2025-05-19 2025-05-22 3 4.63%
Mercado alcista 2025-05-05 2025-05-10 5 11.95%
Mercado alcista 2025-04-20 2025-04-23 3 2.44%
Mercado alcista 2025-04-09 2025-04-12 3 7.63%
Mercado alcista 2025-03-14 2025-03-17 3 8.18%
Mercado bajista 2025-03-08 2025-03-11 3 -7.49%
Mercado alcista 2025-02-10 2025-02-13 3 9.66%
Mercado bajista 2025-01-31 2025-02-03 3 -12.2%

Características de rendimiento del BNB

  • Los mercados alcistas son dominantes, y 7 de cada 10 ciclos son mercados alcistas.
  • El mercado alcista promedio duró 3,43 días, con un rendimiento promedio del 7,14%.
  • El mercado bajista promedio dura 3 días, con una caída promedio de -7,47%.
  • El rendimiento es el más estable, con relativamente pocas condiciones extremas del mercado.

Algunos hallazgos interesantes detrás de los datos

Al analizar los datos de los últimos diez ciclos de tendencia de estas tres monedas, se descubrieron algunos fenómenos interesantes.

Sobre la duración de la tendencia

La mayoría de las tendencias terminan en un plazo de entre 3 y 5 días, lo que coincide con la percepción general sobre el mercado de criptomonedas: cambia muy rápidamente. El plazo mínimo de confirmación establecido inicialmente en 3 días sigue siendo bastante razonable, ya que permite filtrar fluctuaciones aleatorias durante el día y evitar perder oportunidades por esperar demasiado. BTC es el más estable en este sentido, y la duración de la tendencia es relativamente regular.

Las diferencias en el “carácter” de las distintas monedas

Estas tres monedas tienen sus propias características. El rendimiento reciente de ETH es, sin duda, más llamativo, y es posible que haya estado demasiado tiempo estancado, por lo que la volatilidad de rebote es muy alta. Del 6 al 9 de mayo, puede subir un 26,94 % en 3 días, lo cual es sorprendente, pero también hay un mercado alcista del -0,17 % que deja a la gente perpleja. BTC es, sin duda, más estable. Aunque ha habido más mercados bajistas recientemente, la volatilidad sigue siendo aceptable. BNB ha dado muchas sorpresas, con un mercado alcista que representa el 70 %, y la relación riesgo-rendimiento parece ser la mejor.

Algunas observaciones sobre el juicio de tendencias

A juzgar por los resultados, este sencillo indicador capturó algunos momentos clave. Por ejemplo, el aumento del 26,94% de ETH, los múltiples ciclos alcistas de BTC y BNB, y varios recordatorios oportunos de mercados bajistas. Por supuesto, también hay algunos puntos confusos, como el “mercado alcista” del -0,17%, lo que demuestra que el algoritmo aún tiene margen de mejora.

¿Para qué sirve esta herramienta?

Lo que puede hacer por usted

Para ser honesto, esta herramienta te ayuda principalmenteDescubra cómo está el mercado ahora

  • Indica si la tendencia actual es ascendente, descendente o fluctuante lateralmente.
  • Realice un seguimiento de cuánto tiempo lleva vigente esta tendencia y cómo se está desempeñando.
  • Proporcionar una base relativamente objetiva para el juicio, no basada enteramente en sentimientos.
  • A juzgar por los datos reales, es bastante eficaz para identificar tendencias a corto plazo de 3 a 5 días.

Lo que no puede hacer

Es necesario dejar claro que esta herramientaDefinitivamente no es para predecir el futuro.

  • No te dirá si subirá o bajará mañana.
  • No puedo predecir cuánto subirá o bajará.
  • No puede sustituir su propio control de riesgos y gestión de fondos.
  • Cuando el mercado se mueve lateralmente, puede dar algunas señales confusas

Algunos problemas encontrados durante el uso

En la práctica también se encontraron algunas limitaciones:

  1. Un poco lento para responder:Debido a que la confirmación demora 3 días, es básicamente imposible detectar la tendencia en los primeros días.

  2. A veces “veo a la persona equivocada”:Al igual que el “mercado alcista” del -0,17% de ETH, muestra que en algunos casos especiales, el juicio del algoritmo puede ser erróneo.

  3. El mercado lateral es un dolor de cabeza:Cuando el mercado fluctúa dentro de un rango, la señal puede cambiar con frecuencia, lo cual es molesto.

  4. Sólo mirar el precio es un poco monótono.:No tener en cuenta factores igualmente importantes como el volumen de operaciones y las noticias

¿Cómo podemos mejorarlo a continuación?

Basándome en las observaciones durante este período, creo que hay varias direcciones a intentar:

Ajustar parámetros para diferentes monedas: Para una moneda volátil como ETH, podrían requerirse condiciones de confirmación más estrictas, mientras que una moneda relativamente estable como BNB podría acortar el tiempo de confirmación. También puede establecer un umbral de rendimiento mínimo para filtrar señales con rendimientos demasiado bajos.

Añadir algún juicio auxiliar: Por ejemplo, combinar cambios en el volumen comercial para verificar si la tendencia es confiable, o tener en cuenta el rango de fluctuación de precios para evitar ser engañado por cambios menores.

Optimización del algoritmo en sí: Mejorar la lógica de juicio de interrupción de tendencias para reducir los errores de juicio; agregar una calificación de fortaleza a la tendencia para distinguir entre tendencias fuertes y débiles; establecer un mecanismo de manejo especial para algunas situaciones anormales.

Mirando hacia atrás en esta exploración

Esta sencilla herramienta de monitoreo de mercado realmente automatiza algunos conceptos tradicionales de análisis técnico. Gracias a la comodidad de la plataforma FMZ, hemos creado una herramienta que monitorea el estado del mercado de criptomonedas en tiempo real.

Su principal valor radica en proporcionar un registro relativamente objetivo de las condiciones del mercado, lo que puede ayudarnos a:

  • Tener una comprensión macro de la situación general del mercado.
  • Filtrar algunas monedas populares a través de datos históricos
  • Proporcionar soporte de datos para un análisis más profundo

A medida que se acumulen más datos, esta herramienta será cada vez más valiosa. Claro que es solo una de muchas herramientas de análisis y no se puede esperar que resuelva todos los problemas, pero como punto de partida, creo que sigue siendo muy interesante.

'''backtest
start: 2020-01-01 00:00:00
end: 2025-06-16 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
'''

import json
from datetime import datetime
from collections import defaultdict

# 配置参数
SYMBOLS = ["ETH_USDT", "BTC_USDT", "BNB_USDT"]
MIN_CONSECUTIVE = 3  # 最少连续天数
MAX_HISTORY = 1000  # 最大历史记录数

# 全局数据存储
data = defaultdict(lambda: {
    "daily_records": [],  # 存储每日的昨天数据
    "trend_buffer": [],   # 当前趋势缓冲区
    "patterns": [],       # 完整的趋势模式
    "current_trend": None, # 当前趋势状态
    "last_processed_time": 0
})

class TrendAnalyzer:
    def get_yesterday_data(self, records):
        """获取昨天的完整数据(records[-2])"""
        if len(records) < 2:
            return None
        return records[-2]  # 昨天的完整K线数据
    
    def is_trend_continuing(self, buffer, trend_type):
        """检查趋势是否持续"""
        if len(buffer) < 2:
            return False
        
        curr = buffer[-1]
        prev = buffer[-2]
        
        if trend_type == "BULL":
            # 牛市:High和Low都上升
            return curr["High"] > prev["High"] and curr["Low"] > prev["Low"]
        elif trend_type == "BEAR":
            # 熊市:High和Low都下降
            return curr["High"] < prev["High"] and curr["Low"] < prev["Low"]
        
        return False
    
    def detect_new_trend(self, buffer):
        """从缓冲区检测新趋势"""
        if len(buffer) < 2:
            return None
        
        curr = buffer[-1]
        prev = buffer[-2]
        
        # 检查是否开始牛市趋势
        if curr["High"] > prev["High"] and curr["Low"] > prev["Low"]:
            return "BULL"
        # 检查是否开始熊市趋势
        elif curr["High"] < prev["High"] and curr["Low"] < prev["Low"]:
            return "BEAR"
        
        return None
    
    def process_daily_data(self, symbol, records):
        """处理每日数据"""
        if not records or len(records) < 2:
            return
        
        storage = data[symbol]
        yesterday_data = self.get_yesterday_data(records)
        
        if not yesterday_data or yesterday_data["Time"] <= storage["last_processed_time"]:
            return  # 没有新的昨天数据
        
        # 更新处理时间
        storage["last_processed_time"] = yesterday_data["Time"]
        
        # 添加到每日记录
        storage["daily_records"].append(yesterday_data)
        if len(storage["daily_records"]) > MAX_HISTORY:
            storage["daily_records"] = storage["daily_records"][-MAX_HISTORY:]
        
        # 添加到趋势缓冲区
        storage["trend_buffer"].append(yesterday_data)
        
        # 分析趋势
        self.analyze_trend_state(symbol)
    
    def analyze_trend_state(self, symbol):
        """分析趋势状态"""
        storage = data[symbol]
        buffer = storage["trend_buffer"]
        current_trend = storage["current_trend"]
        
        if len(buffer) < 2:
            return
        
        if current_trend is None:
            # 尝试检测新趋势
            new_trend = self.detect_new_trend(buffer)
            if new_trend:
                storage["current_trend"] = {
                    "type": new_trend,
                    "start_time": buffer[-2]["Time"],  # 趋势从前一天开始
                    "start_price": buffer[-2]["Close"],
                    "start_open": buffer[-2]["Open"],
                    "consecutive_days": 1
                }
                Log(f"{symbol} 检测到{new_trend}趋势开始")
            else:
                # 没有趋势,只保留最近的数据
                storage["trend_buffer"] = buffer[-1:]
        else:
            # 检查现有趋势是否继续
            if self.is_trend_continuing(buffer, current_trend["type"]):
                # 趋势继续
                current_trend["consecutive_days"] += 1
                
                # 检查是否达到最小天数要求
                if current_trend["consecutive_days"] == MIN_CONSECUTIVE:
                    trend_name = "牛市" if current_trend["type"] == "BULL" else "熊市"
                    Log(f"{symbol} {trend_name}趋势确认! 连续{MIN_CONSECUTIVE}天")
                
            else:
                # 趋势中断
                if current_trend["consecutive_days"] >= MIN_CONSECUTIVE:
                    # 记录完整的趋势
                    end_data = buffer[-2]  # 趋势在前一天结束
                    duration = current_trend["consecutive_days"]
                    start_price = current_trend["start_open"]
                    end_price = end_data["Close"]
                    return_pct = round((end_price - start_price) / start_price * 100, 2)
                    
                    storage["patterns"].append({
                        "trend": current_trend["type"],
                        "start_time": current_trend["start_time"],
                        "end_time": end_data["Time"],
                        "duration": duration,
                        "return": return_pct
                    })
                    
                    trend_name = "牛市" if current_trend["type"] == "BULL" else "熊市"
                    Log(f"{symbol} {trend_name}趋势结束,持续{duration}天,收益{return_pct}%")
                
                # 重置趋势状态,重新开始检测
                storage["current_trend"] = None
                storage["trend_buffer"] = buffer[-2:]  # 保留最近两天数据重新开始
                
                # 立即检测新趋势
                self.analyze_trend_state(symbol)

def generate_tables():
    """生成所有统计表格"""
    tables = []
    
    # 概览表
    overview_rows = []
    for symbol in SYMBOLS:
        storage = data[symbol]
        if not storage["daily_records"]:
            continue
        
        patterns = storage["patterns"]
        current_trend = storage["current_trend"]
        
        # 计算统计数据
        bull_patterns = [p for p in patterns if p["trend"] == "BULL"]
        bear_patterns = [p for p in patterns if p["trend"] == "BEAR"]
        
        stats = {
            "bull_avg_return": round(sum(p["return"] for p in bull_patterns) / len(bull_patterns), 2) if bull_patterns else 0,
            "bear_avg_return": round(sum(p["return"] for p in bear_patterns) / len(bear_patterns), 2) if bear_patterns else 0,
            "bull_avg_days": round(sum(p["duration"] for p in bull_patterns) / len(bull_patterns), 1) if bull_patterns else 0,
            "bear_avg_days": round(sum(p["duration"] for p in bear_patterns) / len(bear_patterns), 1) if bear_patterns else 0
        }
        
        # 当前状态
        current_status = "震荡"
        current_return = 0
        current_days = 0
        consecutive = 0
        
        if current_trend and storage["daily_records"]:
            latest_price = storage["daily_records"][-1]["Close"]
            start_price = current_trend["start_open"]
            current_return = round((latest_price - start_price) / start_price * 100, 2)
            current_days = current_trend["consecutive_days"]
            current_status = "牛市" if current_trend["type"] == "BULL" else "熊市"
            consecutive = current_trend["consecutive_days"]
        
        overview_rows.append([
            symbol.replace("_USDT", ""),
            current_status,
            str(current_days),
            f"{current_return}%",
            str(consecutive),
            str(len(bull_patterns)),
            str(len(bear_patterns)),
            f"{stats['bull_avg_return']}%",
            f"{stats['bear_avg_return']}%",
            f"{stats['bull_avg_days']}天",
            f"{stats['bear_avg_days']}天"
        ])
    
    tables.append({
        "type": "table",
        "title": "每日高低价趋势监控(基于昨日完整数据)",
        "cols": ["币种", "状态", "持续", "收益", "强度", "牛市次数", "熊市次数", "牛市均收益", "熊市均收益", "牛市均天数", "熊市均天数"],
        "rows": overview_rows
    })
    
    # 趋势缓冲区分析表
    buffer_rows = []
    for symbol in SYMBOLS:
        storage = data[symbol]
        buffer = storage["trend_buffer"]
        current_trend = storage["current_trend"]
        
        if not buffer:
            continue
        
        latest_price = buffer[-1]["Close"]
        buffer_size = len(buffer)
        
        # 显示最近几天的High/Low变化
        if len(buffer) >= 2:
            recent_highs = [f"{r['High']:.0f}" for r in buffer[-min(5, len(buffer)):]]
            recent_lows = [f"{r['Low']:.0f}" for r in buffer[-min(5, len(buffer)):]]
            high_trend = " → ".join(recent_highs)
            low_trend = " → ".join(recent_lows)
        else:
            high_trend = f"{buffer[-1]['High']:.0f}"
            low_trend = f"{buffer[-1]['Low']:.0f}"
        
        trend_status = "无趋势"
        if current_trend:
            trend_status = f"{'牛市' if current_trend['type'] == 'BULL' else '熊市'}{current_trend['consecutive_days']}天"
        
        buffer_rows.append([
            symbol.replace("_USDT", ""),
            f"{latest_price:.2f}",
            trend_status,
            str(buffer_size),
            high_trend,
            low_trend
        ])
    
    tables.append({
        "type": "table",
        "title": "趋势缓冲区状态",
        "cols": ["币种", "价格", "当前趋势", "缓冲区", "High变化", "Low变化"],
        "rows": buffer_rows
    })
    
    # 历史记录表
    for symbol in SYMBOLS:
        patterns = [p for p in data[symbol]["patterns"] if p["duration"] >= MIN_CONSECUTIVE]
        coin_name = symbol.replace("_USDT", "")
        
        if not patterns:
            tables.append({
                "type": "table",
                "title": f"{coin_name} 历史趋势",
                "cols": ["类型", "开始", "结束", "天数", "收益"],
                "rows": [["无数据", "-", "-", "-", "-"]]
            })
            continue
        
        rows = []
        for p in sorted(patterns, key=lambda x: x["end_time"], reverse=True)[:10]:  # 只显示最近10条
            rows.append([
                "牛市" if p["trend"] == "BULL" else "熊市",
                datetime.fromtimestamp(p["start_time"] / 1000).strftime('%Y-%m-%d'),
                datetime.fromtimestamp(p["end_time"] / 1000).strftime('%Y-%m-%d'),
                str(p["duration"]),
                f"{p['return']}%"
            ])
        
        tables.append({
            "type": "table",
            "title": f"{coin_name} 历史趋势",
            "cols": ["类型", "开始", "结束", "天数", "收益"],
            "rows": rows
        })
    
    return tables

def main():
    analyzer = TrendAnalyzer()
    
    Log("趋势分析系统启动 - 基于昨日完整数据的逐日分析")
    Log("牛市定义: High和Low连续上升≥3天")
    Log("熊市定义: High和Low连续下降≥3天")
    
    while True:
        try:
            # 处理每个币种的数据
            for symbol in SYMBOLS:
                records = exchange.GetRecords(symbol)
                analyzer.process_daily_data(symbol, records)
            
            # 生成并显示表格
            tables = generate_tables()
            LogStatus('`' + json.dumps(tables) + '`')
            
        except Exception as e:
            Log(f"错误: {str(e)}")
        
        Sleep(1000 * 60 * 60)  # 24小时

def onexit():
    total = sum(len(data[s]["patterns"]) for s in SYMBOLS)
    Log(f"系统停止, 共识别 {total} 个趋势模式")