<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://roshameow.github.io//personal_homepage/atom.xml" rel="self" type="application/atom+xml" /><link href="https://roshameow.github.io//personal_homepage/" rel="alternate" type="text/html" /><updated>2026-09-15T01:01:35+00:00</updated><id>https://roshameow.github.io//personal_homepage/atom.xml</id><title type="html">Liu, Wen’s Home Page</title><subtitle>Work, Experiments and Ideas.</subtitle><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><entry><title type="html">怎么把一个小功能润色成用户产品</title><link href="https://roshameow.github.io//personal_homepage/tool/feature2product/" rel="alternate" type="text/html" title="怎么把一个小功能润色成用户产品" /><published>2026-01-01T00:00:00+00:00</published><updated>2026-01-11T20:59:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/tool/feature2product</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/tool/feature2product/"><![CDATA[<p>通过学习这个 <a href="https://github.com/journey-ad/gemini-watermark-remover">优秀的案例</a> 学了一些我没做到, 不过不知道有没有用的技巧. 应该有点用吧?</p>
<h2 id="更专业的github">更专业的github</h2>

<ul>
  <li>README
    <ul>
      <li>隐私声明： 明确告知用户“纯前端运行，图片数据不离机”。这是这个产品最大的卖点之一。如果你的算法能在本地跑，一定要大写加粗告诉用户。</li>
      <li>开源/原理透明：在页面底部放上原理解释和原理的文章链接</li>
      <li>安装方法</li>
      <li> 免责声明：Disclaimer（仅供学习交流，后果自负)</li>
    </ul>
  </li>
  <li>Demo GIF</li>
  <li>LICENSE</li>
  <li>Shields.io badges</li>
  <li>About 区域填满</li>
</ul>

<h2 id="降低使用门槛">降低使用门槛</h2>

<ul>
  <li>纯前端实现(不登陆, 不注册, 不配置)</li>
  <li>Web版
    <ul>
      <li>极简的功能</li>
    </ul>
  </li>
  <li>插件化
    <ul>
      <li>通用Userscript</li>
    </ul>
  </li>
</ul>

<h2 id="试验">试验</h2>

<p>尝试小范围的宣传自己的开源项目, 发现很困难</p>
<ol>
  <li>设计了很多开放性接口, 但是没人会使用, 没有配套文档. 别人并不会看readme. 想要的是安装后就能直接使用的app</li>
  <li>不够通用.</li>
  <li>每个界面, 每个按钮都要有用.</li>
</ol>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="tool" /><category term="content" /><summary type="html"><![CDATA[通过学习这个 优秀的案例 学了一些我没做到, 不过不知道有没有用的技巧. 应该有点用吧? 更专业的github]]></summary></entry><entry><title type="html">组合交易 (二)</title><link href="https://roshameow.github.io//personal_homepage/finance/alpha13/" rel="alternate" type="text/html" title="组合交易 (二)" /><published>2025-12-24T00:00:00+00:00</published><updated>2026-01-18T19:11:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/finance/alpha13</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/finance/alpha13/"><![CDATA[<h2 id="单个alpha的性能">单个alpha的性能</h2>

<table>
  <thead>
    <tr>
      <th style="text-align: left">维度</th>
      <th style="text-align: left">指标名称</th>
      <th style="text-align: left">描述</th>
      <th style="text-align: left">计算公式</th>
      <th>特点</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><strong>表现</strong><br />和未来一天returns的关系</td>
      <td style="text-align: left">daily pnl</td>
      <td style="text-align: left"> </td>
      <td style="text-align: left">$S_t\cdot R_{t+1}$</td>
      <td>最直接</td>
    </tr>
    <tr>
      <td style="text-align: left"> </td>
      <td style="text-align: left">Quintile Long–Short Strategy（五分位多空策略）</td>
      <td style="text-align: left"> </td>
      <td style="text-align: left">$R_{Q5}-R_{Q1}$</td>
      <td>常用投资研究方法</td>
    </tr>
    <tr>
      <td style="text-align: left"> </td>
      <td style="text-align: left">Information Coefficient(IC)</td>
      <td style="text-align: left">计算alpha值和未来一天returns的Pearson相关性</td>
      <td style="text-align: left">\(IC_t = \rho(S_t,R_{t+1}) = \frac{\sum_{i=1}^N (S_{i,t} - \bar{S}_t)(R_{i,t+1} - \bar{R}_{t+1})}{\sqrt{\sum_{i=1}^N (S_{i,t} - \bar{S}_t)^2 \sum_{i=1}^N (R_{i,t+1} - \bar{R}_{t+1})^2}}\)</td>
      <td>容易受到极端值影响</td>
    </tr>
    <tr>
      <td style="text-align: left"> </td>
      <td style="text-align: left">Fama-MacBeth Regression</td>
      <td style="text-align: left">计算alpha值对未来returns的beta系数</td>
      <td style="text-align: left">Linear Regression Model:<br />$R_{i,t+1} = \lambda_{0,t} + \lambda_{1,t} S_{i,t} + \epsilon_{i,t+1}$<br /><br />\(\lambda_{1,t} = \frac{\sum_{i=1}^N (S_{i,t} - \bar{S}_t)(R_{i,t+1} - \bar{R}_{t+1})}{\sum_{i=1}^N (S_{i,t} - \bar{S}_t)^2}\)</td>
      <td>还可以得出alpha和现有alpha的冗余度</td>
    </tr>
    <tr>
      <td style="text-align: left"> </td>
      <td style="text-align: left">RankIC</td>
      <td style="text-align: left">计算alpha排名和returns排名的<a href="https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient">Spearman相关性</a> <br />(是Pearson相关系数的rank版, <br />完全等价, 计算简单) <a href="#1-rankic-spearman-公式推导">1</a></td>
      <td style="text-align: left">$RankIC_t = \rho(\text{rank}(S_t), \text{rank}(R_{t+h}))$<br />$= 1 - \frac{6 \sum d_i^2}{N(N^2 - 1)}$</td>
      <td>alpha不受单调非线性变换的影响, 更稳定</td>
    </tr>
    <tr>
      <td style="text-align: left"> </td>
      <td style="text-align: left">Predictive Power Score（PPS）</td>
      <td style="text-align: left">IC和RankIC的线性组合</td>
      <td style="text-align: left">$PPS = w_1 \cdot IC + w_2 \cdot RankIC$</td>
      <td> </td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>费率</strong><br />自身时序上的关系</td>
      <td style="text-align: left">turnover</td>
      <td style="text-align: left">衡量 alpha 信号在前后两个交易日的持仓变化程度</td>
      <td style="text-align: left">\(\text{Turnover}_t = \frac{\sum_i \vert S_{t,i} - S_{t-1,i} \vert}{2}\)</td>
      <td> </td>
    </tr>
    <tr>
      <td style="text-align: left"> </td>
      <td style="text-align: left">Signal Autocorrelation</td>
      <td style="text-align: left">Alpha 前后两天的自相关性</td>
      <td style="text-align: left">$AutoCorr = \rho(S_t, S_{t-1})$</td>
      <td> </td>
    </tr>
    <tr>
      <td style="text-align: left"> </td>
      <td style="text-align: left">Relative Rank Entropy（RRE）</td>
      <td style="text-align: left">用 KL散度 计算前后两天alpha分布的差异</td>
      <td style="text-align: left">$D_{KL}(P_t \parallel P_{t-1}) = \sum P_t(i) \ln \frac{P_t(i)}{P_{t-1}(i)}$</td>
      <td> </td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>稳定性</strong><br /><br /></td>
      <td style="text-align: left">Perturbation Fidelity Score（PFS）</td>
      <td style="text-align: left">加入轻微扰动后信号的相关性<br />- 加入guassian noise<br />- 加入 t 分布</td>
      <td style="text-align: left">$PFS = \rho(S, S + \epsilon), \epsilon \sim N(0, \sigma^2)$</td>
      <td> </td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>金融逻辑</strong></td>
      <td style="text-align: left">llm打分</td>
      <td style="text-align: left">- 是否符合经济直觉<br />- 是否可解释<br />- 是否有金融含义</td>
      <td style="text-align: left">$\text{Score} = \text{LLM}(Prompt, \text{AlphaLogic})$</td>
      <td> </td>
    </tr>
  </tbody>
