跳转至

快速入门

本指南将引导您完成 Almanak SDK 的安装、创建您的第一个策略,以及在本地 Anvil 分叉上运行 -- 无需钱包或 API 密钥。

前提条件

  • Python 3.12+
  • uv(Python 包管理器):
curl -LsSf https://astral.sh/uv/install.sh | sh
  • Foundry(提供用于本地分叉测试的 Anvil):
curl -L https://foundry.paradigm.xyz | bash
foundryup

安装

pipx install almanak

或者使用 uv

uv tool install almanak

这会全局安装 almanak CLI。每个创建的策略也会在自己的 .venv/ 中将 almanak 作为本地依赖 -- 这种双重安装模式是标准做法(与 CrewAI、Dagster 等相同)。

使用 AI 编程代理? 一个命令即可让它学会 SDK:

almanak agent install

这会自动检测您的平台(Claude Code、Codex、Cursor、Copilot 以及 其他 6 个)并安装策略构建器技能。

1. 获取策略

选项 A:复制一个可运行的演示(推荐初学者使用)

almanak strat demo

这会显示一个交互式菜单,包含可运行的演示策略。选择一个,它会被复制到您当前的目录中,随时可以运行。您也可以跳过菜单:

almanak strat demo --name uniswap_rsi

选项 B:从模板创建

almanak strat new

按照交互式提示选择模板、链和名称。这将创建一个独立的 Python 项目,包含:

  • strategy.py - 您的策略实现,包含 decide() 方法
  • config.json - 链、协议和参数配置
  • pyproject.toml - 依赖和 [tool.almanak] 元数据
  • uv.lock - 锁定的依赖(由 uv sync 创建)
  • .venv/ - 每个策略的虚拟环境(由 uv sync 创建)
  • .env - 环境变量(稍后填入您的密钥)
  • .gitignore - Git 忽略规则
  • .python-version - Python 版本固定(3.12)
  • __init__.py - 包导出
  • tests/ - 测试脚手架
  • AGENTS.md - AI 代理指南

脚手架会自动运行 uv sync 来安装依赖。要添加额外的包:

uv add pandas-ta          # 更新 pyproject.toml + uv.lock + .venv/
uv run pytest tests/ -v   # 在策略的 venv 中运行测试

2. 在本地 Anvil 分叉上运行

测试策略的最快方式 -- 无需钱包密钥、无需真实资金、零风险:

cd my_strategy
almanak strat run --network anvil --once

此命令会自动:

  1. 启动 Anvil 分叉 -- 分叉 config.json 中指定的链(默认使用免费公共 RPC)
  2. 使用默认 Anvil 钱包 -- 无需 ALMANAK_PRIVATE_KEY
  3. 启动网关侧车在后台运行
  4. 为您的钱包充值 anvil_funding 中列出的代币(见下方)
  5. 运行一次迭代 您的策略的 decide() 方法

Anvil 上的钱包充值

config.json 中添加 anvil_funding 块,以便在分叉启动时自动为您的钱包充值:

{
    "anvil_funding": {
        "ETH": 10,
        "USDC": 10000,
        "WETH": 5
    }
}

原生代币(ETH、AVAX 等)通过 anvil_setBalance 充值。ERC-20 代币通过存储槽操作充值。每次分叉启动时都会自动执行。

更好的 RPC 性能(可选)

免费公共 RPC 可用但有速率限制。如需更快的分叉速度,请在 .env 中设置 Alchemy 密钥:

ALCHEMY_API_KEY=your_alchemy_key

这会自动为所有支持的链构建 RPC URL。任何提供商都可以 -- 请参阅环境变量了解完整的优先级顺序。

3. 在主网运行

Warning

主网执行使用真实资金。请从小额开始,并使用专用钱包。

要在实际链上运行,您需要在 .env 中设置钱包私钥:

# .env
ALMANAK_PRIVATE_KEY=0xYOUR_PRIVATE_KEY

# RPC 访问(选择一个)
ALCHEMY_API_KEY=your_alchemy_key
# 或者: RPC_URL=https://your-rpc-provider.com/v1/your-key

然后不使用 --network anvil 标志运行:

