3
Follow
1505
Followers
멀티 플랫폼 선물 자금 조달 비율 획득 및 모니터링 전략
설명하다:
이 전략은 OKCoin, Binance, Bitget 등 다양한 선물 플랫폼에서 자금 조달 비율을 얻고 모니터링하는 데 사용됩니다. 다양한 거래소의 영구 계약 시장을 병렬 스레드를 통해 조사하고 자금 조달 비율 데이터를 얻는 동시에 지연 메커니즘을 사용하여 요청 빈도를 최적화합니다.
이 문서에서는 디스플레이 및 자금 조달 비율 알람 푸시 기능을 지원하기 위한 전략에 몇 가지 변경 사항을 적용합니다.
오픈소스 주소: https://www.fmz.com/strategy/470345
기능:
- 다중 플랫폼 지원: 여러 거래소의 자금 조달 비율을 동기화하고 각 거래소에 대해 다른 요청 지연을 설정합니다.
- 특정 심볼 획득: 특정 거래 쌍(예: BTC/USDT, ETH/USDT)에 대한 자금 조달 비율을 확보하는 것을 지원합니다.
- 다양한 플랫폼에 최적화됨: 각 시장을 하나하나 쿼리할 필요가 없는 플랫폼(예: 바이낸스)과 모든 시장을 탐색해야 하는 플랫폼(예: OKCoin)을 구분합니다.
- 요금 표시: 여러 거래 플랫폼의 자금 조달 비율을 표시합니다. 충전 간격이 다르기 때문에 직접 비교할 수 있도록 24시간 비율로 균일하게 조정됩니다.
- 요금 경고 푸시: 특정 임계값을 설정할 수 있습니다. 24시간 등가 비율이 설정 값을 초과하면 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)


