学习笔记
Solidity 与 LP 策略学习笔记
本文整理 Solidity 函数可见性、数据位置和集中流动性策略中的基础判断。两个主题都强调状态边界:Solidity 关注调用与存储状态,LP 策略关注价格区间与仓位状态。
Solidity 函数可见性
| 可见性 | 合约内部直接调用 | 派生合约调用 | 外部账户或合约调用 |
|---|---|---|---|
private |
可以 | 不可以 | 不可以 |
internal |
可以 | 可以 | 不可以 |
public |
可以 | 可以 | 可以 |
external |
不可以 | 不可以直接调用 | 可以 |
external 函数不能在同一合约中通过函数名直接执行内部调用。若确需调用,可使用 this.operation() 发起外部消息调用,但这会改变 msg.sender、增加 Gas,并产生新的调用边界。复用逻辑时,更合理的做法是抽取 internal 函数。
1 | pragma solidity ^0.8.20; |
1 | flowchart TD |
内部调用与外部调用
内部调用使用跳转执行,保留当前调用上下文。外部调用通过 EVM 消息调用进入目标函数,重新进行 ABI 编码与解码,并可能触发回调。this.operation() 中的 msg.sender 是当前合约地址,而不是原始调用者。
不应为了调用自己的 external 函数而普遍使用 this。除了额外成本,它还会引入重入面与异常处理差异。
Memory 与 Storage
memory 参数接收独立副本,对它的修改不会写回状态。storage 引用直接指向链上存储,对其修改会改变状态变量。
1 | contract DataLocationDemo { |
执行 operation 后,返回值为 40 和 10。_changeMemory 只修改副本,因此 values[3] 保持 40。_changeStorage 修改实际状态,因此 values[4] 变为 10。
Pure 与 View
pure函数既不读取也不修改合约状态。view函数可以读取状态,但不能修改状态。- 普通非
payable函数可以读取和修改状态,但不能接收原生代币。 payable函数可以接收原生代币,也可以修改状态。
上例中的 operation 和 _changeStorage 会修改存储,因此不能声明为 pure 或 view。通过 Remix 发送交易时,返回值通常不作为普通调用结果直接展示,验证状态变化更适合读取状态变量、检查事件或编写测试。
LP 策略训练与回测
集中流动性 LP 策略需要根据价格、波动率、成交量、手续费和 Gas 成本动态选择区间。强化学习可以用于探索调仓策略,但必须先建立可验证的模拟环境和基准策略。
1 | flowchart LR |
状态空间
可包含当前价格、区间上下界、仓位内外状态、流动性分布、短期和长期波动率、成交量、手续费增长、Gas 价格、未实现损失与剩余投资期限。所有特征必须基于决策时刻可获得的数据,防止使用未来信息。
动作空间
- 保持当前区间。
- 撤出流动性并持有资产。
- 重新设置更窄或更宽的区间。
- 调整区间中心,使其偏向预期价格方向。
- 调整投入比例或保留现金缓冲。
奖励函数
奖励不能只使用手续费收入。较完整的净收益应扣除无常损失、价格滑点、Gas 成本和再平衡成本,并考虑最大回撤与尾部风险。
1 | 净收益 = 期末仓位价值 - 期初资产价值 + 已收手续费 - Gas 成本 - 滑点成本 |
撤仓判断示例
若 ETH 与 USDC 仓位当前相对持币基准落后百分之八,过去七天手续费收益为百分之四,预计继续持有三十天,并判断未来波动显著上升,则不能仅用历史手续费线性外推。应重新估计未来成交量、区间外概率、调仓成本和方向性风险。
更稳健的判断流程如下:
- 计算继续持有、立即退出和重新设定区间的情景收益。
- 对价格趋势、波动率与成交量设置多个情景,而非单点预测。
- 计算每个情景的净收益、最大回撤和退出成本。
- 当继续持有的风险调整收益持续低于替代方案时执行调仓。
回测要求
- 使用事件时间顺序切分训练集与测试集。
- 模拟真实手续费层级、价格冲击、Gas 与交易延迟。
- 与持币、固定宽度区间和定期调仓等简单基准比较。
- 防止幸存者偏差、前视偏差与数据重复。
- 记录策略在极端行情和流动性枯竭阶段的表现。
链上数据可由节点、索引服务或 Dune 等分析平台获取。关系型数据库适合保存标准化事件和仓位快照,XGBoost 与 LightGBM 可用于建立可解释的监督学习基线,再判断是否确有必要引入强化学习。





