前言本文主要梳理期权相关的理论知识,涵盖期权的定义、功能、运行原理、行业应用及优劣势,同时解析期权与其他金融衍生品的区别;并基于HardhatV3开发框架,结合OpenZeppelinV5、Solidity0.8.24+及Chainlink工具,完整实现了极简期权智能合约从开
本文主要梳理期权相关的理论知识,涵盖期权的定义、功能、运行原理、行业应用及优劣势,同时解析期权与其他金融衍生品的区别;并基于 Hardhat V3 开发框架,结合 OpenZeppelin V5、Solidity 0.8.24 + 及 Chainlink 工具,完整实现了极简期权智能合约从开发、测试到部署落地的全流程。
期权相关知识梳理
一、期权是什么
期权是一种金融衍生品,买方支付少量权利金,获得在约定时间内以约定价格买卖标的资产(股票、指数、期货等)的权利;卖方收权利金后,需承担买方行权的履约义务。核心是“权利与义务分离”,买方只享权利,卖方仅担义务。
关键分类:按权利方向分认购(看涨)、认沽(看跌)期权;按行权时间分欧式(仅到期可行权)、美式(到期前任意时间可行权)。
定价核心:权利金=内在价值(行权即时收益,分实值、平值、虚值)+时间价值(到期前波动潜力,越临近到期衰减越快);
交易流程:场内标准化合约交易,买方付权利金,卖方缴保证金;交易后可平仓了结,或持有至到期行权(实值行权,虚值放弃);
结算方式:分实物交割(如股票)和现金交割(如指数),场内以现金交割为主。
买方风险可控(最大亏权利金)、收益无限;杠杆灵活、资金成本低;策略丰富,适配牛熊震荡全行情,兼顾攻防。
有时间损耗,到期虚值期权权利金归零;定价复杂,对专业度要求高;卖方无对冲时风险无限;部分合约流动性不足。
| 工具 | 风险收益特征 | 权利义务 | 资金成本 | 策略丰富度 |
|---|---|---|---|---|
| 期权(买方) | 亏损有限,收益无限 | 只享权利,不担义务 | 低(仅付权利金) | 极高(多策略适配所有行情) |
| 期权(卖方) | 收益有限,风险无限 | 只担义务,享权利金 | 中(缴纳保证金) | 较高(震荡市收权利金) |
| 期货 | 亏损无限,收益无限 | 权利义务对等 | 中(缴纳保证金) | 一般(多空为主,组合少) |
| 股票 | 亏损有限(本金),收益无限 | 权利义务对等 | 高(全额支付本金) | 低(低买高卖为主) |
期权的核心是 “权利与义务分离” 的选择权,永续合约的核心是 “无到期日” 的杠杆式标的资产交易。| 对比维度 | 永续合约 | 期权 |
|---|---|---|
| 核心定义 | 无到期日的杠杆式衍生品,对标标的资产价格,本质是双方对标的价格走势的赌约,需缴纳保证金 | 买方支付权利金获得 “行权选择权”,卖方收取权利金承担履约义务,本质是权利的买卖 |
| 权利义务 | 买卖双方权利义务完全对等,均需履约,无选择权 | 买卖双方权利义务完全分离:买方只享权利、不担义务;卖方只担义务、享权利金收益 |
| 到期规则 | 无到期日,可长期持有,只需维持保证金充足,避免爆仓 | 有明确到期日,到期未行权则权利作废,时间价值随到期日临近衰减 |
| 成本 / 保证金 | 买卖双方均需缴纳保证金(杠杆交易,保证金比例低),无额外费用,保证金随标的价格波动补仓 / 平仓 | 买方:仅支付权利金(最大亏损,无保证金要求);卖方:缴纳保证金(担保履约),权利金是卖方的收益 |
| 风险收益特征 | 买卖双方均风险无限、收益无限:做多涨则赚、跌则亏;做空跌则赚、涨则亏,极端行情易爆仓 | 买方:亏损有限(权利金)、收益无限;卖方:收益有限(权利金)、风险无限(无对冲时) |
| 价格影响因素 | 仅对标标的资产的市场价格,受标的供需、行情波动影响 | 受标的价格、行权价、到期日、波动率、无风险利率等多重因素影响,定价更复杂 |
| 核心功能 | 主要用于杠杆投机、短期趋势交易,少量用于对冲(需主动平仓) | 可风险管理(对冲)、杠杆投机、收益增强、套利,策略丰富,适配所有行情 |
hardhatV3本地部署MockV3Aggregator3便于测试,正式环境使用Chainlink对应的合约地址
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;contract MockV3Aggregator3 { uint8 public decimals; int256 public latestAnswer; uint256 public updatedAt;
constructor(uint8 _decimals, int256 _initialAnswer) {
decimals = _decimals;
latestAnswer = _initialAnswer;
updatedAt = block.timestamp;
}
// 关键:在测试脚本中调用此函数模拟行情变动
function updateAnswer(int256 _newAnswer) external {
latestAnswer = _newAnswer;
updatedAt = block.timestamp;
}
function latestRoundData() external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt_,
uint80 answeredInRound
) {
return (1, latestAnswer, updatedAt, updatedAt, 1);
}
}
* **价格预言机**
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24;
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
contract PriceOracle { function getAssetPrice(address feedAddress) public view returns (uint256) { AggregatorV3Interface feed = AggregatorV3Interface(feedAddress); (, int256 price, , uint256 updatedAt, ) = feed.latestRoundData();
require(price > 0, "Oracle: Invalid price");
// 本地测试时,如果 block.timestamp 和 updatedAt 都是 0 会报错,这里确保兼容
require(updatedAt != 0, "Oracle: Invalid update time");
uint8 decimals = feed.decimals();
// 统一转为 18 位小数,方便 Engine 计算
return uint256(price) * (10 ** (18 - decimals));
}
}
* **资产金库**
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract FuturesVault is Ownable { using SafeERC20 for IERC20;
IERC20 public immutable asset; // 结算货币 (如 USDT)
mapping(address => bool) public isEngine;
mapping(address => uint256) public userMargin; // 用户保证金余额
constructor(address _asset) Ownable(msg.sender) {
asset = IERC20(_asset);
}
modifier onlyEngine() {
require(isEngine[msg.sender], "Vault: Not an authorized engine");
_;
}
function setEngine(address _engine, bool _status) external onlyOwner {
isEngine[_engine] = _status;
}
// 充值保证金
function depositMargin(uint256 amount) external {
asset.safeTransferFrom(msg.sender, address(this), amount);
userMargin[msg.sender] += amount;
}
// 引擎结算盈亏:从金库划转或扣除
function settlePnL(address trader, int256 pnl) external onlyEngine {
if (pnl > 0) {
userMargin[trader] += uint256(pnl);
} else {
userMargin[trader] -= uint256(-pnl);
}
}
// 提现
function withdraw(uint256 amount) external {
require(userMargin[msg.sender] >= amount, "Vault: Insufficient balance");
userMargin[msg.sender] -= amount;
asset.safeTransfer(msg.sender, amount);
}
}
* **交易引擎**
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24;
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import {PriceOracle} from "./PriceOracle.sol"; import {FuturesVault} from "./FuturesVault.sol";
contract FuturesEngine is ReentrancyGuard { PriceOracle public immutable oracle; FuturesVault public immutable vault; address public immutable priceFeed; // Chainlink 喂价地址
struct Position {
uint256 size; // 头寸大小
uint256 entryPrice; // 开仓价格
bool isLong; // 方向
bool isActive;
}
mapping(address => Position) public positions;
constructor(address _oracle, address _vault, address _priceFeed) {
oracle = PriceOracle(_oracle);
vault = FuturesVault(_vault);
priceFeed = _priceFeed;
}
// 开仓
function openPosition(uint256 size, bool isLong) external nonReentrant {
require(!positions[msg.sender].isActive, "Engine: Position already exists");
uint256 currentPrice = oracle.getAssetPrice(priceFeed);
// 极简风控:保证金必须至少是头寸大小的 10% (10倍杠杆限制)
require(vault.userMargin(msg.sender) >= size / 10, "Engine: Insufficient margin");
positions[msg.sender] = Position({
size: size,
entryPrice: currentPrice,
isLong: isLong,
isActive: true
});
}
// 平仓并结算盈亏
function closePosition() external nonReentrant {
Position storage pos = positions[msg.sender];
require(pos.isActive, "Engine: No active position");
uint256 currentPrice = oracle.getAssetPrice(priceFeed);
int256 pnl;
// 计算 PnL = size * (price_diff / entry_price)
if (pos.isLong) {
pnl = int256(pos.size * (currentPrice - pos.entryPrice) / pos.entryPrice);
} else {
pnl = int256(pos.size * (pos.entryPrice - currentPrice) / pos.entryPrice);
}
pos.isActive = false;
vault.settlePnL(msg.sender, pnl); // 通知金库更新余额
}
}
### 测试脚本
**用例说明**:
* **交易流程**:(正常的交易结算)
* **安全检测**:(保证金不足以支撑杠杆交易回滚)
import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { parseUnits } from "viem"; import { network } from "hardhat";
const TOKEN_DECIMALS = 18; const ORACLE_DECIMALS = 8; // 模拟 Chainlink 常见的 8 位小数
describe("Futures System - Local Mock Test", () => { async function deployFixture() { const { viem } = await network.connect(); const [owner, trader] = await viem.getWalletClients(); const publicClient = await viem.getPublicClient();
// 1. 部署 Mock 资产和 Oracle
const mockUSDT = await viem.deployContract("BoykaYuriToken", [owner.account.address, owner.account.address]);
const oracle = await viem.deployContract("PriceOracle");
const vault = await viem.deployContract("FuturesVault", [mockUSDT.address]);
// 2. 【重点】部署本地价格模拟器:初始价格 3000 USD
const initialPrice = parseUnits("3000", ORACLE_DECIMALS);
const mockAggregator = await viem.deployContract("MockV3Aggregator3", [ORACLE_DECIMALS, initialPrice]);
// 3. 部署 Engine,绑定到 Mock 预言机地址
const engine = await viem.deployContract("FuturesEngine", [
oracle.address,
vault.address,
mockAggregator.address, // 这里传入的是 mock 地址,而非在线地址
]);
await vault.write.setEngine([engine.address, true]);
return { trader, mockUSDT, vault, engine, mockAggregator, publicClient };
}
it("手动价格操纵后应正确计算利润", async () => { const { trader, mockUSDT, vault, engine, mockAggregator } = await deployFixture();
// 步骤 A: 准备 1000 USDT 保证金
const marginAmount = parseUnits("1000", TOKEN_DECIMALS);
await mockUSDT.write.mint([trader.account.address, marginAmount]);
await mockUSDT.write.approve([vault.address, marginAmount], { account: trader.account });
await vault.write.depositMargin([marginAmount], { account: trader.account });
// 步骤 B: 价格 3000 时开 5000 USDT 的多单
const positionSize = parseUnits("5000", TOKEN_DECIMALS);
await engine.write.openPosition([positionSize, true], { account: trader.account });
// 步骤 C: 【手动操纵价格】将价格上调至 3300 (+10%)
const newPrice = parseUnits("3300", ORACLE_DECIMALS);
await mockAggregator.write.updateAnswer([newPrice]);
// 步骤 D: 平仓并验证盈亏
await engine.write.closePosition([], { account: trader.account });
const finalMargin = await vault.read.userMargin([trader.account.address]);
// 理论盈利:5000 * (3300-3000)/3000 = 500 USDT
// 最终余额应接近 1500 USDT
const expectedProfit = parseUnits("500", TOKEN_DECIMALS);
assert.ok(finalMargin >= marginAmount + expectedProfit, "Trader should have earned 500 USDT");
}); it("应因高杠杆保证金不足而恢复", async () => { const { trader, mockUSDT, vault, engine } = await deployFixture();
const smallMargin = parseUnits("10", TOKEN_DECIMALS);
// 1. 铸造代币
await mockUSDT.write.mint([trader.account.address, smallMargin]);
// 2. 【缺失的修复步骤】授权 Vault 扣款
await mockUSDT.write.approve([vault.address, smallMargin], { account: trader.account });
// 3. 存入保证金
await vault.write.depositMargin([smallMargin], { account: trader.account });
const hugeSize = parseUnits("2000", TOKEN_DECIMALS); // 200x leverage
// 4. 验证开仓失败
await assert.rejects(
engine.write.openPosition([hugeSize, true], { account: trader.account }),
(err: any) => {
// 打印错误详情有助于调试
// console.log(err.message);
return err.message.includes("Engine: Insufficient margin");
}
);
});
});
### 部署脚本
// scripts/deploy.js import { network, artifacts } from "hardhat"; import { parseUnits } from "viem"; async function main() { // 连接网络 const { viem } = await network.connect({ network: network.name });//指定网络进行链接
// 获取客户端 const [deployer] = await viem.getWalletClients(); const publicClient = await viem.getPublicClient();
const deployerAddress = deployer.account.address; console.log("部署者的地址:", deployerAddress); // 加载合约 const BoykaYuriTokenArtifact = await artifacts.readArtifact("BoykaYuriToken"); const PriceOracleArtifact = await artifacts.readArtifact("PriceOracle"); const FuturesVaultArtifact = await artifacts.readArtifact("FuturesVault"); const MockV3Aggregator3Artifact = await artifacts.readArtifact("MockV3Aggregator3"); const FuturesEngineArtifact = await artifacts.readArtifact("FuturesEngine");
// 部署(构造函数参数:recipient, initialOwner) const BoykaYuriTokenHash = await deployer.deployContract({ abi: BoykaYuriTokenArtifact.abi,//获取abi bytecode: BoykaYuriTokenArtifact.bytecode,//硬编码 args: [deployerAddress,deployerAddress],//部署者地址,初始所有者地址 }); const BoykaYuriTokenReceipt = await publicClient.waitForTransactionReceipt({ hash: BoykaYuriTokenHash }); console.log("代币合约地址:", BoykaYuriTokenReceipt.contractAddress); // const PriceOracleHash = await deployer.deployContract({ abi: PriceOracleArtifact.abi,//获取abi bytecode: PriceOracleArtifact.bytecode,//硬编码 args: [], }); // 等待确认并打印地址 const PriceOracleReceipt = await publicClient.waitForTransactionReceipt({ hash: PriceOracleHash }); console.log("预言机合约地址:", PriceOracleReceipt.contractAddress); // 部署(构造函数参数:recipient, initialOwner) const FuturesVaultHash = await deployer.deployContract({ abi: FuturesVaultArtifact.abi,//获取abi bytecode: FuturesVaultArtifact.bytecode,//硬编码 args: [BoykaYuriTokenReceipt.contractAddress],// }); // 等待确认并打印地址 const FuturesVaultReceipt = await publicClient.waitForTransactionReceipt({ hash: FuturesVaultHash }); console.log("期货合约地址:", FuturesVaultReceipt.contractAddress); const ORACLE_DECIMALS = 8; const initialPrice = parseUnits("3000", ORACLE_DECIMALS); const MockV3Aggregator3Hash = await deployer.deployContract({ abi: MockV3Aggregator3Artifact.abi,//获取abi bytecode: MockV3Aggregator3Artifact.bytecode,//硬编码 args: [ORACLE_DECIMALS, initialPrice],// }); // 等待确认并打印地址 const MockV3Aggregator3Receipt = await publicClient.waitForTransactionReceipt({ hash: MockV3Aggregator3Hash }); console.log("预言机合约地址:", MockV3Aggregator3Receipt.contractAddress); const FuturesEngineHash = await deployer.deployContract({ abi: FuturesEngineArtifact.abi,//获取abi bytecode: FuturesEngineArtifact.bytecode,//硬编码 args: [PriceOracleReceipt.contractAddress,FuturesVaultReceipt.contractAddress,MockV3Aggregator3Receipt.contractAddress],// }); // 等待确认并打印地址 const FuturesEngineReceipt = await publicClient.waitForTransactionReceipt({ hash: FuturesEngineHash }); console.log("期货引擎合约地址:", FuturesEngineReceipt.contractAddress); }
main().catch(console.error);
# 结语
至此,期权相关的知识体系梳理与代码落地实操已全部完成,同时也对各类金融衍生品的核心特性与差异完成了系统的对比梳理。从理论框架到实操落地,从单一产品解析到同类衍生品横向对标,整套内容已形成完整闭环,希望能为大家理解期权及金融衍生品、开展相关实操应用提供切实的参考与助力。 如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!