</table>

<h3 id="1-rankic-spearman-公式推导">1: RankIC (Spearman) 公式推导</h3>

<p>Spearman相关系数本质上是<strong>秩(Rank)变量之间的Pearson相关系数</strong>。</p>

<p>对于 $N$ 个样本，alpha排名和returns排名 $x_i, y_i$ 均为 $1, 2, …, N$ 的排列。
已知前 $N$ 个整数的性质:</p>
<ol>
  <li><strong>均值</strong>: $\bar{x} = \bar{y} = \frac{N+1}{2}$</li>
  <li><strong>方差项</strong>: $\sum (x_i - \bar{x})^2 = \frac{N(N^2 - 1)}{12}$</li>
</ol>

<p>定义秩差 $d_i = x_i - y_i$，则:
\(\sum d_i^2 = \sum (x_i - y_i)^2 = \sum x_i^2 + \sum y_i^2 - 2\sum x_i y_i\)
由于 $\sum x_i^2 = \sum y_i^2$ (都是 $1^2 + … + N^2$)，代入得:
\(\sum x_i y_i = \sum x_i^2 - \frac{1}{2} \sum d_i^2\)</p>

<p>代入 Pearson 相关系数公式:
\(\begin{aligned}
\rho &amp;= \frac{\sum (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum (x_i - \bar{x})^2 \sum (y_i - \bar{y})^2}} \\
&amp;= \frac{\sum x_i y_i - N\bar{x}\bar{y}}{\sum (x_i - \bar{x})^2} \quad (\text{分母两项相等}) \\
&amp;= \frac{(\sum x_i^2 - \frac{1}{2}\sum d_i^2) - N\bar{x}^2}{\sum x_i^2 - N\bar{x}^2} \\
&amp;= 1 - \frac{\frac{1}{2}\sum d_i^2}{\frac{N(N^2-1)}{12}} \\
&amp;= 1 - \frac{6 \sum d_i^2}{N(N^2 - 1)}
\end{aligned}\)</p>

<h2 id="组合alpha的性能">组合alpha的性能</h2>

<table>
  <thead>
    <tr>
      <th style="text-align: left">维度</th>
      <th style="text-align: left">指标名称</th>
      <th style="text-align: left">描述</th>
      <th style="text-align: left">计算公式</th>
      <th>特点</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left">多样性<br /><br />不考虑组合方式</td>
      <td style="text-align: left">Diversity Entropy (DE)</td>
      <td style="text-align: left">衡量 Alpha 集合的非线性相关性与冗余度</td>
      <td style="text-align: left">对 $\Sigma$ 进行特征分解，得到特征值 $\lambda_1, \lambda_2, \dots, \lambda_m$。<br /><br />$DE = -\frac{\sum p_i \ln p_i}{\ln m}, \quad p_i = \frac{\lambda_i}{\sum \lambda_j}$</td>
      <td>量化得出系统的冗余度</td>
    </tr>
    <tr>
      <td style="text-align: left">平衡性<br /><br />只考虑每个instrument线性组合</td>
      <td style="text-align: left">Risk Contribution(RC)</td>
      <td style="text-align: left">衡量总风险($\sigma$) 变化时对每个alpha 增量均匀(风险贡献不均衡度) <a href="#2-风险分解">2</a><br /><br />由<a href="https://en.wikipedia.org/wiki/Homogeneous_function#Euler's_theorem">欧拉定理</a> , 分解为风险贡献 (Risk Contribution, RC):<br />$\sigma =w_i\frac{\partial \sigma}{\partial w_i}=\Sigma_i \frac{w_i(\Sigma w)_i}{\sigma}=RC_i$</td>
      <td style="text-align: left">Risk Parity (风险平价)<br /><br /><br /><br />$\min_{w_i} \sum_{i=1}^N (RC_i - \frac{\sigma}{N})^2$</td>
      <td>变量无主次, 分解变简单<br /><br />适合用cyclic coordinate descend优化$w_i$</td>
    </tr>
  </tbody>
</table>

<h3 id="2-风险分解">2. 风险分解</h3>

<p>用协方差矩阵 $\Sigma$  衡量样本的组合相关性</p>

\[\frac{\partial \sigma}{\partial w_i}=\frac{\partial}{\partial w_i}( \sqrt{w^T\Sigma w}) \overset{\text{幂函数求导}}{=} \frac{1}{2\sqrt{w^T\Sigma w}} \cdot \frac{\partial (w^T\Sigma w)}{\partial w_i} = \frac{1}{2\sigma} \cdot 2(\Sigma w)_i = \frac{(\Sigma w)_i}{\sigma}\]

<p>其中关于 $w^T\Sigma w$ 的求导细节展开如下:
\(\begin{aligned}
\frac{\partial (w^T\Sigma w)}{\partial w_i} &amp;= \frac{\partial}{\partial w_i} \left(\sum_j \sum_k w_j \Sigma_{jk} w_k\right) \\
&amp;= \frac{\partial}{\partial w_i} \left( w_i \Sigma_{ii} w_i + \sum_{k \neq i} w_i \Sigma_{ik} w_k + \sum_{j \neq i} w_j \Sigma_{ji} w_i + \sum_{j \neq i, k \neq i} w_j \Sigma_{jk} w_k \right) \\
&amp;= 2w_i \Sigma_{ii} + \sum_{k \neq i} \Sigma_{ik} w_k + \sum_{j \neq i} w_j \Sigma_{ji} \\
&amp;= \sum_{k} \Sigma_{ik} w_k + \sum_{j} w_j \Sigma_{ji} \\
&amp;= (\Sigma w)_i + (\Sigma^T w)_i \\
&amp;= 2(\Sigma w)_i \quad (\text{因协方差矩阵对称 } \Sigma = \Sigma^T)
\end{aligned}\)</p>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="finance" /><category term="content" /><summary type="html"><![CDATA[单个alpha的性能]]></summary></entry><entry><title type="html">消毒液</title><link href="https://roshameow.github.io//personal_homepage/daily/disinfectant/" rel="alternate" type="text/html" title="消毒液" /><published>2025-11-10T00:00:00+00:00</published><updated>2025-11-10T08:06:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/daily/disinfectant</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/daily/disinfectant/"><![CDATA[]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="daily" /><category term="content" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">代码模块的多维索引</title><link href="https://roshameow.github.io//personal_homepage/code/tag-code/" rel="alternate" type="text/html" title="代码模块的多维索引" /><published>2025-11-06T00:00:00+00:00</published><updated>2026-01-20T17:46:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/code/tag-code</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/code/tag-code/"><![CDATA[<p>记录讨论代码模块多维索引的发展</p>

<h2 id="-一从语言设计角度看从物理模块到语义模块">🧩 一、从语言设计角度看：从「物理模块」到「语义模块」</h2>

<p>传统语言的模块系统是<strong>文件层级绑定的命名空间</strong>：</p>

