想象一下,有一种策略,能够在数字货币市场的剧烈波动中稳如泰山,无论牛市还是熊市,都能为你带来持续的正收益。听起来像是天方夜谭?其实不然。币本位一倍做空资费套利策略,正是这样一个“躺赚”神器。
通过巧妙利用币本位合约的独特性质与资金费率机制,这一策略不仅能够在牛市中获取稳定收益,还能在熊市中有效规避风险,实现跨越市场周期的稳健回报。币本位合约的“保现金”特性,使得即使市场价格大幅波动,策略的总价值也能保持稳定。而资金费率作为永续合约的核心机制,为策略提供了额外的收益来源。本文将深入解析币本位做空策略的核心逻辑、实现过程及其优缺点,帮助投资者理解如何在数字货币市场中,通过这一策略实现“躺赚”收益。无论你是量化交易新手,还是经验丰富的投资者,这一策略都值得你深入了解与尝试。
币本位做空
币本位的特点
币本位合约的单位以张为计量,每张的价值固定(例如 BTC 的 1 张合约价值为 100 USD,ETH 为 10 USD)。这种特点使得在 1 倍杠杆的情况下,即使市场价格大幅波动,理论上不会爆仓。
盈亏结算分析
假设当前价格为 100 USD,开 10 张币本位做空合约,其价值等于 100 USD,换算为币数量为 1 个单位:
-
价格下跌:
- 价格跌至 50 USD,收益率为:
\[ \text{收益率} = \frac{100 - 50}{50} = 100\% \]
持币数量变为 2 个,总价值仍为:
\[ 2 \times 50 = 100 \, \text{USD} \]
- 价格跌至 50 USD,收益率为:
-
价格上涨:
- 价格涨至 200 USD,收益率为:
\[ \text{收益率} = \frac{100 - 200}{200} = -50\% \]
持币数量变为 0.5 个,总价值仍为:
\[ 0.5 \times 200 = 100 \, \text{USD} \]
- 价格涨至 200 USD,收益率为:
因此在一定程度上来说,币本位做空的总价值保持稳定,是一种保现金的操作。那么该策略的收益来源来自于哪里呢,我们介绍下一个概念:资金费率。
资金费率
在币本位做空策略中,资金费率是策略收益的核心驱动力之一,其特性和变化直接影响策略的稳定性和盈利能力。通过合理利用资金费率的特点,策略可以在不同市场环境下保持较好的表现,但也需要注意其潜在的局限性。
资金费率的定义与特点
资金费率是永续合约市场中的一种调节机制,旨在平衡多空双方的持仓成本,避免永续合约价格长期偏离现货价格。其实有学过CFA的朋友,会对永续合约的原名 swap 记忆犹新。永续合约的资金费率机制,其设计灵感很大程度上来源于传统金融中的利率互换(Interest Rate Swap)。在利率互换中,双方根据约定的利率(如固定利率与浮动利率)定期交换利息支付,以对冲利率波动的风险。类似地,永续合约的资金费率机制也是通过定期支付或收取费用,来平衡多空双方的持仓成本,确保合约价格与现货价格之间的差距不会过大。
资金费率的引入,本质上是为了解决永续合约与现货价格之间的基差问题。当永续合约价格高于现货价格时,资金费率为正,多头支付费用给空头;当永续合约价格低于现货价格时,资金费率为负,空头支付费用给多头。这种机制不仅借鉴了利率互换的核心理念,还结合了数字货币市场的特点,形成了一种独特的市场调节工具。在数字货币领域,其主要特点包括:
- 市场供需决定:资金费率由市场中多头与空头的供需关系决定,是多空力量博弈的结果。
- 周期性支付:资金费率按一定周期(如8小时)支付,费用在多头和空头之间相互转移。
- 情绪反映:正资金费率通常表明市场情绪偏多,永续合约价格高于现货价格;负资金费率则表明市场情绪偏空,永续合约价格低于现货价格。
正资金费率(Funding Rate > 0)
- 表现:在正资金费率环境下,多头需支付费用给空头。
- 收益逻辑:随着资金费率的稳定支付,策略通过持有空头头寸持续收取资金费用,即使市场价格上涨,也不会对收益产生过大负面影响。例如,当资金费率为0.02%/8小时时,持有$10,000价值的合约可获得每日收益:
\[ 每日收益 = 10,000 \times 0.02\% \times 3 = 6 \, \text{USDT} \]
这种收益来源相对稳定且与价格波动关系较小。
负资金费率(Funding Rate < 0)
- 表现:当资金费率为负时,空头需支付费用给多头,策略收益可能受到压缩,甚至出现亏损。
- 风险点:在负资金费率持续时间较长或波动较大的情况下,如长期熊市,策略可能因支付资金费用而面临较高成本,导致整体收益无法覆盖运营成本。
策略盈利来源
正如子楠大神所言,策略在构建初始阶段需要了解策略的收益来源和风险来源。在上面的基础上,我们了解了币本位做空的总价值是保持稳定,那么收益的来源是资金费率套利。有些同学可能好奇,资金费率会持续带来稳定的正向收益吗?我们在【数据探索】模块进行一下数据分析工作:
sql
SELECT
Exchange,
Symbol,
toDateTime(Time / 1000) AS Time, -- 将毫秒时间戳转换为时间戳
Rate,
SUM(Rate) OVER (PARTITION BY Exchange, Symbol ORDER BY Time) AS CumulativeRate -- 计算累加的 Rate
FROM
klines.funding
WHERE
Exchange = '{{exchange}}'
AND Symbol = '{{symbol}}'
ORDER BY
Time;
(chart/ffb27bb9-e647-42a0-84fb-6016cdf39f89)
动态参数使用币安交易所,合约选择比特币币本位(btc_usd)合约,进行累计资金费率的展示。可以看到,在2020至今,资金费率收益呈现稳步上涨的水平,累计5年收益高达50%。虽然和动辄成百上千的收益不能媲美,但是胜在比较稳定,因此我们可以理清该策略的盈利来源。
在币本位做空策略中,资金费率是盈利的关键来源。由于币本位合约的单位是固定的,即使市场价格波动,做空者的合约价值变化通常是可控的,因此资金费率成为策略的主要盈利来源。以下是资金费率对策略的具体影响:
-
牛市阶段(资金费率为正)
- 市场现象:在牛市中,由于市场情绪高涨,投资者普遍倾向于做多,导致多头持仓增加,从而推动资金费率变为正值。
- 收益逻辑:在这种情况下,做空者将从多头支付的资金费率中获得收益,成为策略的主要盈利来源。由于资金费率为正,空头头寸可以持续获利,且通过利用获得的资金费率可以继续开仓空单,获取更多的资金费率收益。
- 具体影响:如果资金费率为正且稳定,空头将定期收取资金费率,且不受价格波动太大影响。即使市场价格上涨,空头在合约上可能会面临较大的明面损失,但从整体来看,资金的净值保持相对稳定。这是因为策略的盈利来源主要依赖于资金费率的收取,而非价格波动。尽管价格波动可能对合约的明面亏损产生影响,但由于空头头寸的合约价值变化可控,资金的主要盈利还是来自于资金费率的定期收取,而非市场价格的波动。这使得策略能够在一定程度上抵消价格波动的风险,维持资金的稳定增值。
-
熊市阶段(资金费率为负)
- 市场现象:在熊市中,市场价格下跌较快,做空头寸通常激增,导致资金费率变为负值,即空头需要向多头支付费用。然而,由于近年来数字货币市场的蓬勃发展,熊市阶段相对较少。
- 收益逻辑:尽管资金费率为负,且空头需要支付费用,但由于做空合约的单位固定,空头头寸的合约价值变化较小,因此策略的保值特性依然有效。价格的剧烈波动不会导致大幅亏损,同时资金费率的负担相对可控,策略仍能在一定程度上保持稳定。
通过这两种市场环境的分析,可以看出,币本位做空策略的盈利和风险主要受资金费率的影响。牛市阶段资金费率为正时,做空者能够从中获益;而熊市阶段虽然资金费率为负,但由于合约价值变化可控,策略仍具备较强的保值能力。
策略逻辑架构
一个稳健的策略架构是策略成功实施的关键,它提供了清晰的执行框架,确保策略能够在各种市场条件下稳定运作,并有效应对风险和波动。这里我们参考小草大神的U本位多币种合约策略架构,针对币本位,做了一定程度的修改和完善。
python
'''backtest
start: 2024-11-20 00:00:00
end: 2024-11-20 01:00:00
period: 1d
basePeriod: 1m
exchanges: [{"eid":"Futures_OKX","currency":"BTC_USD"}]
'''
import time
import json
# 全局变量,储存数据
SYMBOLS = 'BTC' # SYMBOLS代表要交易的币种,格式如"BTC,ETH,LTC"
QUOTO = 'USD' # QUOTO为基础货币, 币本位为USD
INTERVAL = 5 # INTERVAL代表循环的间隔
ICEMONEY = 2000 # 冰山下单金额
ROLLINGNUM = 1 # 滚动盈利加仓数量
Info = {
'trade_symbols': SYMBOLS.split(','), # 交易币种
'base_coin': QUOTO, # 基础货币
'ticker': {}, # 行情数据
'order': {}, # 订单信息
'account': {}, # 账户信息
'precision': {}, # 精度信息
'position': {}, # 仓位信息
'time': {}, # 时间相关数据
'count': {}, # 计数器
'interval': INTERVAL # 循环的间隔时间
}
# 初始化策略
def InitInfo():
# 初始化时间数据,控制更新的时间
Info['time'] = {
'update_ticker_time': 0, # 更新行情的时间
'update_pos_time': 0, # 更新仓位的时间
'update_profit_time': 0, # 更新利润的时间
'update_account_time': 0, # 更新账户信息的时间
'update_status_time': 0, # 更新状态的时间
'last_loop_time': 0, # 上一次主循环的时间
'loop_delay': 0, # 循环延迟
'start_time': time.time() # 起始时间
}
# 初始化每个交易币种的数据
for symbol in Info['trade_symbols']:
Info['account'][symbol] = {
'init_balance': 0, # 初始余额
'margin_balance': 0, # 保证金余额
'margin_used': 0, # 已用保证金
'margin_free': 0, # 可用保证金
'profit': 0, # 总收益
'profit_rate': 0, # 收益率
'unrealised_profit': 0, # 未实现收益
} # 初始化账户信息,初始余额为0
Info['ticker'][symbol] = {'last': 0, 'ask': 0, 'bid': 0} # 行情
Info['order'][symbol] = { # 订单信息
'buy': {'id': 0, 'price': 0, 'amount': 0},
'sell': {'id': 0, 'price': 0, 'amount': 0}
}
Info['position'][symbol] = { # 仓位信息
'amount': 0, 'hold_price': 0, 'unrealised_profit': 0, 'open_time': 0, 'value': 0
}
Info['precision'][symbol] = {} # 精度信息初始化为空
Info['position'][symbol] = { # 仓位信息
'amount': 0, 'hold_price': 0, 'unrealised_profit': 0, 'open_time': 0, 'value': 0
}
# 获取精度信息
def GetPrecision():
# 获取交易所的市场信息
# 回测系统需要获取行情信息后, 才能获取市场信息,实盘系统可忽略
for symbol in Info['trade_symbols']:
curcontract = symbol + '_' + QUOTO + '.swap'
exchange.GetTicker(curcontract)
exchange_info = exchange.GetMarkets()
# 遍历市场中的所有交易对
for pair, data in exchange_info.items():
symbol = pair.split('_')[0] # 永续合约交易对的格式为 BTC_USDT.swap
# 检查该交易对是否为我们要交易的币种,基础货币是否匹配,且是永续合约
if symbol in Info['trade_symbols'] and pair.split('.')[0].endswith(Info['base_coin']) and pair.endswith('swap'):
# 获取该交易对的精度信息
Info['precision'][symbol] = {
'tick_size': data['TickSize'], # 价格精度
'amount_size': data['AmountSize'], # 数量精度
'price_precision': data['PricePrecision'], # 价格小数位精度
'amount_precision': data['AmountPrecision'], # 数量小数位精度
'min_qty': data['MinQty'], # 最小下单数量
'max_qty': data['MaxQty'], # 最大下单数量
'min_notional': data['MinNotional'], # 最小交易额
'ctVal': data['CtVal'] # 合约价值,如1张代表100USD
}
Log(f"初始化币种信息: {symbol}, "
f"价格精度: {Info['precision'][symbol]['tick_size']}, "
f"数量精度: {Info['precision'][symbol]['amount_size']}, "
f"价格小数位精度: {Info['precision'][symbol]['price_precision']}, "
f"数量小数位精度: {Info['precision'][symbol]['amount_precision']}, "
f"最小下单数量: {Info['precision'][symbol]['min_qty']}, "
f"最大下单数量: {Info['precision'][symbol]['max_qty']}, "
f"最小交易额: {Info['precision'][symbol]['min_notional']}, "
f"合约价值(张): {Info['precision'][symbol]['ctVal']}")
# 更新行情信息
def UpdateTicker():
# 记录当前更新时间戳
Info['time']['update_ticker_time'] = time.time() * 1000 # 使用time.time()获取当前时间的时间戳
# 遍历获取到的行情数据
for symbol in Info['trade_symbols']:
curcontract = symbol + '_' + QUOTO + '.swap'
data = exchange.GetTicker(curcontract)
if not data:
Log("获取行情失败", GetLastError())
return
# 更新行情的卖出价、买入价和最后成交价
Info['ticker'][symbol]['ask'] = float(data['Sell']) # 卖出价
Info['ticker'][symbol]['bid'] = float(data['Buy']) # 买入价
Info['ticker'][symbol]['last'] = float(data['Last']) # 最后成交价
# 更新账户信息
def UpdateAccount():
# 遍历所有交易币种,更新账户信息
for symbol in Info['trade_symbols']:
curcontract = symbol + '_' + QUOTO # 拼接币种和报价货币,形成合约标识
exchange.SetCurrency(curcontract) # 设置当前合约
# 获取账户信息
account = exchange.GetAccount()
# 如果账户信息获取失败,记录日志并结束函数
if account is None:
Log(curcontract, ": 更新账户失败")
return
# 计算账户的关键信息
# 'Stocks': 可用余额, 'FrozenStocks': 冻结余额, 'Equity': 总权益, 'UPnL': 未实现盈亏, 区别U本位(Balance)
Info['account'][symbol]['margin_used'] = account['Equity'] - account['Stocks'] # 已用保证金
Info['account'][symbol]['margin_balance'] = account['Equity'] # 当前账户总权益
Info['account'][symbol]['margin_free'] = account['Stocks'] # 当前可用余额
Info['account'][symbol]['unrealised_profit'] = account['UPnL'] # 未实现盈亏
# 从全局存储中读取账户初始余额字典
accDict = _G("init_balance")
if accDict is None:
accDict = {} # 如果全局存储为空,则初始化为空字典
# 初始化账户初始余额(仅在第一次运行时设置)
if not Info['account'][symbol]['init_balance']:
# 如果全局存储有记录且余额大于0,则使用该记录作为初始余额
if accDict and accDict.get(symbol) and accDict[symbol] > 0:
Info['account'][symbol]['init_balance'] = round(accDict[symbol], 2)
else:
# 否则,将当前保证金余额作为初始余额
Info['account'][symbol]['init_balance'] = Info['account'][symbol]['margin_balance'] * Info['ticker'][symbol]['last']
accDict[symbol] = Info['account'][symbol]['init_balance'] # 更新全局存储
_G("init_balance", accDict)
# 计算账户利润及利润率
Info['account'][symbol]['profit'] = round(Info['account'][symbol]['margin_balance'] * Info['ticker'][symbol]['last'] - Info['account'][symbol]['init_balance'], 2) # 当前利润
Info['account'][symbol]['profit_rate'] = round((100 * Info['account'][symbol]['profit']) / Info['account'][symbol]['init_balance'], 2) # 当前利润率(百分比)
# 更新仓位信息
def UpdatePosition():
# 获取永续合约的仓位信息
# 调用接口获取指定币种的仓位信息
pos = exchange.GetPositions(Info['base_coin'] + ".swap")
# 记录仓位信息的更新时间(单位:毫秒)
Info['time']['update_pos_time'] = time.time() * 1000
# 初始化仓位信息
# 为每个交易币种创建默认的仓位信息
position_info = {symbol: {'amount': 0, 'hold_price': 0, 'unrealised_profit': 0} for symbol in Info['trade_symbols']}
# 遍历获取到的仓位信息,更新对应币种的仓位数据
for data in pos:
# 提取币种名称(Symbol)的一部分作为标识
symbol = data['Symbol'].split("_")[0]
# 过滤掉不属于指定基准币种或不在交易列表中的币种
if not data['Symbol'].split(".")[0].endswith(Info['base_coin']) or symbol not in Info['trade_symbols']:
continue
# 更新仓位信息,区分多头和空头(通过 Type 字段)
position_info[symbol] = {
'amount': data['Amount'] if data['Type'] == 0 else -data['Amount'], # 多头为正,空头为负
'hold_price': data['Price'], # 仓位持有价格
'unrealised_profit': data['Profit'] # 未实现盈亏
}
# 初始化每个币种的仓位统计数据
# long: 多头价值, short: 空头价值, total: 总仓位价值, leverage: 杠杆率
for symbol in Info['trade_symbols']:
Info['count'][symbol] = {'long': 0, 'short': 0, 'total': 0, 'leverage': 0}
# 遍历更新后的仓位信息
for symbol, info in position_info.items():
# 计算仓位变化量
deal_volume = abs(info['amount'] - Info['position'][symbol]['amount'])
# 计算变化方向(正数为增仓,负数为减仓)
direction = 1 if info['amount'] - Info['position'][symbol]['amount'] > 0 else -1
# 如果仓位发生变化,记录成交信息
if deal_volume:
# 获取成交价格(买入或卖出)
deal_price = Info['order'][symbol]['buy']['price'] if direction == 1 else Info['order'][symbol]['sell']['price']
# 打印仓位更新日志
Log(
symbol,
"仓位更新:",
round(Info['position'][symbol]['amount'], 1),
" -> ",
round(info['amount'], 1),
", 买" if direction == 1 else ", 卖",
", 成交价:",
deal_price,
", 成本价:",
round(Info['position'][symbol]['hold_price'], Info['precision'][symbol]['price_precision']),
)
# 更新仓位信息
Info['position'][symbol]['amount'] = info['amount'] # 更新仓位数量
Info['position'][symbol]['hold_price'] = info['hold_price'] # 更新持仓价格
Info['position'][symbol]['value'] = round(Info['position'][symbol]['amount'] * Info['precision'][symbol]['ctVal'], 2) # 仓位价值
Info['position'][symbol]['unrealised_profit'] = info['unrealised_profit'] # 更新未实现盈亏
# 统计多头和空头仓位价值
if Info['position'][symbol]['amount'] > 0:
# 如果为多头,增加多头仓位价值
Info['count'][symbol]['long'] += abs(Info['position'][symbol]['value'])
else:
# 如果为空头,增加空头仓位价值
Info['count'][symbol]['short'] += abs(Info['position'][symbol]['value'])
# 计算仓位总价值(按最新价格计算)
Info['count'][symbol]['total'] = round((Info['count'][symbol]['long'] + Info['count'][symbol]['short']) / Info['ticker'][symbol]['last'], 2)
# 计算杠杆率(总仓位价值与账户保证金的比值)
Info['count'][symbol]['leverage'] = round(Info['count'][symbol]['total'] / Info['account'][symbol]['margin_balance'], 2)
# 订单函数
def Order(symbol, direction, price, amount, msg):
pair = f"{symbol}_{Info['base_coin']}.swap" # 构造交易对名称
ret = exchange.CreateOrder(pair, direction, price, amount, msg) # 执行下单操作
# 判断是否下单成功
if ret:
Info['order'][symbol][direction]['id'] = ret # 记录订单ID
Info['order'][symbol][direction]['price'] = price # 记录下单价格
Log('记录下单价格:', price, direction, Info['order'][symbol][direction]['price'], )
else:
Log(f"{symbol} {direction} {price} {amount} 下单异常") # 输出异常信息
# 交易函数
def Trade(symbol, direction, price, amount, msg):
# 根据最小价格变动调整价格
price = round(price - (price % Info['precision'][symbol]['tick_size']), Info['precision'][symbol]['price_precision'])
# 计算调整后的交易数量
amount = amount / Info['precision'][symbol]['ctVal'] # 计算真实合约数量
amount = round(amount - (amount % Info['precision'][symbol]['amount_size']), Info['precision'][symbol]['amount_precision'])
# 限制最大交易数量
if Info['precision'][symbol]['max_qty'] > 0:
amount = min(amount, Info['precision'][symbol]['max_qty'])
new_order = False
# 如果新价格与之前的订单价格差异大于0.0001,则重新下单
if Info['order'][symbol][direction]['price'] > 0 and abs(price - Info['order'][symbol][direction]['price']) / price > 0.0001:
Log('已持订单,订单价格发生变化')
new_order = True
# 如果交易数量为0或者当前订单ID为0,则撤单
if amount <= 0 or Info['order'][symbol][direction]['id'] == 0:
Log('新订单产生')
new_order = True
# 如果需要新订单
if new_order:
# 如果有原有订单,撤销它
if Info['order'][symbol][direction]['id'] != 0:
exchange.CancelOrder(Info['order'][symbol][direction]['id'])
Info['order'][symbol][direction]['id'] = 0
Info['order'][symbol][direction]['price'] = 0
Log('撤单成功:', symbol)
# 如果更新仓位或ticker的延迟太高,则不下单
#if (time.time() * 1000 - Info['time']['update_pos_time'] > 2 * Info['interval'] * 1000 or
# time.time() * 1000 - Info['time']['update_ticker_time'] > 2 * Info['interval'] * 1000):
# Log('仓位更新时间', time.time() * 1000, Info['time']['update_pos_time'], time.time() * 1000 - Info['time']['update_pos_time'])
# Log('Ticker更新时间', time.time() * 1000, Info['time']['update_ticker_time'], time.time() * 1000 - Info['time']['update_ticker_time'])
# Log('延迟过高')
# return
# 如果订单金额或数量过低,不执行下单操作
if price * amount <= Info['precision'][symbol]['min_notional'] or amount < Info['precision'][symbol]['min_qty']:
Log(f"{symbol} 下单量太低", price * amount)
return
# 执行下单操作
Log('order下单:', symbol)
Order(symbol, direction, price, amount, msg)
# 更新状态函数
def UpdateStatus():
# 更新状态时间
Info['time']['update_status_time'] = time.time() * 1000
# 账户信息表格
table1 = {
"type": "table",
"title": "账户信息",
"cols": [
"币种", "初始权益", "实时权益", "可用余额",
"总收益", "收益率"
],
"rows": [],
}
# 遍历每个交易对,填充交易对信息
for symbol in Info['trade_symbols']:
table1['rows'].append([
symbol, # 币种
round(Info['account'][symbol]['init_balance'], 2), # 初始权益
round(Info['account'][symbol]['margin_balance'] * Info['ticker'][symbol]['last'], 2), # 实时权益
round(Info['account'][symbol]['margin_free'] * Info['ticker'][symbol]['last'], 2), # 可用余额
round(Info['account'][symbol]['profit'], 2), # 总收益
str(Info['account'][symbol]['profit_rate']) + "%" # 收益率
])
# 交易对信息表格
table2 = {
"type": "table",
"title": "交易对信息",
"cols": [
"币种", "方向", "数量", "持仓价格", "持仓价值",
"现价"
],
"rows": [],
}
# 遍历每个交易对,填充交易对信息
for symbol in Info['trade_symbols']:
table2['rows'].append([
symbol, # 币种
"LONG" if Info['position'][symbol]['amount'] > 0 else "SHORT", # 方向
Info['position'][symbol]['amount'], # 数量
round(Info['position'][symbol]['hold_price'], Info['precision'][symbol]['price_precision']), # 持仓价格
round(Info['position'][symbol]['value'], 2), # 持仓价值
round(Info['ticker'][symbol]['last'], Info['precision'][symbol]['price_precision']) # 现价
])
# 输出状态日志
LogStatus(
f"初始化时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(Info['time']['start_time']))}\n",
f"`{json.dumps(table1)}`\n" + f"`{json.dumps(table2)}`\n",
f"循环延时: {str(Info['time']['loop_delay']) + 'ms'}\n",
f"最后执行时间: {_D()}\n"
)
totalprofit = 0
for symbol in Info['trade_symbols']:
totalprofit += Info['account'][symbol]['profit']
# 每10秒钟更新一次账户信息
if time.time() * 1000 - Info['time']['update_profit_time'] > 10 * 1000:
LogProfit(round(totalprofit, 3), '&') # 输出收益日志
Info['time']['update_profit_time'] = time.time() * 1000 # 更新收益时间
def MakeOrder():
# 遍历所有交易对
for symbol in Info['trade_symbols']:
availBal = Info['account'][symbol]['margin_free'] * Info['ticker'][symbol]['last'] #可用金额
sell_price = Info['ticker'][symbol]['ask'] #卖出价格
if availBal > ICEMONEY: #可用金额大于冰山挂单数量,起始建仓
Trade(symbol, "sell", sell_price, ICEMONEY, symbol) # 执行买入操作
elif availBal > ROLLINGNUM * Info['precision'][symbol]['ctVal']: #可用盈利大于滚动加仓数量,逐步下单
Trade(symbol, "sell", sell_price, ROLLINGNUM * Info['precision'][symbol]['ctVal'], symbol) # 执行买入操作
def OnTick():
# 更新市场行情信息
UpdateTicker()
# 更新账户信息
UpdateAccount()
# 更新持仓信息
UpdatePosition()
# 执行下单操作
MakeOrder()
# 更新状态信息
UpdateStatus()
def main():
LogReset(0) # 日志重置
Log('策略起始#0000ff')
# 初始化信息
InitInfo() # 初始化币种信息
GetPrecision() # 获取精度信息
exchange.SetMarginLevel(1) # 设置杠杆倍数
while True: # 无限循环
loop_start_time = time.time() * 1000 # 获取当前时间(毫秒)
# 检查上次循环时间与设定的间隔时间是否已过
if time.time() * 1000 - Info['time']['last_loop_time'] > Info['interval'] * 1000:
OnTick() # 调用 OnTick 函数
# 更新最后一次循环时间
Info['time']['last_loop_time'] = time.time() * 1000
# 计算当前循环的延迟时间
Info['time']['loop_delay'] = time.time() * 1000 - loop_start_time
# 暂停5毫秒,避免过度消耗CPU资源
Sleep(5)
1. 全局变量与功能描述
策略以简单变量定义为基础,通过模块化功能实现滚动加仓与状态监控。
- SYMBOLS:交易币种(如"BTC")。
- QUOTO:基础货币,币本位通常为USD。
- INTERVAL:策略循环的时间间隔。
- ICEMONEY:初始下单金额,用于冰山订单。
- ROLLINGNUM:滚动盈利后的加仓数量。
2. 核心功能模块
以下为各功能模块的简要说明:
-
初始化函数 (InitInfo)
用于加载交易币种信息和初始账户状态。 -
精度信息获取 (GetPrecision)
通过交易所 API 获取每个交易对的最小下单单位和合约价值。 -
行情更新 (UpdateTicker)
定期获取当前市场行情,包括买一价、卖一价和最新价。 -
账户与持仓更新 (UpdateAccount, UpdatePosition)
实时同步账户余额、持仓信息,为交易决策提供依据。 -
交易与订单管理 (Order, Trade)
统一下单与执行功能,支持限价单与市价单操作。 -
状态监控 (UpdateStatus)
跟踪策略运行状态,包括当前盈亏和未成交订单。
3. 策略下单逻辑 (MakeOrder)
策略的核心在于初始建仓(冰山建仓)和滚动加仓(受滚动加仓参数 ROLLINGNUM 控制)。以下是具体逻辑的详细说明:
- 初始建仓检查:验证账户余额是否大于初始冰山建仓金额(ICEMONEY)。若满足条件,逐步分批开仓,以减少因一次性建仓而产生的过大价格滑点。
- 滚动加仓策略:根据账户的盈利情况(资金费率收益),合理增加仓位,通过滚动加仓优化收益,从而提升策略的总体盈利能力。
根据策略回测结果,可以看到策略在多个市场周期中获取了稳定的收益,尤其是在资金费率长期为正的牛市中表现尤为突出。因此,这一策略在一定程度上非常适合大资金管理。其低波动性、稳定收益的特点,能够满足大资金对风险控制和收益稳定性的双重需求。同时,策略采用1倍杠杆,避免了高杠杆带来的爆仓风险,进一步增强了其安全性。
策略优缺点分析
优点
-
策略简单易执行
逻辑清晰,无需复杂计算,适合对冲基金或个人投资者的大资金管理。 -
抗风险能力强
一倍杠杆规避爆仓风险,且币本位的特性保证了美元价值恒定,无惧市场大幅波动。 -
收益稳定
牛市中资金费率收益较高,延展性强,可利用所得币种进行其他投资(如质押)。
缺点
- 对币种和行情依赖较强
这点是硬伤,当一个币种资金费率长期为正时(空头支付多头),比如BNB合约,使用【数据探索】模块选择BNB币本位合约,可以看到由于交易所的设置,资金费率累计为负值。另外当大周期长期处于熊市(2022年),资金费率为负时,收益可能无法覆盖策略运行成本。
(chart/1c793b63-cb8b-49ff-bdc1-db482e6f8cd7)
-
策略刚性不足
当前策略未包含动态调整逻辑,如牛熊市切换时缺乏应对措施(如止损或止盈策略)。 -
盈利空间有限
适合“躺平”收取资费,无法捕捉大波动行情中的超额收益,某些情况下收益率不如传统债券基金。
小结
币本位一倍做空资费套利策略充分利用了币本位合约的特殊性质,为资金保值与稳定增值提供了一个低风险的方案。然而,面对不同的市场阶段,策略需要具备一定的灵活性,以应对资金费率的波动和潜在风险。未来的优化方向可以包括:
- 增加牛熊市场切换的动态管理措施;
- 根据资金费率的变化情况,调整加仓节奏。
但从本质上讲,该策略存在一定的矛盾。策略的初始假设是数字货币市场长期处于牛市状态,通过做空币本位合约来保持稳定现金流并获取资金费率收益。然而,如果我们假设市场处于长期牛市,为什么不直接选择囤币(hlod),静待比特币的稳步上涨呢?当然,对于追求稳定收益的策略而言,该策略依然是可靠的。本文的目标主要是介绍这一设计思路,并提供一种量化投资的策略框架,大家可以在此基础上进行进一步完善和优化。希望该策略能够成为数字货币量化投资者的有效工具。
参考来源
算法交易实战日记(十九) —— 套利策略详解系列(1):币本位做空资费套利
温馨提示:投资有风险,入市需谨慎。建议投资者在充分了解策略逻辑与风险的基础上,根据自身风险承受能力合理配置资金,并严格控制仓位与杠杆。本文内容仅供参考,不构成任何投资建议。
- 1