almanak strat run --once

Tip

先使用 --dry-run 测试,模拟运行但不提交交易:

almanak strat run --dry-run --once

请参阅环境变量了解完整的配置选项列表,包括协议特定的 API 密钥。

上线前注意事项

  • 首次实际执行前,务必先运行 --dry-run --once 以验证 intent 编译,而不提交交易。
  • 如果交换因 "Too little received" 而回滚,请将 amount_usd= 改为 amount=(代币单位)。 amount_usd= 依赖网关价格预言机进行 USD 到代币的转换,可能与 DEX 价格有偏差。
  • 从小额开始,监控前几次迭代。部署 ID 由您的钱包和链确定性地派生,因此重启会自动恢复同一次运行。

策略结构

策略实现 decide() 方法,该方法接收 MarketSnapshot 并返回 Intent

from decimal import Decimal
from almanak import IntentStrategy, Intent, MarketSnapshot

class MyStrategy(IntentStrategy):
    def decide(self, market: MarketSnapshot) -> Intent | None:
        price = market.price("ETH")
        balance = market.balance("USDC")

        if price < Decimal("2000") and balance.balance_usd > Decimal("500"):
            return Intent.swap(
                from_token="USDC",
                to_token="ETH",
                amount_usd=Decimal("500"),
            )
        return Intent.hold(reason="没有机会")

可用意图