<ul>
  <li>Python：<code class="language-plaintext highlighter-rouge">import module.submodule</code></li>
  <li>Java：<code class="language-plaintext highlighter-rouge">package com.example.util</code></li>
  <li>C++：基于 include 路径</li>
  <li>Rust：基于 <code class="language-plaintext highlighter-rouge">mod</code> 文件树</li>
</ul>

<p>但未来趋势正往<strong>语义模块（semantic module）</strong>发展，也就是：</p>

<blockquote>
  <p>模块不由文件夹决定，而由「意图」或「语义标签」定义。</p>
</blockquote>

<p>一些现代语言的迹象：</p>

<ul>
  <li><strong>Swift Package Manager</strong> 已经支持 target-based 依赖，可跨文件复用；</li>
  <li><strong>Rust Crates + feature flags</strong> 开始允许 feature-based 组合；</li>
  <li><strong>CUE / Bazel</strong> 通过标签（labels）管理依赖；</li>
  <li><strong>ReScript / Rome / Deno</strong> 正在探索 import maps 与语义分组。</li>
</ul>

<p>这说明整个行业在从 “文件组织” 向 “语义组织” 过渡。</p>

<hr />

<h2 id="-二从工程实践看tag-是多维索引的一种形式">🧠 二、从工程实践看：tag 是“多维索引”的一种形式</h2>

<p>软件结构现在普遍面对的一个问题是：</p>

<blockquote>
  <p>代码的「用途」比代码的「位置」更重要。</p>
</blockquote>

<p>比如：</p>

<ul>
  <li>一个函数同时属于 “data-cleaning” 和 “ML-preprocessing”；</li>
  <li>一个模块既是 “API endpoint” 又是 “business rule”；</li>
  <li>一个 class 在 “experiment” 和 “production” 中都被使用。</li>
</ul>

<p><strong>文件夹结构只能表达单继承</strong>。
但现代系统需要<strong>多继承式逻辑分类</strong>，这就是 tag 的优势。</p>

<p>你可以理解为：</p>

<ul>
  <li>文件夹层级 = 树状组织；</li>
  <li>tag 体系 = 多维超图组织。</li>
</ul>

<p>在大型项目中，已经有类似趋势：</p>

<ul>
  <li><strong>monorepo + metadata-based build</strong>（如 Google 的 Blaze / Bazel）</li>
  <li><strong>component registry</strong>（如 Web Components、React Storybook、Unity ECS）</li>
  <li><strong>ML pipeline DAG</strong>（节点通过类型和标签组装）</li>
  <li><strong>Infrastructure as Code (IaC)</strong> 的资源管理，也通过标签做分组调度</li>
</ul>

<p>这些都不是传统意义上的“目录组织”，而是“属性驱动组织”。</p>

<hr />

<h2 id="-三从-ai-辅助开发看tag-模块是机器可理解的知识单元">🤖 三、从 AI 辅助开发看：tag 模块是「机器可理解的知识单元」</h2>

<p>在 AI 代码生成/检索领域，tag 化的组织方式简直是理想形态：</p>

<ul>
  <li>AI 可以根据任务语义（“时间序列特征提取”）直接检索带有对应 tag 的函数；</li>
  <li>tag 可以承载更丰富的上下文（依赖关系、使用场景、复杂度、作者）；</li>
  <li>在代码搜索、重构、自动文档生成中，这类“语义索引”比路径树高效得多。</li>
</ul>

<p>这其实是<strong>代码转向知识图谱化（code as knowledge graph）</strong>的一个趋势。
未来 IDE（或 AI 编程助手）可能这样工作：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>query: "Find all functions tagged with 'ts_zscore' and 'alpha_transform'"
→ semantic code graph lookup
→ compose into new alpha factor
</code></pre></div></div>

<p>这已经在 GitHub Copilot、Cursor、Sourcegraph Cody、Gemini Code Assist 的实验版本中初现端倪。</p>

<hr />

<h2 id="-四从知识结构演化看从树到图">🌌 四、从知识结构演化看：从「树」到「图」</h2>

<p>整个信息管理领域（文档、代码、数据库、笔记）都在经历同样的结构演变：</p>

<table>
  <thead>
    <tr>
      <th>阶段</th>
      <th>组织方式</th>
      <th>代表</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1️⃣ 树结构</td>
      <td>文件夹、类继承</td>
      <td>Python 包、C++ 头文件</td>
    </tr>
    <tr>
      <td>2️⃣ 网格结构</td>
      <td>import 依赖图</td>
      <td>JS bundler、Rust crates</td>
    </tr>
    <tr>
      <td>3️⃣ 图结构</td>
      <td>tag + 语义链接</td>
      <td>Obsidian、Notion AI、LlamaIndex</td>
    </tr>
    <tr>
      <td>4️⃣ 知识层</td>
      <td>意图索引、语义模块</td>
      <td>未来 IDE / CodeGraph</td>
    </tr>
  </tbody>
</table>

<p>代码组织迟早会跟随这一趋势。
换句话说：<strong>tag-based 代码组织不是“异想天开”，而是文件系统式编程的下一步进化。</strong></p>

<hr />

<h2 id="-未来可能的形态">🚀 未来可能的形态</h2>

