Python案例:识别"战术被摸透"的风险
在量化交易、游戏AI、竞价策略等场景中,"战术被摸透"指对手能预测你的行为模式并加以利用,下面用几个可运行的Python案例来演示如何识别这种风险。

问题建模
"被摸透"的本质是:你的行为序列具有高可预测性,可以从三个维度量化:
| 维度 | 含义 | 指标 |
|---|---|---|
| 熵 | 行为分布的随机性 | 香农熵、条件熵 |
| 周期性 | 是否重复固定模式 | 自相关、FFT |
| 可预测性 | 对手能否预测下一步 | 马尔可夫/ML模型准确率 |
案例1:行为熵检测(分布是否太集中)
from collections import Counter
import numpy as np
from scipy.stats import entropy
def behavior_entropy(actions):
"""
actions: 你的历史动作序列,如 ['buy','sell','hold',...]
返回归一化熵:0=完全可预测,1=完全随机
"""
counts = Counter(actions)
probs = np.array(list(counts.values())) / len(actions)
h = entropy(probs, base=2)
h_max = np.log2(len(counts)) if len(counts) > 1 else 1
return h / h_max # 归一化
# 示例
tactics_A = ['buy','sell','hold'] * 100 # 死板循环 → 容易被摸透
tactics_B = np.random.choice(['buy','sell','hold'], 300) # 随机
print("循环战术熵:", round(behavior_entropy(tactics_A), 3)) # 接近0
print("随机战术熵:", round(behavior_entropy(tactics_B), 3)) # 接近1
判读:归一化熵 < 0.4 就意味着行为过于集中,风险高。
案例2:序列可预测性(对手能不能猜下一步)
用一阶马尔可夫链模拟对手的预测能力:
from collections import defaultdict
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
def markov_predictability(actions):
# 构造 (前一步 -> 下一步) 转移对
transitions = defaultdict(list)
for a, b in zip(actions[:-1], actions[1:]):
transitions[a].append(b)
# 用众数作为预测规则
rule = {k: Counter(v).most_common(1)[0][0] for k, v in transitions.items()}
# 留出法评估:用前半段训练,后半段测试
split = len(actions) // 2
rule_train = defaultdict(list)
for a, b in zip(actions[:split-1], actions[1:split]):
rule_train[a].append(b)
rule_train = {k: Counter(v).most_common(1)[0][0] for k, v in rule_train.items()}
y_true = actions[split:]
y_pred = [rule_train.get(a, None) for a in actions[split-1:-1]]
valid = [(t,p) for t,p in zip(y_true, y_pred) if p]
if not valid:
return 0.0
return accuracy_score([t for t,_ in valid], [p for _,p in valid])
# 对比
print("循环战术可预测率:", markov_predictability(tactics_A)) # ≈1.0 危险
print("随机战术可预测率:", markov_predictability(list(tactics_B))) # ≈0.33 安全
阈值参考(3类动作):> 0.5 表示对手有显著优势。
案例3:周期性检测(FFT + 自相关)
import numpy as np
def detect_periodicity(actions, top_k=3):
"""把动作编码为0/1/2后做FFT,找主频"""
mapping = {a: i for i, a in enumerate(set(actions))}
x = np.array([mapping[a] for a in actions], dtype=float)
x = x - x.mean()
fft = np.abs(np.fft.rfft(x))
freqs = np.fft.rfftfreq(len(x))
# 忽略直流分量
idx = np.argsort(fft[1:])[::-1][:top_k] + 1
peaks = [(freqs[i], fft[i]) for i in idx]
# 用最大峰/次大峰 判断"是否明显周期"
if len(peaks) < 2 or peaks[1][1] == 0:
return peaks, float('inf')
ratio = peaks[0][1] / (peaks[1][1] + 1e-9)
return peaks, ratio
peaks, ratio = detect_periodicity(tactics_A)
print("主周期峰:", [(round(f,3), round(a,1)) for f,a in peaks])
print("主次峰比:", round(ratio, 2), " >3 表示周期明显,危险")
案例4:综合风险打分器
把三个指标整合成一个实时监控面板:
def risk_score(actions, weights=(0.4, 0.4, 0.2)):
h = behavior_entropy(actions) # 越低越危险
p = markov_predictability(actions) # 越高越危险
_, ratio = detect_periodicity(actions)
periodicity = min(ratio / 5.0, 1.0) # 归一化
risk = (weights[0] * (1 - h)
+ weights[1] * p
+ weights[2] * periodicity)
return {
"entropy": round(h, 3),
"predictability": round(p, 3),
"periodicity": round(periodicity, 3),
"risk": round(risk, 3),
"level": "🔴高" if risk > 0.7 else "🟡中" if risk > 0.4 else "🟢低"
}
print("循环战术:", risk_score(tactics_A))
print("随机战术:", risk_score(list(tactics_B)))
输出示例:
循环战术: {'entropy': 0.02, 'predictability': 1.0, 'periodicity': 0.6, 'risk': 0.91, 'level': '🔴高'}
随机战术: {'entropy': 0.95, 'predictability': 0.34, 'periodicity': 0.1, 'risk': 0.22, 'level': '🟢低'}
实战落地建议
- 滑动窗口监控:每隔 N 步(如 50 次)重算一次
risk_score,画时间曲线,一旦持续 > 0.6 就告警。 - 对局反馈结合:如果对手胜率随对局数上升,配合上述指标可确认是"被适应"而非运气。
- 自动化反制:
- 加入 ε-greedy 随机扰动(把熵拉到 0.7+)
- 定期切换策略池(用 bandit 算法动态选策略)
- 引入对抗训练:让自博弈的对手去学习自己
- 区分场景:
- 交易:还要看成交量、盘口反应(对手针对性下单)
- 游戏AI:还要看对手的反制动作频率
- 竞价:还要看对手报价是否踩在你出价的临界点上
扩展方向
- 用 LSTM/Transformer 替代马尔可夫,捕捉高阶模式(预测准确率更能反映真实威胁)
- 用 KL 散度 对比"你"与"对手建模出的你"的分布差异
- 用 博弈论 的 exploitability 指标(在扑克AI领域常用)量化可被利用程度
核心思想一句话:"被摸透"= 高可预测性 + 高周期性 + 低熵,用这三个指标做监控就能提前预警。