意图 描述
SwapIntent DEX 上的代币交换
HoldIntent 无操作,等待下一轮
LPOpenIntent 开设流动性头寸
LPCloseIntent 关闭流动性头寸
BorrowIntent 从借贷协议借款
RepayIntent 偿还借款资产
DeleverageIntent 风险管理触发的紧急偿还。工厂方法:Intent.deleverage()
SupplyIntent 向借贷协议提供资产
WithdrawIntent 从借贷协议提取资产
StakeIntent 质押代币
UnstakeIntent 取消质押代币
PerpOpenIntent 开设永续合约头寸
PerpCloseIntent 关闭永续合约头寸
FlashLoanIntent 闪电贷操作 (实验性 — 测试中;未列入 almanak info matrix
CollectFeesIntent 收取 LP 费用
PredictionBuyIntent 购买预测市场份额 (实验性 — 测试中;未列入 almanak info matrix
PredictionSellIntent 出售预测市场份额 (实验性 — 测试中;未列入 almanak info matrix
PredictionRedeemIntent 赎回预测市场收益 (实验性 — 测试中;未列入 almanak info matrix
VaultDepositIntent 存入金库
VaultRedeemIntent 从金库赎回
WrapNativeIntent 包装原生代币(例如 ETH 转 WETH)。工厂方法: Intent.wrap()
UnwrapNativeIntent 解包原生代币(例如 WETH 转 ETH)。工厂方法: Intent.unwrap()
Intent.bridge() 跨链桥接代币(工厂方法,返回复合意图)
Intent.ensure_balance() 确保目标链上的最低代币余额(工厂方法,解析为桥接或持有)
Intent.sequence() 原子多步复合意图(IntentSequence),按顺序执行子意图并共享回滚语义

状态持久化(有状态策略必需)

框架会在每次迭代后自动持久化运行器级别的元数据(迭代计数、错误计数器)。但是,策略特定的状态 -- 头寸 ID、交易次数、阶段跟踪、冷却计时器 -- 只有在您实现两个钩子时才会保存:

from typing import Any
from decimal import Decimal

class MyStrategy(IntentStrategy):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._position_id: int | None = None
        self._trades_today: int = 0

    def get_persistent_state(self) -> dict[str, Any]:
        """返回要保存的状态。每次迭代后调用。"""
        return {
            "position_id": self._position_id,
            "trades_today": self._trades_today,
        }

    def load_persistent_state(self, state: dict[str, Any]) -> None:
        """在启动时恢复状态。恢复运行时调用。"""
        self._position_id = state.get("position_id")
        self._trades_today = state.get("trades_today", 0)

如果没有这些钩子,您的策略在重启时将丢失所有内部状态。这对于 LP 策略尤其危险,因为丢失 position_id 意味着策略无法关闭自己的头寸。

没有持久化会丢失什么

如果您将状态存储在实例变量中(例如 self._position_id)但没有实现 get_persistent_state()load_persistent_state(),该状态会在进程停止时丢失。重启后,您的策略将从零开始,不记得任何已开启的头寸、已完成的交易或内部阶段。

提示

  • load_persistent_state() 中使用带默认值的 .get() 进行防御性编程,这样旧的状态字典不会因缺少键而崩溃。
  • Decimal 值存储为字符串(str(amount))并在读取时解析(Decimal(state["amount"])),以确保 JSON 往返安全。
  • on_intent_executed() 回调是在交易后更新状态的最佳位置(例如存储新的头寸 ID),然后 get_persistent_state() 会在保存时获取它。

策略拆卸(必需)

每个策略都必须实现拆卸功能,以便运营者可以安全地关闭头寸。没有拆卸功能,关闭请求会被静默忽略,头寸将保持开启状态。almanak strat new 模板包含存根 -- 在构建策略时填写它们。

class MyStrategy(IntentStrategy):
    def supports_teardown(self) -> bool:
        return True

    def get_open_positions(self) -> "TeardownPositionSummary":
        """查询链上状态并返回已开启的头寸。"""
        from almanak.framework.teardown import PositionInfo, PositionType, TeardownPositionSummary
        # ... 返回包含您头寸的 TeardownPositionSummary

    def generate_teardown_intents(self, mode: "TeardownMode", market=None) -> list[Intent]:
        """返回有序的 intent 列表以平仓所有头寸。"""
        from almanak.framework.teardown import TeardownMode
        max_slippage = Decimal("0.03") if mode == TeardownMode.HARD else Decimal("0.005")
        return [Intent.swap(from_token="WETH", to_token="USDC", amount="all", max_slippage=max_slippage)]

如果您的策略持有多种头寸类型,请按以下顺序关闭:永续合约 -> 借款 -> 供应 -> LP -> 代币。参阅拆卸 CLI了解运营者如何触发拆卸。

生成权限清单(Safe 钱包)

通过带有 Zodiac Roles 限制的 Safe 钱包部署策略时,代理需要一组明确的合约权限。SDK 可以通过检查策略的 intent 编译到哪些合约和函数选择器来自动生成此清单:

# 从策略目录运行
almanak strat permissions

# 指定目录
almanak strat permissions -d almanak/demo_strategies/uniswap_rsi

# 覆盖链
almanak strat permissions --chain base

# 写入文件
almanak strat permissions -o permissions.json

该命令从 @almanak_strategy 装饰器读取 supported_protocolsintent_types,通过真实编译器编译合成 intent,并提取所需的最小合约地址和函数选择器集合。输出为 JSON 清单,可应用于 Zodiac Roles 模块。如果策略支持多条链,输出为 JSON 数组,每条链一个清单;使用 --chain 可生成单条链的清单。

仅用于 Safe/Zodiac 部署

权限清单仅在通过带有 Zodiac Roles 的 Safe 钱包运行时需要。本地 Anvil 测试或直接密钥执行不需要权限。

回测 CLI

almanak strat run 从当前目录自动发现策略不同, 回测命令需要明确的策略名称:almanak strat backtest pnl -s my_strategy。 使用 --list-strategies 查看可用的策略。

下一步

想让 LLM 来做决策?

SDK 还支持代理策略,其中 LLM 使用 Almanak 的 39 个内置工具自主决定 要做什么。您无需在 Python 中编写 decide() 逻辑,而是编写系统提示词, 让 LLM 基于市场数据进行推理。

这种方式需要您自己的 LLM API 密钥(OpenAI、Anthropic 或任何 兼容 OpenAI 的提供商)。

确定性策略(本指南) 代理策略
您编写的 Python decide() 方法 系统提示词 + 策略
决策者 您的代码 LLM(GPT-4、Claude 等)
需要 仅 SDK SDK + LLM API 密钥
最适合 已知规则、量化信号 复杂推理、多步计划

两种路径共享相同的网关、连接器和执行管道。

开始使用: 代理交易指南