<p>未来 IDE 或语言生态可能这样工作：</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@tag</span><span class="p">(</span><span class="sh">"</span><span class="s">data</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">io</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">ml</span><span class="sh">"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">load_dataset</span><span class="p">(...):</span> <span class="bp">...</span>

<span class="c1"># 直接用语义查询或导入
</span><span class="kn">from</span> <span class="n">semantic</span> <span class="kn">import</span> <span class="n">tag</span> <span class="k">as</span> <span class="n">T</span>
<span class="n">data_utils</span> <span class="o">=</span> <span class="nc">T</span><span class="p">(</span><span class="sh">"</span><span class="s">data</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">io</span><span class="sh">"</span><span class="p">)</span>

<span class="n">data_utils</span><span class="p">.</span><span class="nf">load_dataset</span><span class="p">()</span>
</code></pre></div></div>

<p>或者：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import @data, @ml
</code></pre></div></div>

<p>这种“tag 作为导入单元”的语法在一些研究语言（如 Eve、DarkLang、Unison）中已经开始出现。</p>

<hr />

<h2 id="-总结判断">🔮 总结判断</h2>

<table>
  <thead>
    <tr>
      <th>维度</th>
      <th>趋势</th>
      <th>现状</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>编程语言</td>
      <td>向语义模块演化</td>
      <td>需要 import hook 支持</td>
    </tr>
    <tr>
      <td>工程实践</td>
      <td>向多维组织演化</td>
      <td>tag 体系在 CI/CD 已普遍存在</td>
    </tr>
    <tr>
      <td>AI 辅助</td>
      <td>强烈依赖 tag 化代码</td>
      <td>正在快速推进</td>
    </tr>
    <tr>
      <td>IDE 支持</td>
      <td>未来版本将内建语义索引</td>
      <td>初步阶段（VSCode Semantic Index）</td>
    </tr>
  </tbody>
</table>

<blockquote>
  <p>✅ <strong>结论</strong>
是的——“tag 化代码组织”非常可能是未来方向，
但不是取代目录结构，而是<strong>覆盖在其之上的一层语义索引层</strong>。
文件树仍然存在，但它只是物理实现，<strong>tag 层才是语义组织的核心。</strong></p>
</blockquote>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="code" /><category term="content" /><summary type="html"><![CDATA[记录讨论代码模块多维索引的发展]]></summary></entry><entry><title type="html">服务器发送消息通知</title><link href="https://roshameow.github.io//personal_homepage/tool/message/" rel="alternate" type="text/html" title="服务器发送消息通知" /><published>2025-10-23T00:00:00+00:00</published><updated>2025-11-04T08:24:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/tool/message</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/tool/message/"><![CDATA[<p>发送文字/表格/图片的混合消息</p>

<ul>
  <li>飞书: 支持富文本和卡片
    <ul>
      <li>普通消息</li>
      <li>消息卡片
        <ul>
          <li>打开 <a href="https://open.feishu.cn/">飞书开放平台</a>。</li>
          <li>在企业自建应用, 创建机器人
            <ul>
              <li>获得机器人的App ID, App Secret</li>
              <li>在权限管理, 给机器人添加上传图片的权限: <code class="language-plaintext highlighter-rouge">im:message</code>
                <ul>
                  <li>图片需要先上传到平台, 在消息里用链接</li>
                  <li>每次token只能保存两个小时.</li>
                </ul>
              </li>
            </ul>
          </li>
          <li>在开放平台的开发文档里搜发送卡片的各种示例
            <ul>
              <li>llm没法知道专用格式. 可能需要可以上网的agent</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>邮件: 支持html渲染
    <ul>
      <li>在gmail开启两步验证, 然后开启 https://myaccount.google.com/apppasswords 就可以</li>
    </ul>
  </li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="tool" /><category term="content" /><summary type="html"><![CDATA[发送文字/表格/图片的混合消息]]></summary></entry><entry><title type="html">hash映射</title><link href="https://roshameow.github.io//personal_homepage/algorithm/alpha12/" rel="alternate" type="text/html" title="hash映射" /><published>2025-09-25T00:00:00+00:00</published><updated>2025-10-05T19:42:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/algorithm/alpha12</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/algorithm/alpha12/"><![CDATA[<p>估算alpha id 和什么有关</p>

<p>有些hash会非常相似. 目的, 得到alpha id的全部编码信息: 秒级的timestamp+machine id</p>

<p>44/s. 2640/min. 1w consultant. 每人回测100/ 5min.</p>

<p>44x3600x24/10000 = 380 次/天. 这和实际结果很不符合.</p>

<p>1天5w.</p>
<h3 id="假设1">假设1:</h3>

<table>
  <thead>
    <tr>
      <th>可能的方案</th>
      <th>做法</th>
      <th>特点</th>
      <th>输入</th>
      <th>输出</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>密码</strong>学hash函数<br />(SHA-256 / SHA-1 / MD5)</td>
      <td><strong>碎纸机</strong>:<br />→ 生成和输出相同的初始值<br />加入输入的内容进行各种非线性混合<br />重复多次</td>
      <td>1. 相近的输入会输出完全不同的结果<br />2. 可以人为制造hash冲突</td>
      <td>任意长度二进制文本</td>
      <td>md5: 128bit/32hex<br />SHA-256: 256bit</td>
    </tr>
    <tr>
      <td>多项式除法的<strong>校验</strong>码<br />(CRC32)</td>
      <td>把输入的任意长度看成(mod2)多项式$M(x)$<br />→ 指定生成多项式$G(x)$ <br />得到输出为 residue $R(x)$<br /><br />实际中通过移位+XOR实现</td>
      <td>1. 常见的变化, 输出可预测<br />(单比特错、双比特错、突发错)</td>
      <td>任意长度二进制文本</td>
      <td>CRC32: 32bit/8hex<br /></td>
    </tr>
    <tr>
      <td>文本<strong>去重</strong>, 片段<strong>匹配</strong><br />Rolling Hash</td>
      <td>把字符串看成B进制整数, 对M取residue</td>
      <td>1. 计算方便<br />2. 根据hash能快速找到相同字串<br />3. 不是强校验, 冲突常见<br />4. 相似字串hash差别大</td>
      <td>任意长度字符串</td>
      <td>整数</td>
    </tr>
    <tr>
      <td>相似度<strong>聚类</strong>(LSH)<br />(MinHash, SimHash)</td>
      <td>MinHash:<br />提取文本特征, 映射成整数集合<br />→ 用n组随机hash函数<br />$h(x)=ax+b(\mod P)$ 对集合每个元素hash<br />每个hash值取hash最小值<br /><br /><br /><br /></td>
      <td>1. 比较hash值有多少位重复, <br />就能知道文本中有多少重复特征<br />2. 可以把整数分成band, <br />用于LSH bucketing</td>
      <td>任意大小整数集合</td>
      <td>取决于算法的超参数<br />n 位 int vector<br /></td>
    </tr>
    <tr>
      <td> </td>
      <td>SimHash(PCAHash, Spectral Hash):<br />输入向量<br />→用n个投影向量<br />计算投影, 二进制化</td>
      <td>1. 相似的向量会使hash值相同位数多,<br />从而可以被LSH bucketing召回<br />2. 过程和逻辑回归一样都是线性+激活. <br />用逻辑回归训练+预测, <br />准确率应该高于0.5</td>
      <td>固定长度向量</td>
      <td>n bit</td>
    </tr>
    <tr>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<ul>
  <li>假设1: 由pnl(长2496位的float vector)编码
    <ul>
      <li>pnl 是</li>
    </ul>
  </li>
</ul>

<p>相同pnl不同user -&gt; hash不同
排除这个假设的原因: 生成一系列pnl完全相同的alpha, hash有些是相似但不同, 但有些完全不同.</p>

<h3 id="假设2">假设2</h3>

<p>user id和hash同为7位. 是否用xor加密. 验证.</p>

<p><code class="language-plaintext highlighter-rouge">hash_a ^ id_a == hash_b ^ id_b</code> 也 <strong>不成立</strong></p>
<h3 id="假设2-1">假设2</h3>

<p>expression</p>
<ul>
  <li>ast clean</li>
</ul>

<p>排除这个假设的原因: 两个表达式完全不相关的alpha, hash相似</p>
<ul>
  <li>猜测是不是settings, 表达式, user id的联合编码.</li>
</ul>

<p>统计重复的hash前缀个数</p>
<h3 id="假设3">假设3</h3>

<p>时间</p>

<p>统计「前缀 → 时间」的关系
把 dateCreated 转成秒或分钟级的 时间戳。
按 hash 前缀分组，算时间戳的 均值 / 分布范围。
如果「相同前缀的时间非常接近」，说明前缀和时间相关</p>

<p>前缀与创建时间的相关性
出现次数多的前缀通常集中在较短时间区间内（span_sec 不大），说明相同前缀的 ID 可能是同时生成的。
反过来, 固定时间段, 前缀也固定同样的44种. 跨相邻时间段, 就变成88种.</p>

<p>这验证了你之前的猜测：hash 前缀和 dateCreated 时间有关，ID 的前缀不是完全随机，生成算法可能会受时间影响或按批次生成</p>

<p>可视化验证
可以画出 时间 vs hash 前缀 的散点图</p>

<p>这样你就能看到：
前缀长度为 1 → 有多少种不同前缀
前缀长度为 2 → 有多少种不同前缀
…
直到 max_len。
📈 如果前缀确实和时间强相关，你会看到 前缀长度增加时，唯一前缀数量接近样本数（说明前缀逐渐唯一化）。</p>

<p>时间主导，但横向有并发带 这就是我现在看到的情况</p>

<p>同样时间平行带大概有44个左右</p>

<p>歪路:
猜测prefix之间的关系. 👍 从你的结果可以看出明显的规律：
mod 16
大部分前缀落在 [0,5,10,15,6,9,…]，集中在少数几个余数上。
说明前缀低位每 16 有一个间隔的规律，但还有一些偏移（可能是并发带/随机部分）。
mod 32
余数集中在 16,0,10 等位置，说明低位有更大的分段，仍然有少量分散。
mod 64
集中在 16 和几个其他余数上，每个余数对应大概一组“平行带”。
这非常吻合你观察到的 “同一时间平行带大概 44 个左右” 的现象。
低位取模 64 时，可以把并发带分离出来。
mod 128
更大模数开始显得稀疏，主要几个值有重复。
说明前缀的低位并没有均匀分布，而是有特定分片/并发槽的规律。</p>

<p><strong>按 count 或 span_sec 排序</strong>，那就用 <code class="language-plaintext highlighter-rouge">sort_values</code></p>

<p>只用到44个字符</p>

<p>为什么选择44字符? 可能是URL-safe / visually unambiguous alphabet 防止混淆 -&gt; I/L, O/0 没有这种规律</p>

<p>有 <strong>纯数字 + 大写</strong>：<code class="language-plaintext highlighter-rouge">0G, 1G, … 9G</code>. 猜测不同平行带可能等距 -&gt; 图上就能看出是个错误猜测</p>

<p>猜测同一种混淆方式? 没法验证</p>

<p>猜测通过出现频率计算混淆顺序 -&gt; 这种想法没有道理</p>

<p>把平行带分开计算</p>

<ul>
  <li>发现hash变化有明显的周期,</li>
  <li>
    <p>画图</p>
  </li>
  <li>推测BASE44的顺序
    <ul>
      <li>是统一的?
        <ul>
          <li>如果是统一的, 应该是真正的进位. 但是同时出现了 0N-&gt; 0x, PY -&gt; Px, pM-&gt;px 所以我的猜测应该不对</li>
        </ul>
      </li>
      <li>还是不同bucket 不同</li>
    </ul>
  </li>
  <li>指数假设: <code class="language-plaintext highlighter-rouge">log(decoded-intercept) = log(A) + B * timestamp</code>
    <ul>
      <li>固定intercept的情况</li>
      <li>exp优化的自由度太高了. 数值算法无法收敛</li>
    </ul>
  </li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="algorithm" /><category term="content" /><summary type="html"><![CDATA[估算alpha id 和什么有关]]></summary></entry><entry><title type="html">pv 衍生数据</title><link href="https://roshameow.github.io//personal_homepage/data/alpha11/" rel="alternate" type="text/html" title="pv 衍生数据" /><published>2025-09-19T00:00:00+00:00</published><updated>2026-01-06T04:31:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/data/alpha11</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/data/alpha11/"><![CDATA[<h2 id="pv数据">pv数据</h2>

<table>
  <thead>
    <tr>
      <th><strong>0阶数据 (原始)</strong></th>
      <th><strong>一阶数据 (派生)</strong></th>
      <th><strong>二阶数据 (高阶特征 &amp; 技术指标)</strong></th>
      <th><strong>三阶数据 (组合/因子)</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>open</strong></td>
      <td> </td>
      <td><strong>cumret</strong>:<code class="language-plaintext highlighter-rouge">prod(1+returns)-1</code><br /><strong>excess_ret</strong>:<code class="language-plaintext highlighter-rouge">returns - rf</code><br /><strong>fear</strong>:<code class="language-plaintext highlighter-rouge">ts_mean(abs(returns - market_return)/(abs(returns)+abs(market_return)), 20)</code></td>
      <td><strong>liquidity-adjusted return</strong>:<code class="language-plaintext highlighter-rouge">returns / (1+Illiquidity)</code></td>
    </tr>
    <tr>
      <td><strong>close</strong></td>
      <td><strong>returns</strong>:<code class="language-plaintext highlighter-rouge">(close - close[-1]) / close[-1]</code><br />—<br /><strong>vwap</strong>:<code class="language-plaintext highlighter-rouge">sum(close*volume)/sum(volume)</code><br /></td>
      <td><strong>volatility</strong>:<code class="language-plaintext highlighter-rouge">ts_std(returns, 20)</code><br /><strong>RSI</strong> (relative strength index)<br /><strong>MACD</strong> (EMA_diff(close))<br /><strong>ROC</strong>:<code class="language-plaintext highlighter-rouge">(close_t/close_{t-n} - 1)</code></td>
      <td><strong>risk-adjusted momentum</strong>:<code class="language-plaintext highlighter-rouge">momentum / volatility</code></td>
    </tr>
    <tr>
      <td><strong>high</strong></td>
      <td> </td>
      <td><strong>maxdrawdown</strong>:<code class="language-plaintext highlighter-rouge">(peak(close) - trough(close)) / peak(close)</code><br /><strong>Williams %R</strong>:<code class="language-plaintext highlighter-rouge">(HH_n - close)/(HH_n-LL_n)</code></td>
      <td><strong>volume-adjusted maxdrawdown</strong>:<code class="language-plaintext highlighter-rouge">maxdrawdown / adv20</code></td>
    </tr>
    <tr>
      <td><strong>low</strong></td>
      <td><br /><br /></td>
      <td><strong>downside_vol</strong>:<code class="language-plaintext highlighter-rouge">ts_std(min(returns,0),20)</code><br /><strong>Stochastic %K/%D</strong>:<code class="language-plaintext highlighter-rouge">(close - LL_n)/(HH_n-LL_n)</code></td>
      <td><strong>reversal-risk</strong>:<code class="language-plaintext highlighter-rouge">(-returns(1m)) / downside_vol</code></td>
    </tr>
    <tr>
      <td><strong>volume</strong></td>
      <td><strong>adv20</strong>:<code class="language-plaintext highlighter-rouge">ts_mean(volume, 20)</code><br /><strong>log_volume</strong>:<code class="language-plaintext highlighter-rouge">log(volume)</code><br /><strong>volume_z</strong>:<code class="language-plaintext highlighter-rouge">(volume - mean(volume,20))/std</code></td>
      <td><strong>Illiquidity</strong>:<code class="language-plaintext highlighter-rouge">abs(returns) / volume</code><br /><strong>OBV</strong> (on-balance volume)<br /><strong>CMF</strong> (Chaikin money flow)</td>
      <td><strong>liquidity_momentum</strong>:<code class="language-plaintext highlighter-rouge">momentum * (-Illiquidity)</code></td>
    </tr>
    <tr>
      <td><strong>sharesout</strong></td>
      <td><strong>mkt_cap</strong>:<code class="language-plaintext highlighter-rouge">close * sharesout</code><br /><strong>turnover</strong>:<code class="language-plaintext highlighter-rouge">volume / sharesout</code><br /><strong>turn20</strong>:<code class="language-plaintext highlighter-rouge">ts_mean(turnover, 20)</code></td>
      <td><strong>size_effect</strong>:<code class="language-plaintext highlighter-rouge">log(mkt_cap)</code></td>
      <td><strong>scaled_turnover</strong>:<code class="language-plaintext highlighter-rouge">turnover / size_effect</code></td>
    </tr>
    <tr>
      <td><strong>vwap</strong></td>
      <td> </td>
      <td><strong>spread</strong>:<code class="language-plaintext highlighter-rouge">(high - low)/vwap</code><br /><strong>Amihud illiq</strong>:<code class="language-plaintext highlighter-rouge">ts_mean(abs(returns)/dollar_volume,20)</code></td>
      <td><strong>liquidity_volatility</strong>:<code class="language-plaintext highlighter-rouge">volatility * Amihud_illiq</code></td>
    </tr>
    <tr>
      <td><strong>dollar_vol</strong></td>
      <td><strong>dollar_volume</strong>:<code class="language-plaintext highlighter-rouge">close * volume</code></td>
      <td><strong>turnover_vol</strong>:<code class="language-plaintext highlighter-rouge">ts_std(turnover,20)</code></td>
      <td><strong>volume_volatility_ratio</strong>:<code class="language-plaintext highlighter-rouge">volatility / turnover_vol</code></td>
    </tr>
    <tr>
      <td><strong>ohlc</strong></td>
      <td><strong>hl_range</strong>:<code class="language-plaintext highlighter-rouge">(high - low)/close</code><br /><strong>oc_gap/overnight return</strong>:<code class="language-plaintext highlighter-rouge">(open - close[-1])/close[-1]</code></td>
      <td><strong>realized_vol</strong>:<code class="language-plaintext highlighter-rouge">sqrt(sum(log(high/low)^2 + log(close/open)^2 ... over window))</code></td>
      <td><strong>gap_volatility</strong>:<code class="language-plaintext highlighter-rouge">oc_gap / realized_vol</code></td>
    </tr>
    <tr>
      <td><strong>returns</strong></td>
      <td> </td>
      <td><strong>momentum</strong>:<code class="language-plaintext highlighter-rouge">ts_mean(returns, 12m)</code><br /><strong>reversal</strong>:<code class="language-plaintext highlighter-rouge">-returns(1m)</code></td>
      <td><strong>momentum_reversal</strong>:<code class="language-plaintext highlighter-rouge">momentum * reversal</code><strong>vol_mom</strong>:<code class="language-plaintext highlighter-rouge">momentum * (1/volatility)</code></td>
    </tr>
  </tbody>
</table>

<ul>
  <li>rsv(未成熟随机值) = (close - ts_min(low, n)) / (ts_max(high, n) - ts_min(low, n)) n=9</li>
</ul>

<p>对应关系</p>
<ul>
  <li>cap = close x sharesout</li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="data" /><category term="content" /><summary type="html"><![CDATA[pv数据]]></summary></entry><entry><title type="html">nano-banana 效果: 常用的作图功能</title><link href="https://roshameow.github.io//personal_homepage/photo/stable-diffusion10/" rel="alternate" type="text/html" title="nano-banana 效果: 常用的作图功能" /><published>2025-09-02T00:00:00+00:00</published><updated>2025-09-17T12:56:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/photo/stable-diffusion10</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/photo/stable-diffusion10/"><![CDATA[<p>换背景(inpaint)</p>

<p>修改局部</p>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="photo" /><category term="content" /><summary type="html"><![CDATA[换背景(inpaint)]]></summary></entry><entry><title type="html">mac系统字典</title><link href="https://roshameow.github.io//personal_homepage/tool/mac/dictionary/" rel="alternate" type="text/html" title="mac系统字典" /><published>2025-08-16T00:00:00+00:00</published><updated>2025-08-19T18:47:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/tool/mac/dictionary</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/tool/mac/dictionary/"><![CDATA[<p>目标是把 MongoDB 里存放的术语和定义，打包成可以在 <strong>macOS 自带“字典”应用</strong>中查询的本地词典。</p>

<h2 id="成功步骤">成功步骤</h2>

<p>用脚本实现1-2-3步骤即可. 代码:  <a href="https://gist.github.com/roshameow/15d29ace410e296cdbd0da4c4531ba14#file-mongo_2_dictionary-py"><strong>mongo_2_dictionary.py</strong></a></p>

<ol>
  <li>把数据转成 <strong>Apple Dictionary 支持的 TSV 格式</strong>。
    <ul>
      <li>⚠️ 避坑：不要用 <code class="language-plaintext highlighter-rouge">\t\n</code> , 用 <strong>HTML 标签</strong>来控制排版，用 <code class="language-plaintext highlighter-rouge">&lt;div&gt;</code> 表示新行，用 <code class="language-plaintext highlighter-rouge">&lt;br&gt;</code> 来做分隔。这样避免了特殊字符被误解析。</li>
    </ul>
  </li>
  <li>用  <a href="https://github.com/ilius/pyglossary">PyGlossary</a> 把 <code class="language-plaintext highlighter-rouge">.tsv</code> 转成 AppleDict 的源文件。<code class="language-plaintext highlighter-rouge">pyglossary dictionary_dump.tsv output.dictionary --read-format=Tabfile --write-format=AppleDict</code>
    <ul>
      <li>⚠️ 避坑：不要用 CSV,  一开始我试过 CSV，但 AppleDict 的编译脚本会直接解析失败。</li>
    </ul>
  </li>
  <li>编译 Apple Dictionary
    <ul>
      <li>PyGlossary 会生成一个字典目录，里面包含：<code class="language-plaintext highlighter-rouge">.xml</code> 源文件,  <code class="language-plaintext highlighter-rouge">.css</code> 样式文件, <code class="language-plaintext highlighter-rouge">.plist</code> 配置文件, <code class="language-plaintext highlighter-rouge">Makefile</code></li>
      <li>正常情况下，进入目录直接运行：<code class="language-plaintext highlighter-rouge">make ; make install</code></li>
    </ul>
  </li>
  <li>安装完成后，打开 macOS 自带的“字典”应用，在settting里勾选新字典。</li>
</ol>

<h2 id="工具和坑点总结">工具和坑点总结</h2>

<ul>
  <li><strong>需要安装 Dictionary Development Kit (DDK)</strong>
    <ul>
      <li>据说macOS 有自带的 <code class="language-plaintext highlighter-rouge">dictutil</code> 我没有找到。</li>
      <li>DDK 要单独安装（Xcode 附带）。</li>
    </ul>
  </li>
  <li><strong>不要用 DDK 官方的 <code class="language-plaintext highlighter-rouge">build_dict.sh</code></strong>, 用  <a href="https://github.com/ilius/pyglossary">PyGlossary</a> 生成
    <ul>
      <li>这个脚本里调用的 <code class="language-plaintext highlighter-rouge">make_line.pl</code> ，perl 脚本里有 bug。无法解决. xml 格式也非常讨厌</li>
    </ul>
  </li>
  <li><strong>样式限制</strong>
    <ul>
      <li>Apple Dictionary 对标题样式是写死的，没法自定义。</li>
    </ul>
  </li>
  <li><strong>调试</strong>
    <ul>
      <li>我在自己本地的dev版app上调试, 发现字典不是实时更新的, <strong>需要重启之后才会加载新的</strong> (可能是<code class="language-plaintext highlighter-rouge">DictionaryServices.framework</code> 的行为特性, 每个app单独一个缓存, 字典也在里面, 不会热更新)</li>
    </ul>
  </li>
</ul>

<h2 id="结果">结果</h2>

<p><img src="/personal_homepage/docs/attachment/Pasted%20image%2020250819114921.png" alt="Pasted image 20250819114921.png" width="300" /></p>

<ul>
  <li>效果和官方字典差不多</li>
  <li>但是在一些网页的在线代码编辑器(可能用的是自绘控件, 而不是macos的Cocoa文本系统)和微信(lookup被软件禁用)不能用</li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="tool" /><category term="mac" /><category term="content" /><summary type="html"><![CDATA[目标是把 MongoDB 里存放的术语和定义，打包成可以在 macOS 自带“字典”应用中查询的本地词典。]]></summary></entry><entry><title type="html">代码语法解析</title><link href="https://roshameow.github.io//personal_homepage/code/algorithm/string/" rel="alternate" type="text/html" title="代码语法解析" /><published>2025-08-10T00:00:00+00:00</published><updated>2025-09-12T17:50:00+00:00</updated><id>https://roshameow.github.io//personal_homepage/code/algorithm/string</id><content type="html" xml:base="https://roshameow.github.io//personal_homepage/code/algorithm/string/"><![CDATA[<h2 id="三元运算符ternary解析">三元运算符(ternary)解析</h2>

<p>把 <code class="language-plaintext highlighter-rouge">...?...:...</code> 处理成<code class="language-plaintext highlighter-rouge">if_else(...,...,...)</code> 的形式.</p>

<p>初衷是用正则替换把对应DSL的operator转换成python语言, 然后用python的ast 直接解析. 但是三元运算符的处理比较复杂, Python 中并没有直接对应的语法结构, 导致没法简单的替换.</p>

<p>可以把字符串token解析成<strong>AST 的构建过程</strong>理解成“对运算符按优先级排序”的过程.</p>

<table>
  <thead>
    <tr>
      <th>方法</th>
      <th>优缺点</th>
      <th>类比排序思路</th>
      <th>平均复杂度</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>用正则表达式替换三元运算符</td>
      <td>思路naive, 但是可读性差，难以维护</td>
      <td> </td>
      <td>O(n logn)+kO(n)<br />全字符串扫描+递归</td>
    </tr>
    <tr>
      <td>设计语法树解析器（Parser）</td>
      <td>灵活性高, 但实现较复杂</td>
      <td>选择排序</td>
      <td>O(n logn)<br />近似二分递归</td>
    </tr>
    <tr>
      <td>结合 <a href="https://www.google.com/search?client=safari&amp;rls=en&amp;q=pratt+parser&amp;ie=UTF-8&amp;oe=UTF-8">Pratt Parser</a> 优化解析</td>
      <td>代码简洁, 可读性高, 扩展性好</td>
      <td>插入排序/堆排序</td>
      <td>O(n)<br />线性扫描</td>
    </tr>
  </tbody>
</table>

<h3 id="直接用字符串替换">直接用字符串替换</h3>

<ul>
  <li>用字符串正则查找tenary并替换</li>
  <li>递归处理?: 和括号, =, 逗号的关系
    <ul>
      <li>处理 括号, 逗号 都依赖栈来正确处理嵌套结构</li>
    </ul>
  </li>
</ul>

<h3 id="写parser处理">写parser处理</h3>

<p>可以通过编写自定义的解析器来处理三元运算符。下面是一些处理流程：</p>
<ol>
  <li>定义:
    <ol>
      <li><strong>定义 AST 节点</strong>：设计不同类型的节点来表示表达式，如常量、变量、运算符等。</li>
      <li><strong>Tokenize</strong>：将源代码字符串分割成 tokens（例如：数字、运算符、字符串等）。
        <ol>
          <li>例如: ``a&lt;0.2?<code class="language-plaintext highlighter-rouge"> → </code>[(“NAME”,”a”) (“OP”,”&lt;”) (“NUMBER”,”0.2”) (“QMARK”,”?”)]`</li>
        </ol>
      </li>
      <li><strong>定义优先级</strong>: <strong>找表达式中最低的优先级处理</strong>.</li>
    </ol>
  </li>
  <li>具体流程:
    <ol>
      <li><strong>预处理（字符串替换/注释/关键字替换）</strong>
        <ul>
          <li>把wq expr 中的<code class="language-plaintext highlighter-rouge">'...'</code> / <code class="language-plaintext highlighter-rouge">"..."</code> 用占位符替换
            <ul>
              <li><code class="language-plaintext highlighter-rouge">ts_sum(group_zscore(a&lt;0.2? (a+0.7):(a&gt;0.9? a:0.9),bucket(rank(cap),range='0.1, 1, 0.1')),5) -&gt; ts_sum(group_zscore(a&lt;0.2? (a+0.7):(a&gt;0.9? a:0.9),bucket(rank(cap),range=__STR_CONST_0__)),5)</code></li>
            </ul>
          </li>
          <li>做若干文本替换（or/and/not → logical_or/logical_and/…、–→+、NaN→nan 等）。</li>
          <li>删除注释（/* … */ 与行注释 // 或 #）。</li>
          <li>按分号 ; 切分成多条<strong>语句</strong>，逐条 tokenize() → parse_expr() → to_python()。</li>
          <li>token 化</li>
          <li>自顶向下递归解析（赋值 → 三元→ 二元<strong>按最低 precedence 为根</strong> → 原子/函数/一元）</li>
        </ul>
      </li>
      <li><strong>解析每句代码:</strong>
        <ul>
          <li>顶层赋值检测
            <ul>
              <li>去掉最外层的分号</li>
              <li>检查最外层(用括号记录层数)的赋值 <code class="language-plaintext highlighter-rouge">=</code>, 把赋值语句的左右两侧分开.</li>
            </ul>
          </li>
          <li>三元检测
            <ul>
              <li>检查最外层 ? 的第一个位置作为三元入口, 再从 <code class="language-plaintext highlighter-rouge">?</code> 后扫描并找到对应的最外层 <code class="language-plaintext highlighter-rouge">:</code>（depth=0）的位置</li>
              <li>每当遇到括号要剥去括号重新检测三元</li>
            </ul>
          </li>
          <li>二元检测(binop)
            <ul>
              <li>检查最外层优先级最低的op. 优先级相同, 取最右边的op拆分(左结合)</li>
            </ul>
          </li>
          <li>一元检测(atom):
            <ul>
              <li>检查 一元运算符(!, -) -&gt; 单token原子(number, string, name) -&gt; function call -&gt; 检查每个参数</li>
            </ul>
          </li>
        </ul>
      </li>
      <li><strong>构建 AST</strong>
        <ul>
          <li>递归生成 Python 代码: 对不同节点分别处理</li>
          <li>还原字符串并输出</li>
          <li>每条语句生成的 Python 片段再还原字符串常量占位符.</li>
        </ul>
      </li>
      <li><strong>收集所有处理过的</strong>语句<strong>并最终用 \n 拼接返回</strong></li>
    </ol>
  </li>
</ol>

<ul>
  <li>⚠️ 注意点: ast解析<strong>一定要注意代码的覆盖率. 保证不会出现不认识的token, operator, 分支情况</strong>.</li>
</ul>

<h3 id="parse优化">parse优化</h3>

<h4 id="token优化">token优化</h4>

<p>把预处理步骤内化到token中统一处理.</p>
<h4 id="pratt优化">pratt优化</h4>

<p>Pratt parser 其实是 <strong>自顶向下递归下降解析器</strong>的一种优化方式: 不是从最低优先级的字符开始, 而是随着解析从左往右动态的构建ast.</p>

<ul>
  <li>每个token除了优先级外, 定义两个方法: (nud和led)
    <ul>
      <li>nud(null denotation, 前序) 当token出现在表达式开头时</li>
      <li>led(left denotation, 中序) 当 token 出现在 <strong>表达式中间</strong>（左边有东西）时调用</li>
    </ul>
  </li>
</ul>

<p>下面是一个DSL对应的token行为表格.</p>

<table>
  <thead>
    <tr>
      <th>Token/操作符</th>
      <th>进入 nud / led</th>
      <th>触发条件</th>
      <th>动作描述</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>NUMBER</strong></td>
      <td>nud</td>
      <td>token 类型是 <code class="language-plaintext highlighter-rouge">"NUMBER"</code></td>
      <td>- 若全是数字 → <code class="language-plaintext highlighter-rouge">Const(int)</code><br />- 否则 → <code class="language-plaintext highlighter-rouge">Const(float)</code></td>
    </tr>
    <tr>
      <td><strong>STRING</strong></td>
      <td>nud</td>
      <td>token 类型是 <code class="language-plaintext highlighter-rouge">"STRING"</code></td>
      <td>构造 <code class="language-plaintext highlighter-rouge">Const(str)</code>，去掉引号</td>
    </tr>
    <tr>
      <td><strong>NAME(变量)</strong></td>
      <td>nud</td>
      <td>token 类型是 <code class="language-plaintext highlighter-rouge">"NAME"</code><br />且 peek不是<code class="language-plaintext highlighter-rouge">(</code></td>
      <td>返回 <code class="language-plaintext highlighter-rouge">Name</code></td>
    </tr>
    <tr>
      <td><strong>NAME (调用)</strong></td>
      <td>nud</td>
      <td>token 类型是 <code class="language-plaintext highlighter-rouge">"NAME"</code> 且 peek=<code class="language-plaintext highlighter-rouge">(</code><br /><br /> <strong>函数调用</strong></td>
      <td>- 消费 <code class="language-plaintext highlighter-rouge">(</code> → 解析参数列表<br />- 参数支持关键字：<code class="language-plaintext highlighter-rouge">key = value</code><br />- 遇到 <code class="language-plaintext highlighter-rouge">,</code> 继续，否则结束<br />- 消费 <code class="language-plaintext highlighter-rouge">)</code> <br />→ 返回 <code class="language-plaintext highlighter-rouge">Call(Name, args)</code></td>
    </tr>
    <tr>
      <td><strong>LPAREN</strong></td>
      <td>nud</td>
      <td>当前 token = <code class="language-plaintext highlighter-rouge">(</code><br /><br /><a href="#ref">3</a></td>
      <td>- 进入子表达式解析（<code class="language-plaintext highlighter-rouge">rbp=-1000</code>）<br />- 必须遇到 <code class="language-plaintext highlighter-rouge">)</code> 结束<br />- 返回子树</td>
    </tr>
    <tr>
      <td><strong>+ / - (unary)</strong></td>
      <td>nud</td>
      <td>token=OP 且值为 <code class="language-plaintext highlighter-rouge">+/-</code>，在前缀位置</td>
      <td>以 <code class="language-plaintext highlighter-rouge">get_prec("U+/-")</code> 为 rbp 递归解析右操作数 <br />→ <code class="language-plaintext highlighter-rouge">UnaryOp</code></td>
    </tr>
    <tr>
      <td><strong>! (unary not)</strong></td>
      <td>nud</td>
      <td>token=OP 且值为 <code class="language-plaintext highlighter-rouge">!</code></td>
      <td>以 <code class="language-plaintext highlighter-rouge">get_prec("!")</code> 为 rbp 递归解析右操作数 <br />→ <code class="language-plaintext highlighter-rouge">UnaryOp("!", expr)</code></td>
    </tr>
    <tr>
      <td><strong>QMARK (?)</strong></td>
      <td>led</td>
      <td>peek = <code class="language-plaintext highlighter-rouge">QMARK</code> <br />且 <code class="language-plaintext highlighter-rouge">TERNARY_PREC &gt; rbp</code></td>
      <td>- 消费 <code class="language-plaintext highlighter-rouge">?</code><br />- 解析 true_part (<code class="language-plaintext highlighter-rouge">rbp=TERNARY_PREC</code>)<br />- 期望 <code class="language-plaintext highlighter-rouge">:</code><br />- 解析 false_part (<code class="language-plaintext highlighter-rouge">rbp=TERNARY_PREC</code>)<br />- 构造 <code class="language-plaintext highlighter-rouge">Ternary(left, true, false)</code></td>
    </tr>
    <tr>
      <td><strong>二元运算符</strong> <br />(如 <code class="language-plaintext highlighter-rouge">+ - * / ^ &lt; &gt; == != &amp;&amp;</code>)</td>
      <td>led</td>
      <td><code class="language-plaintext highlighter-rouge">peek</code> 发现下一个 token 是操作符 (<code class="language-plaintext highlighter-rouge">OP</code>)，<br />并且该操作符的优先级<br /><code class="language-plaintext highlighter-rouge">lbp &gt; rbp</code> <a href="#ref">1</a> <a href="#ref">2</a> <br /></td>
      <td>- 消费当前操作符（op）<br />- 结合性处理：<br />   如果操作符是左结合（默认情况），则 next_rbp = lbp；<br />   如果操作符是右结合（如 =、^），则 next_rbp = lbp - 0.0001（轻微调整优先级, 为了遇到相同的运算符时继续解析）<br />- 递归调用 parse_expression(next_rbp) 来解析右操作数（right）<br />- 生成 BinOp(left, op, right) 节点</td>
    </tr>
    <tr>
      <td><strong>LPAREN (函数调用)</strong><br /><br /></td>
      <td>led</td>
      <td>peek = <code class="language-plaintext highlighter-rouge">(</code><br /><a href="#ref">3</a><br />支持<strong>更一般化的函数调用</strong>. <br />比如, <br />(a+b)(x)、foo()(x) 这种高阶调用</td>
      <td>- 消费 <code class="language-plaintext highlighter-rouge">(</code> → 解析参数列表<br />- 参数使用 <code class="language-plaintext highlighter-rouge">parse_expression(rbp=-1000)</code><br />- <code class="language-plaintext highlighter-rouge">,</code> 分隔，直到遇到 <code class="language-plaintext highlighter-rouge">)</code><br />- 构造 <code class="language-plaintext highlighter-rouge">Call(left, args)</code></td>
    </tr>
  </tbody>
</table>

<p>表格解释 $\downarrow$ :</p>

<p><span id="ref"></span></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">lbp</code>（left binding precedence, 左操作数绑定优先级, 当前op的优先级）, <code class="language-plaintext highlighter-rouge">rbp</code> (右操作符绑定优先级, 上一个op的优先级)
    <ul>
      <li>当下一个op优先级更高时, ast会不断加深. 当下一个op优先级不足时, ast会从底向上直到找到合适的位置添加</li>
      <li>比如 a = b = c, 在第二个等号处, 把第一个等号的优先级稍稍降低, 保证右侧的优先级更高. 解析为 a = (b = c)</li>
      <li>括号总是最优先的, 直接把rdp降到最低</li>
    </ul>
  </li>
</ul>

<p>a + b x c -d: 
<img src="/personal_homepage/docs/attachment/Pasted%20image%2020250912052333.png" alt="Pasted image 20250912052333.png" width="800" /></p>

<p>a = b = c:</p>

<p><img src="/personal_homepage/docs/attachment/Pasted%20image%2020250912052438.png" alt="Pasted image 20250912052438.png" width="300" /></p>

<h3 id="代码">代码</h3>

<ul>
  <li><a href="https://gist.github.com/roshameow/01c0191fae3c534050fa6ab076640549#file-replace_ternary-py"><strong>replace_ternary.py</strong></a></li>
  <li><a href="https://gist.github.com/roshameow/01c0191fae3c534050fa6ab076640549#file-parser-py"><strong>parser.py</strong></a></li>
  <li><a href="https://gist.github.com/roshameow/01c0191fae3c534050fa6ab076640549#file-pratt_parser-py"><strong>pratt_parser.py</strong></a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;picture&quot;=&gt;&quot;/docs/images/logo.svg&quot;, &quot;email&quot;=&gt;&quot;w.liuatnk@gmail.com&quot;, &quot;twitter&quot;=&gt;nil}</name><email>w.liuatnk@gmail.com</email></author><category term="code" /><category term="algorithm" /><category term="content" /><category term="ast" /><category term="string" /><category term="regularization" /><category term="parser" /><category term="pratt" /><category term="ternary" /><category term="python" /><category term="dsl" /><summary type="html"><![CDATA[三元运算符(ternary)解析]]></summary></entry></feed>