技术分析入门:Stochastic 随机指标与 ATR 波动率
技术分析中,Stochastic(随机指标)用于判断超买超卖,ATR 用于量化波动幅度,两者经常配合使用。 Stochastic 随机指标 %K 线(快线)计算公式: %K = (当前收盘价 - N 周期最低价) / (N 周期最高价 - N 周期最低价) × 100%D 线(慢线)= %K 的移动平均线(通常 3 周期 SMA) 常见参数:Stoch(14, 3, 3) 超买超卖的正确理解Stoch > 80:超买区——价格接近近期高点,不等于马上下跌 Stoch < 20:超卖区——价格接近近期低点,不等于马上反弹强趋势中,Stoch 可以在超买区(> 80)持续数周。直接在超买区做空是新手最常见的错误,强上涨趋势中会被持续轧空。 更可靠的使用方式 震荡行情:超买出现死叉(%K 下穿 %D)→ 考虑空;超卖出现金叉(%K 上穿 %D)→ 考虑多。 趋势行情(顺势交易):下跌趋势中,等反弹到高位出现 Stoch 死叉再做空 上涨趋势中,等回调到低位出现 Stoch 金叉再做多背离信号 顶背离(看跌):价格创新高,但 Stoch 没有创新高——上涨动能减弱。 价格:100 → 110(新高) Stoch:95 → 85(未创新高)背离不代表立即反转,需配合:Stoch 死叉 + 阻力位 + 成交量萎缩,多条件共振才更可靠。 底背离(看涨):价格创新低,但 Stoch 未创新低——空头力量衰竭。 ATR(Average True Range,平均真实波幅) ATR 回答的是:价格最近平均波动有多大,而不是方向。 True Range(TR)计算 每根 K 线的真实波幅取三个值中的最大值: TR = max( H - L, # 本根K线高低差 |H - 昨收|, # 处理向上跳空 |L - 昨收| # 处理向下跳空 )H = 最高价,L = 最低价 ATR(14) 计算 第一个值:前 14 根 K 线 TR 的简单平均。 后续更新(Wilder 平滑法): ATR(t) = ATR(t-1) + (TR(t) - ATR(t-1)) / 14ATR 的实战应用 动态止损: # 不使用固定点数,而是基于当前波动率 stop_loss = entry_price + 1.5 * atr # 做空的止损 take_profit = entry_price - 3 * atr # 做空的止盈固定止损(如 ±2%)在低波动市场太宽,在高波动市场太窄。ATR 止损随市场自适应。 判断追单风险:如果当根 K 线已经运动超过 2~3 个 ATR,追单的风险/收益比明显恶化。 顺势做空的基本逻辑 顺势做空不是"跌多了就空",而是:确认下跌趋势:均线空头排列,价格持续创新低 等反弹:不追空,等价格反弹到阻力位(云带/均线) 找信号:Stoch 在高位死叉,或出现顶背离 进场:止损放在反弹高点上方 1~1.5 ATR需要避免的情况:在强上涨趋势中因为超买做空 在重要支撑位附近追空(风险大,利润空间小) 重大消息前开仓(ATR 在消息前后会剧烈变化,技术指标失效) 小周期信号对抗大周期趋势Python 计算 ATR(简单实现) import pandas as pddef calculate_atr(df, period=14): df["tr"] = pd.concat([ df["high"] - df["low"], (df["high"] - df["close"].shift(1)).abs(), (df["low"] - df["close"].shift(1)).abs(), ], axis=1).max(axis=1) df["atr"] = df["tr"].ewm(alpha=1/period, adjust=False).mean() return dfpandas 的 ewm 实现了类 Wilder 的指数加权平均。
JavaScript 属性访问断点:Object.defineProperty getter 与 Proxy 监听
问题场景 想知道 window.__VINFO_DATA__.proxyhttp 在哪段代码中被读取,但不知道从哪里打断点。 方法一:Object.defineProperty getter(最直接) 在 Console 执行: const oldValue = window.__VINFO_DATA__.proxyhttp;Object.defineProperty(window.__VINFO_DATA__, "proxyhttp", { configurable: true, enumerable: true, get() { debugger; // 读取时触发断点 console.trace("proxyhttp get"); // 打印调用栈 return oldValue; }, set(v) { console.log("proxyhttp set", v); } });之后任何代码执行 window.__VINFO_DATA__.proxyhttp 时都会暂停在 debugger,可以在调用栈里找到来源。 方法二:Proxy 监听指定属性 如果属性值后续会变化,用 Proxy 更灵活: window.__VINFO_DATA__ = new Proxy(window.__VINFO_DATA__, { get(target, prop, receiver) { if (prop === "proxyhttp") { debugger; console.trace("proxyhttp get"); } return Reflect.get(target, prop, receiver); }, set(target, prop, value, receiver) { if (prop === "proxyhttp") { console.log("proxyhttp set", value); } return Reflect.set(target, prop, value, receiver); } });Reflect.get/set 保持原始行为,不破坏已有逻辑。 方法三:监控所有属性访问 不知道哪个属性会被访问时,监听整个对象: window.__VINFO_DATA__ = new Proxy(window.__VINFO_DATA__, { get(target, prop, receiver) { console.log("GET", prop); return Reflect.get(target, prop, receiver); } });会打印所有被读取的属性名,帮助定位目标属性。 检查已有描述符 在 hook 之前先检查属性的描述符,避免覆盖已有 getter: Object.getOwnPropertyDescriptor(window.__VINFO_DATA__, "proxyhttp") // {value: "...", writable: true, enumerable: true, configurable: true} // 或者 // {get: f, set: f, enumerable: true, configurable: true}如果已经有 getter,需要先保存原 getter 再包装: const desc = Object.getOwnPropertyDescriptor(window.__VINFO_DATA__, "proxyhttp"); const originalGet = desc.get;Object.defineProperty(window.__VINFO_DATA__, "proxyhttp", { ...desc, get() { debugger; return originalGet ? originalGet.call(this) : desc.value; } });适用场景场景 推荐方案监听特定属性读取 Object.defineProperty getter属性值会动态变化 Proxy不知道具体属性名 全对象 Proxy GET 打印属性已有 getter 保存原 getter 后包装这类调试技巧常用于逆向分析第三方网页、油猴脚本开发和 SDK 调试。
SAM2 / SAM3 文本 Prompt 分割:识别图片中所有特定区域
SAM2 / SAM3 不是问答模型,而是 Promptable Concept Segmentation(PCS) 模型——用自然语言描述一个"概念",模型会找出图中所有匹配的实例,每个都生成一个 mask。 Prompt 写法原则 SAM3 理解的是名词短语(concept),不理解逻辑指令: ✅ 有效 question exam question question block text region❌ 无效 all questions detect all questions find every question on this page写"具体描述词",让模型自己找所有实例。 常用场景 Prompt 试卷 / 文档题目识别 # 基础 text_prompt = "question"# 更精准 text_prompt = "exam question" text_prompt = "question block" text_prompt = "problem statement"负例过滤(排除干扰区域) positive_prompt = "exam question text region" negative_prompt = "header, title, footer, logo, watermark"交通标志识别 text_prompt = "traffic sign" text_prompt = "road sign"物体实例分割 text_prompt = "car" text_prompt = "pedestrian" text_prompt = "building window"Python 调用示例(SAM2 + Grounding DINO 方案) 目前实现 text-prompted 分割的常见管线是 Grounding DINO + SAM2(SAM 官方的 text prompt 能力仍在完善中): from groundingdino.util.inference import load_model, load_image, predict from segment_anything import SAMPredictor# Grounding DINO 定位 boxes, logits, phrases = predict( model=gd_model, image=image, caption="exam question block", box_threshold=0.35, text_threshold=0.25 )# SAM2 分割 predictor.set_image(image) masks, scores, _ = predictor.predict( point_coords=None, point_labels=None, box=boxes, # 把 DINO 的 bbox 传给 SAM multimask_output=False )只做区域切割 + OCR 的方案 SAM 负责"切块",OCR 负责"读内容": # Step 1: SAM 找到所有"题目区域"的 mask masks = sam_segment(image, text_prompt="question block")# Step 2: 按 mask 裁剪图片区域 for i, mask in enumerate(masks): bbox = mask_to_bbox(mask) region = image[bbox[1]:bbox[3], bbox[0]:bbox[2]] # Step 3: OCR 识别文字 text = paddleocr.ocr(region) print(f"题目 {i}: {text}")OCR 推荐:PaddleOCR(中文强)、TrOCR(表格/印刷体强)、Tesseract(通用)。 SAM 的能力边界能力 SAM 支持找出所有"题目"区域 ✅生成 mask/bbox ✅理解"这是第几题" ❌读出题目内容 ❌(需要 OCR)判断题目难度 ❌(需要 LLM)SAM 只做像素级分割,不做语义理解。完整的文档结构化提取需要 SAM + OCR + LLM 组合。 一句话总结 SAM3 文本 prompt 用具体名词短语,它会自动找出所有匹配的实例。复杂场景可以加 negative prompt 排除干扰,或者组合 Grounding DINO + SAM2 + OCR 构建完整的图像理解管线。
SAM3 Prompt 工程:识别文档中的题目区域与多实例分割
SAM3 的核心机制:PCS SAM3 不是问答模型,而是 Promptable Concept Segmentation(PCS) 模型:输入:概念描述(名词短语) 输出:所有匹配该概念的实例 Mask(多个)理解这一点才能写出有效 prompt。 识别题目区域的 Prompt 通用(推荐): exam question question block problem statement更细粒度: question text region numbered question multiple choice question fill-in-the-blank question文档/OCR 类: text question area exercise item不要写 all questions 或 detect all questions,SAM3 不理解 all、detect 这类逻辑词。用名词短语描述"这类东西是什么",SAM3 会自动找出所有实例。 Python 调用示例 import torch from sam3 import SAM3model = SAM3.from_pretrained("facebook/sam3-base") model.eval()from PIL import Image image = Image.open("exam_page.jpg")# PCS 模式:用概念 prompt 找所有实例 with torch.no_grad(): masks = model.predict_concept( image=image, concept="exam question", threshold=0.5 )print(f"找到 {len(masks)} 个题目区域")for i, mask in enumerate(masks): # mask 是 numpy bool array,shape = (H, W) print(f"题目 {i+1}: bbox = {mask_to_bbox(mask)}")与 GroundingDINO 组合使用 SAM3 PCS 直接输出 Mask,但复杂图片中 Mask 边界可能不够精确。可以先用 GroundingDINO 获得检测框,再用 SAM3 精确分割: from groundingdino.util.inference import predict as gdino_predict from sam3 import SAM3Predictor# Step 1: GroundingDINO 获得题目框 boxes, _, _ = gdino_predict( model=gdino_model, image=image, caption="exam question", box_threshold=0.3, text_threshold=0.25 )# Step 2: SAM3 对每个框精确分割 sam3_predictor = SAM3Predictor(model) sam3_predictor.set_image(image)for box in boxes: masks, scores, _ = sam3_predictor.predict( box=box, multimask_output=False ) # masks[0] 即为精确 Mask组合方案比单独使用任一模型效果更好。 Prompt 调试技巧从通用开始,再细化:先试 question,如果噪声太多再改 exam question block同义词扩展:英文 question、problem、exercise、item 可能效果不同,逐一测试调整阈值:threshold 降低会找到更多实例(包括噪声),提高则更保守多 prompt 投票:对同一图片用多个 prompt 预测,取交集或并集prompts = ["exam question", "question block", "problem statement"] all_masks = []for p in prompts: masks = model.predict_concept(image=image, concept=p, threshold=0.4) all_masks.extend(masks)# NMS 去重(基于 IoU) final_masks = nms_masks(all_masks, iou_threshold=0.5)常见场景 Prompt 参考场景 推荐 Prompt试卷题目 exam question, question block表单字段 form field, input field车辆检测 car, vehicle, truck人脸 human face, person face交通标志 traffic sign, road sign文字区域 text region, printed textSAM3 的训练数据以英文概念为主,中文 prompt(如"题目")效果不稳定,建议始终使用英文。
Nginx upstream 负载均衡配置:轮询、ip_hash、权重、least_conn 与 PHPStudy 位置问题
基本结构 upstream 定义后端服务器组,proxy_pass 引用该组名: upstream backend { server 192.168.1.10:8000; server 192.168.1.11:8000; server 192.168.1.12:8000; }server { location / { proxy_pass http://backend; # ... 其他 proxy 配置 } }四种均衡策略 轮询(默认):依次分配请求,适合无状态服务: upstream backend { server 192.168.1.10:8000; server 192.168.1.11:8000; }ip_hash:同一客户端 IP 固定打到同一台服务器,适合有 Session 的服务: upstream backend { ip_hash; server 192.168.1.10:8000; server 192.168.1.11:8000; }weight(加权轮询):按权重比例分配流量: upstream backend { server 192.168.1.10:8000 weight=4; server 192.168.1.11:8000 weight=2; server 192.168.1.12:8000 weight=1; }least_conn(最少连接):新请求优先分配给当前连接数最少的服务器,适合耗时不均匀的服务(如 AI 推理、文件处理): upstream backend { least_conn; server 192.168.1.10:8000; server 192.168.1.11:8000; }健康检查 max_fails 次失败后暂时摘除节点,fail_timeout 秒后重试: upstream backend { server 192.168.1.10:8000 max_fails=3 fail_timeout=30s; server 192.168.1.11:8000 max_fails=3 fail_timeout=30s; }错误:upstream directive is not allowed here [emerg] "upstream" directive is not allowed here in vhosts/xxx.conf:24原因:upstream 只能放在 http {} 块内,不能放在 server {} 或 location {} 内。 PHPStudy 等面板生成的 vhosts 文件是 server {} 块,不能在里面定义 upstream。 解决方案:在主 nginx.conf 的 http {} 块中定义: # nginx.conf http { upstream backend { server 192.168.1.10:8000; server 192.168.1.11:8000; } include vhosts/*.conf; # vhosts 文件只包含 server{} 块 }配置验证与重载 nginx -t # 检查配置语法 nginx -s reload # 平滑重载(不中断现有连接)
