3
Follow
1505
Followers
多平台期货资金费率获取与监控策略
描述:
该策略用于从多个期货平台(如OKCoin、Binance、Bitget等)获取和监控资金费率。通过并行线程轮询各交易所的永续合约市场,并获取资金费率数据,同时使用延迟机制优化请求频率。
本篇文章对策略进行了一些改动,支持了展示和资金费率报警推送功能。
开源地址: https://www.fmz.com/strategy/470345
功能:
- 多平台支持:同步多个交易平台的资金费率,并为每个平台设定不同的请求延迟。
- 特定符号获取:支持获取特定交易对(如BTC/USDT, ETH/USDT)的资金费率。
- 针对不同平台优化:区分无需逐个市场查询的平台(如Binance)和需要遍历所有市场的平台(如OKCoin)。
- 费率展示:展示多个交易平台的资金费率,因为收取间隔不同,为了直接比较,统一调整为24h费率。
- 费率预警推送:可设定一定阈值,当24h等效费率超过设定值就会推送到FMZ手机APP上。
使用方法:
您可以根据需要调整平台列表、符号列表和轮询间隔,以满足特定的交易需求。
策略代码
该脚本分为几个主要部分:
- startFundingWorker:启动每个交易所的独立线程来监控资金费率,避免单个线程请求过多数据引发的限流问题。
- getFundings:从存储中读取指定交易所的资金费率数据。
- UpdateStatus:处理并更新所有交易所的资金费率表,将汇总后的数据展示为一张表,并将高费率的符号记录到日志中。
- main:启动主程序,启动监控线程并定期更新汇总的资金费率状态。
javascript
// 启动资金费率监控线程,为每个交易所的资金费率数据创建一个单独的线程
function startFundingWorker() {
exchanges.forEach((_, pos) => {
__Thread(function (pos) {
let e = exchanges[pos]
let eName = e.GetName()
// 设置不同交易所的请求延迟,以防止频繁请求导致被限流
let delaySettings = {
'Futures_OKCoin': 20,
'Futures_Binance': 500,
'Futures_MEXC': 100,
}
// 需要遍历所有市场的交易所名称列表,这些交易所不支持一次获取所有交易对
let needInterate = ['Futures_OKCoin', 'Futures_Bitget','Futures_OKX', 'Futures_KuCoin', 'Futures_MEXC']
// 根据交易所名称设定延迟
let delay = function () {
let n = delaySettings[eName]
if (n) {
Sleep(n)
}
}
// 设定更新间隔,每两分钟更新一次
let epoch = 60000 * 2;
let ts = 0;
let fundings = {}
// 无限循环,以固定间隔获取资金费率
while (true) {
let now = new Date().getTime()
if (now - ts < epoch) {
// 未达到更新周期则暂停1秒后继续检查
Sleep(1000)
continue
}
let markets = e.GetMarkets()
if (!markets) {
// 如果未能获取到市场信息,则延迟后重试
Sleep(1000)
continue
}
// 如果交易所在需要遍历的列表中,逐个市场请求资金费率
if (needInterate.includes(eName)) {
for (let symbol in markets) {
if (symbol.includes('.swap') && symbol.includes('_USDT')) {
let ret = e.GetFundings(symbol)
if (ret) {
for (let r of ret) {
fundings[r.Symbol] = r
}
}
delay();
}
}
} else {
// 不在遍历列表中的交易所,仅请求 USDT.swap 的资金费率
let ret = e.GetFundings('USDT.swap')
if (ret) {
for (let r of ret) {
fundings[r.Symbol] = r
}
}
}
// 更新数据时间戳
ts = now
// 存储该交易所的资金费率数据
__threadSetData(0, eName+"_funding", fundings)
}
}, pos)
})
}
// 获取指定交易所的资金费率数据
function getFundings(eName) {
let efundings = __threadGetData(0, eName+"_funding")
if (!efundings) {
return null
}
return efundings
}
// 更新资金费率表并在日志中显示
function UpdateStatus(){
let table = {
type: 'table',
title: 'Funding Rate%',
cols: ['index', 'symbol'], // 初始化列,包含 symbol
rows: []
};
let fundingRates = {};
exchanges.forEach((e) => {
let eName = e.GetName();
if (fundings[eName]) {
for (let symbol in fundings[eName]) {
// 解析简短的 symbol 名称,去除多余前缀
let short_symbol = symbol.split('_')[0].replace(/^(100|1000|10000|100000|1000000|10000000)|^(100|1000|10000|100000|1000000|10000000)$/g, '');
let rate = fundings[eName][symbol].Rate;
let day = 24 / (fundings[eName][symbol].Interval / 3600000)
// 初始化符号的数据结构
if (!fundingRates[short_symbol]) {
fundingRates[short_symbol] = { total: 0, count: 0, day_rate: {}, next_time: {}, last_time:0};
}
// 对超过阈值的费率进行记录并推送
if (Math.abs(rate) > 0.01 && Date.now() - fundingRates[short_symbol].last_time > 30*60*1000) {
Log(e.GetName(), symbol, rate, '@')
fundingRates[short_symbol].last_time = Date.now()
}
fundingRates[short_symbol].total += rate;
fundingRates[short_symbol].count++;
fundingRates[short_symbol].day_rate[eName] = _N(rate * day , 6); // 记录费率
fundingRates[short_symbol].next_time[eName] = _N((fundings[eName][symbol].Time - Date.now()) / 3600000 , 1) + 'h'
}
}
});
// 为每个交易所添加费率列和下次更新的时间列
for (let e of exchanges) {
table.cols.push(e.GetName()+' Rate');
table.cols.push('Next Time');
}
table.cols.push('Average Rate'); // 添加平均费率列
let i = 0;
// 遍历每个符号并填充数据
for (let symbol in fundingRates) {
let data = fundingRates[symbol];
if (data.count == 1) {
continue // 只包含单个数据点的符号忽略
}
let averageRate = data.total / data.count; // 计算平均费率
let row = [i++, symbol];
for (let e of exchanges) {
row.push(data.day_rate[e.GetName()] || null); // 填充各个交易所的费率
row.push(data.next_time[e.GetName()] || null);
}
row.push(_N(averageRate, 6)); // 填充平均费率
table.rows.push(row);
}
LogStatus('`' + JSON.stringify(table) + '`');
}
// 主函数,启动资金费率监控和状态更新
var fundings = {}
function main() {
startFundingWorker() // 启动每个交易所的监控线程
while (true) {
exchanges.forEach((e) => {
let eName = e.GetName()
let eFundings = getFundings(eName)
fundings[eName] = eFundings
})
Sleep(15000) // 每15秒更新一次
UpdateStatus()
}
}
Related Recommendations
Discussion on External Signal Reception of FMZ Platform: Extended API VS Strategy Built-in HTTP ServiceDiscussion on Strategy Testing Method Based on Random Ticker GeneratorNew Feature of FMZ Quant: Use _Serve Function to Create HTTP Services EasilyFMZ Quant Trading Platform Custom Protocol Access GuideFMZ Funding Rate Acquisition and Monitoring StrategyA Strategy Template Allows You to Use WebSocket Market SeamlesslyHow to Build a Universal Multi-Currency Trading Strategy Quickly after FMZ UpgradeDCA Trading: A Widely Used Quantitative StrategyExploring FMZ: Practice of Communication Protocol Between Live Trading StrategiesExploring FMZ: New Application of Status Bar Buttons (Part 1)


