
No campo da análise técnica, a identificação dos quatro principais padrões de estrutura de preços: “máximas mais altas (MMA)”, “mínimas mais altas (MMA)”, “máximas mais baixas (MMA)” e “mínimas mais baixas (MMA)” é a base para avaliar a direção da tendência do mercado e os potenciais pontos de reversão. Esses padrões revelam intuitivamente o equilíbrio dinâmico das forças de oferta e demanda do mercado e o sentimento dominante (altista ou baixista), fornecendo uma base objetiva para decisões de negociação.

Tendência de altaMáximas e mínimas mais altas são indicadores-chave de uma tendência de alta. Máximas mais altas ocorrem quando um pico de preço excede o pico anterior, indicando que os compradores estão elevando os preços, refletindo a força do mercado. Mínimas mais altas ocorrem quando uma queda de preço para em um nível superior à queda anterior, indicando que o mercado está mantendo seu momentum de alta. Juntos, esses padrões indicam uma forte tendência de alta, identificada em um gráfico por uma série de picos e mínimas ascendentes.
Tendência de baixaMáximas e mínimas mais baixas indicam uma tendência de baixa. Máximas mais baixas se formam quando um pico de preço não atinge o nível do pico anterior, indicando um enfraquecimento da pressão de compra. Mínimas mais baixas se formam quando os preços caem abaixo da mínima anterior, refletindo o aumento da pressão de venda e a fraqueza do mercado. Esses padrões são essenciais para identificar tendências de baixa, que são identificadas em um gráfico de preços por uma série de picos e mínimas decrescentes.
O mercado de criptomoedas é caracterizado por alta volatilidade, negociações 24 horas por dia, 7 dias por semana e tendências significativas impulsionadas pelo sentimento. Em tal ambiente, torna-se ainda mais importante identificar com precisão os padrões de tendência. Ao quantificar a continuidade de “máximas mais altas, mínimas mais altas” ou “máximas mais baixas, mínimas mais baixas”, as tendências de mercado podem ser identificadas com mais precisão, fornecendo uma base objetiva para decisões de negociação.
A plataforma quantitativa FMZ Inventor oferece um ambiente ideal para o desenvolvimento de tais indicadores:
Vantagem de dados:
Ambiente de Desenvolvimento:
Conveniência de teste:
Com base nessas vantagens, a plataforma FMZ foi escolhida para explorar os indicadores de tendência de continuidade de preços altos e baixos.
Antes de projetar um indicador, precisamos considerar as diferenças entre o mercado de criptomoedas e o mercado de ações:
Com base nessas características, o esquema de projeto é o seguinte:
Após uma reflexão aprofundada, adotamos um método de análise baseado em “dados completos de ontem” para evitar erros de julgamento causados por dados incompletos naquele dia. A estrutura principal dos dados é a seguinte:
# 每个币种的数据都单独存储
data = defaultdict(lambda: {
"daily_records": [], # 存储每日的昨天数据
"trend_buffer": [], # 当前趋势缓冲区
"patterns": [], # 完整的趋势模式
"current_trend": None, # 当前趋势状态
"last_processed_time": 0
})
Principais funções para determinar tendências:
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
Gerenciamento de status de tendências:
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)
A ideia-chave do design é exigir pontos altos e pontos baixosao mesmo tempoSatisfaça as mudanças contínuas e alcance um período mínimo de confirmação de 3 dias, o que pode reduzir significativamente os erros de julgamento. A estatística da taxa de retorno é o aumento ou a diminuição do preço de abertura no início da tendência até o preço de fechamento no final da tendência.
Com base no teste histórico de dados da plataforma FMZ de 2020 a junho de 2025, a seguir está o desempenho real das três principais moedas nos últimos 10 ciclos de tendência completos:
| tipo | data de início | Data de término | Duração | Colheita |
|---|---|---|---|---|
| Mercado em baixa | 2025-05-29 | 2025-06-01 | 3 | -5.38% |
| Mercado de alta | 2025-05-19 | 2025-05-22 | 3 | 6.73% |
| Mercado de alta | 2025-05-06 | 2025-05-09 | 3 | 26.94% |
| Mercado de alta | 2025-04-24 | 2025-04-27 | 3 | -0.17% |
| Mercado em baixa | 2025-03-25 | 2025-03-30 | 5 | -13.13% |
| Mercado de alta | 2025-03-21 | 2025-03-24 | 3 | 5.04% |
| Mercado em baixa | 2025-01-06 | 2025-01-10 | 4 | -10.86% |
| Mercado de alta | 2025-01-01 | 2025-01-06 | 5 | 11.2% |
| Mercado em baixa | 2024-12-17 | 2024-12-20 | 3 | -15.5% |
| Mercado em baixa | 2024-12-07 | 2024-12-10 | 3 | -9.96% |
Características de desempenho do ETH:
| tipo | data de início | Data de término | Duração | Colheita |
|---|---|---|---|---|
| Mercado de alta | 2025-06-06 | 2025-06-11 | 5 | 7.78% |
| Mercado em baixa | 2025-06-03 | 2025-06-06 | 3 | -0.78% |
| Mercado em baixa | 2025-05-27 | 2025-05-31 | 4 | -4.37% |
| Mercado em baixa | 2025-05-22 | 2025-05-25 | 3 | -2.63% |
| Mercado de alta | 2025-05-06 | 2025-05-09 | 3 | 8.4% |
| Mercado em baixa | 2025-05-02 | 2025-05-05 | 3 | -2.37% |
| Mercado de alta | 2025-04-20 | 2025-04-23 | 3 | 10.07% |
| Mercado de alta | 2025-04-09 | 2025-04-13 | 4 | 10.25% |
| Mercado em baixa | 2025-03-26 | 2025-03-29 | 3 | -5.53% |
| Mercado em baixa | 2025-03-08 | 2025-03-11 | 3 | -5.81% |
Características de desempenho do BTC:
| tipo | data de início | Data de término | Duração | Colheita |
|---|---|---|---|---|
| Mercado de alta | 2025-06-06 | 2025-06-11 | 5 | 5.46% |
| Mercado em baixa | 2025-06-03 | 2025-06-06 | 3 | -2.73% |
| Mercado de alta | 2025-05-19 | 2025-05-22 | 3 | 4.63% |
| Mercado de alta | 2025-05-05 | 2025-05-10 | 5 | 11.95% |
| Mercado de alta | 2025-04-20 | 2025-04-23 | 3 | 2.44% |
| Mercado de alta | 2025-04-09 | 2025-04-12 | 3 | 7.63% |
| Mercado de alta | 2025-03-14 | 2025-03-17 | 3 | 8.18% |
| Mercado em baixa | 2025-03-08 | 2025-03-11 | 3 | -7.49% |
| Mercado de alta | 2025-02-10 | 2025-02-13 | 3 | 9.66% |
| Mercado em baixa | 2025-01-31 | 2025-02-03 | 3 | -12.2% |
Características de desempenho do BNB:
Ao analisar os dados dos últimos dez ciclos de tendência dessas três moedas, alguns fenômenos interessantes foram descobertos.
Sobre a duração da tendência
A maioria das tendências termina em cerca de 3 a 5 dias, o que, na verdade, está em linha com a percepção geral sobre o mercado de criptomoedas – ele muda muito rapidamente. A configuração original de 3 dias como período mínimo de confirmação ainda é bastante razoável, pois permite filtrar algumas flutuações aleatórias durante o dia e evitar perdas de oportunidades por esperar muito tempo. O BTC é o mais estável nesse aspecto, e a duração da tendência é relativamente regular.
As diferenças no “caráter” das diferentes moedas
Essas três moedas realmente têm suas próprias características. O desempenho recente do ETH é de fato mais chamativo, e pode ser que ele esteja em baixa há muito tempo, então a volatilidade de recuperação é muito grande. De 6 a 9 de maio, ele pode subir 26,94% em 3 dias, o que é surpreendente, mas também há um “mercado em alta” de -0,17% que faz as pessoas coçarem a cabeça. O BTC é, sem dúvida, mais estável. Embora tenha havido mais mercados em baixa recentemente, a volatilidade ainda é aceitável. O BNB surpreendeu a todos, com um mercado em alta representando 70%, e a relação risco-retorno parece ser a melhor.
Algumas observações sobre julgamento de tendências
A julgar pelos resultados, este indicador simples ainda capturou alguns momentos-chave. Por exemplo, a alta de 26,94% do ETH, os múltiplos ciclos de alta do BTC e do BNB e vários lembretes oportunos de mercados em baixa. É claro que também existem alguns pontos confusos, como o “mercado em alta” de -0,17%, o que mostra que o algoritmo ainda tem espaço para melhorias.
Para ser honesto, esta ferramenta ajuda principalmente vocêDescubra como está o mercado agora:
É preciso deixar claro que esta ferramentaDefinitivamente não é para prever o futuro.:
Na operação real, algumas limitações também foram encontradas:
Um pouco lento para responder:Como leva 3 dias para confirmar, é basicamente impossível perceber a tendência nos primeiros dias
Às vezes eu “julgo mal as pessoas”:Como o “mercado de alta” de -0,17% do ETH, isso mostra que, em alguns casos especiais, o julgamento do algoritmo pode estar errado
O mercado lateral é uma dor de cabeça:Quando o mercado flutua dentro de uma faixa, o sinal pode mudar com frequência, o que é irritante
Só de olhar o preço já é um pouco monótono: Falha em considerar fatores igualmente importantes, como volume de negociação e notícias
Com base nas observações durante esse período, acredito que há várias direções a serem tentadas:
Ajuste os parâmetros para diferentes moedas: Para uma moeda volátil como o ETH, condições de confirmação mais rigorosas podem ser necessárias, enquanto uma moeda relativamente estável como o BNB pode reduzir o tempo de confirmação. Você também pode definir um limite mínimo de rendimento para filtrar sinais com rendimentos muito baixos.
Adicione algum julgamento auxiliar: Por exemplo, combinar mudanças no volume de negociação para verificar se a tendência é confiável ou levar em consideração a faixa de flutuação de preços para evitar ser enganado por pequenas mudanças.
Otimizando o algoritmo em si: Melhore a lógica de julgamento da interrupção de tendências para reduzir erros de julgamento; adicione uma classificação de força à tendência para distinguir entre tendências fortes e fracas; estabeleça um mecanismo de tratamento especial para algumas situações anormais.
Esta ferramenta simples de monitoramento de mercado realmente transforma alguns conceitos tradicionais de análise técnica em um sistema automatizado. Com a conveniência da plataforma FMZ, construímos com sucesso uma ferramenta que pode monitorar o status do mercado de criptomoedas em tempo real.
Seu principal valor reside em fornecer um registro relativamente objetivo das condições de mercado, o que pode nos ajudar:
À medida que os dados se acumulam, esta ferramenta se tornará cada vez mais valiosa. É claro que é apenas uma entre muitas ferramentas de análise e não se pode esperar que resolva todos os problemas, mas, como ponto de partida, acho que ainda é muito interessante.
'''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} 个趋势模式")