avatar of 发明者量化-小小梦 发明者量化-小小梦
پر توجہ دیں نجی پیغام
4
پر توجہ دیں
1271
پیروکار

FMZ پر مبنی ایک ملٹی اکاؤنٹ کاپی ٹریڈنگ سسٹم بنانا جو میری زبان اور پائن حکمت عملی کی زبان کو سپورٹ کرتا ہے۔

میں تخلیق کیا: 2025-05-22 16:28:53, تازہ کاری: 2025-05-23 10:08:21
comments   0
hits   546

[TOC]

دستاویزی نظام کے لیے مطالبہ منظرنامے۔

FMZ پلیٹ فارم کمیونٹی میں اور صارفین کے ساتھ نجی بات چیت میں، مجھ سے اکثر یہ سوال پوچھا جاتا ہے:

“میرے یا پائن اسکرپٹ میں لکھی گئی حکمت عملی صرف ایک اکاؤنٹ اور ایک پروڈکٹ کو کیوں کنٹرول کر سکتی ہے؟”

اس مسئلے کا جوہر خود زبان کی ڈیزائن پوزیشننگ میں مضمر ہے۔ میری زبان اور پائن لینگویج انتہائی انکیپسلیٹڈ اسکرپٹنگ زبانیں ہیں، اور ان کا بنیادی نفاذ JavaScript پر مبنی ہے۔ صارفین کو تیزی سے شروع کرنے اور حکمت عملی کی منطق پر توجہ مرکوز کرنے کی اجازت دینے کے لیے، دونوں نے زبان کی سطح پر کافی انکیپسولیشن اور تجرید کیے ہیں، لیکن اس نے ایک خاص حد تک لچک کو بھی قربان کیا ہے: پہلے سے طے شدہ طور پر، صرف ایک اکاؤنٹ، واحد پروڈکٹ حکمت عملی پر عمل درآمد ماڈل کی حمایت کی جاتی ہے۔

جب کوئی صارف ایک سے زیادہ اکاؤنٹس کو حقیقی وقت میں چلانا چاہتا ہے، تو یہ صرف ایک سے زیادہ Pine یا My اصلی مثالوں کو چلا کر حاصل کیا جا سکتا ہے۔ یہ نقطہ نظر اس وقت قابل قبول ہے جب اکاؤنٹس کی تعداد کم ہو، لیکن اگر ایک ہی میزبان پر ایک سے زیادہ مثالیں تعینات کی جاتی ہیں، تو بڑی تعداد میں API کی درخواستیں پیدا ہوں گی، اور ایکسچینج ضرورت سے زیادہ درخواست کی فریکوئنسی کی وجہ سے رسائی کو بھی محدود کر سکتا ہے، جس سے حقیقی وقت میں غیر ضروری خطرات لاحق ہوتے ہیں۔

تو، کیا صرف پائن یا مائی لینگویج اسکرپٹ کو چلانے کا کوئی زیادہ خوبصورت طریقہ ہے تاکہ دوسرے اکاؤنٹس اس کے تجارتی رویے کو خود بخود کاپی کر سکیں؟

جواب ہے: ہاں۔

یہ مضمون شروع سے کراس اکاؤنٹ، کراس پروڈکٹ کاپی ٹریڈنگ سسٹم بنانے میں آپ کی رہنمائی کرے گا، جو مائی اور پائن زبان کی حکمت عملیوں کے ساتھ مطابقت رکھتا ہے۔ لیڈر-سبسکرائبر آرکیٹیکچر کے ذریعے، یہ ایک موثر، مستحکم، اور توسیع پذیر ملٹی اکاؤنٹ سنکرونس ٹریڈنگ فریم ورک کو لاگو کرے گا تاکہ آپ کو حقیقی وقت کی تعیناتی میں درپیش مختلف درد کے نکات کو حل کیا جا سکے۔

حکمت عملی ڈیزائن

پروگرام جاوا اسکرپٹ میں لکھا اور ڈیزائن کیا گیا ہے، اور پروگرام کا فن تعمیر لیڈر-سبسکرائبر ماڈل کا استعمال کرتا ہے۔

حکمت عملی کا ماخذ کوڈ:

/*backtest
start: 2024-05-21 00:00:00
end: 2025-05-20 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"},{"eid":"Futures_Binance","currency":"ETH_USDT"},{"eid":"Futures_Binance","currency":"ETH_USDT","balance":10000}]
args: [["isBacktest",true]]
*/

class Leader {
    constructor(leaderCfg = { type: "exchange", apiClient: exchanges[0] }) {
        // 带单账户配置
        this.leaderCfg = leaderCfg
        // 缓存上次持仓信息,用于对比
        this.lastPos = null
        // 记录当前持仓信息
        this.currentPos = null
        // 记录订阅者
        this.subscribers = []

        // 根据 leaderCfg 配置,确定使用哪种监控方案:1、直接监控带单账户。2、通过FMZ 扩展API监控带单策略实盘的数据。3、消息推送机制跟单。默认使用方案1。

        // 初始化
        let ex = this.leaderCfg.apiClient
        let currency = ex.GetCurrency()
        let arrCurrency = currency.split("_")
        if (arrCurrency.length !== 2) {
            throw new Error("带单账户配置错误,必须是两种币对")
        }
        this.baseCurrency = arrCurrency[0]
        this.quoteCurrency = arrCurrency[1]
        // 获取初始化时,带单账户的总权益
        this.initEquity = _C(ex.GetAccount).Equity
        this.currentPos = _C(ex.GetPositions)
    }

    // 监控leader的逻辑
    poll() {
        // 获取交易所对象
        let ex = this.leaderCfg.apiClient

        // 获取leader的持仓、账户资产数据
        let pos = ex.GetPositions()
        if (!pos) {
            return
        }
        this.currentPos = pos

        // 调用判断方法,判断持仓变化
        let { hasChanged, diff } = this._hasChanged(pos)
        if (hasChanged) {
            Log("Leader持仓变化,当前持仓:", pos)
            Log("持仓变动:", diff)
            // 通知订阅者
            this.subscribers.forEach(subscriber => {
                subscriber.applyPosChanges(diff)
            })
        }

        // 同步持仓
        this.subscribers.forEach(subscriber => {
            subscriber.syncPositions(pos)
        })
    }

    // 判断持仓是否变化
    _hasChanged(pos) {
        if (this.lastPos) {
            // 用于存储持仓差异的结果
            let diff = {
                added: [],    // 新增的持仓
                removed: [],  // 移除的持仓
                updated: []   // 更新的持仓(数量或价格变化)
            }

            // 将上次持仓和当前持仓转换为 Map,键为 `symbol + direction`,值为持仓对象
            let lastPosMap = new Map(this.lastPos.map(p => [`${p.Symbol}|${p.Type}`, p]))
            let currentPosMap = new Map(pos.map(p => [`${p.Symbol}|${p.Type}`, p]))

            // 遍历当前持仓,找出新增和更新的持仓
            for (let [key, current] of currentPosMap) {
                if (!lastPosMap.has(key)) {
                    // 如果上次持仓中没有该 key,则为新增持仓
                    diff.added.push({ symbol: current.Symbol, type: current.Type, deltaAmount: current.Amount })
                } else {
                    // 如果存在,则检查数量或价格是否变化
                    let last = lastPosMap.get(key)
                    if (current.Amount !== last.Amount) {
                        diff.updated.push({ symbol: current.Symbol, type: current.Type, deltaAmount: current.Amount - last.Amount })
                    }
                    // 从 lastPosMap 中移除,剩下的就是被移除的持仓
                    lastPosMap.delete(key)
                }
            }

            // 剩余在 lastPosMap 中的 key 是被移除的持仓
            for (let [key, last] of lastPosMap) {
                diff.removed.push({ symbol: last.Symbol, type: last.Type, deltaAmount: -last.Amount })
            }

            // 判断是否有变化
            let hasChanged = diff.added.length > 0 || diff.removed.length > 0 || diff.updated.length > 0

            // 如果有变化,更新 lastPos
            if (hasChanged) {
                this.lastPos = pos
            }

            return { hasChanged: hasChanged, diff: diff }
        } else {
            // 如果没有上次持仓记录,更新记录,不做持仓同步
            this.lastPos = pos
            return { hasChanged: false, diff: { added: [], removed: [], updated: [] } }

            /* 另一种方案:同步仓位
            if (pos.length > 0) {
                let diff = {
                    added: pos.map(p => ({symbol: p.Symbol, type: p.Type, deltaAmount: p.Amount})),
                    removed: [],
                    updated: []
                }
                return {hasChanged: true, diff: diff}
            } else {
                return {hasChanged: false, diff: {added: [], removed: [], updated: []}}
            }
            */
        }
    }

    // 订阅者注册
    subscribe(subscriber) {
        if (this.subscribers.indexOf(subscriber) === -1) {
            if (this.quoteCurrency !== subscriber.quoteCurrency) {
                throw new Error("订阅者币对不匹配,当前leader币对:" + this.quoteCurrency + ",订阅者币对:" + subscriber.quoteCurrency)
            }
            if (subscriber.followStrategy.followMode === "equity_ratio") {
                // 设置跟单比例
                let ex = this.leaderCfg.apiClient
                let equity = _C(ex.GetAccount).Equity
                subscriber.setEquityRatio(equity)
            }
            this.subscribers.push(subscriber)
            Log("订阅者注册成功,订阅配置:", subscriber.getApiClientInfo())
        }
    }

    // 取消订阅
    unsubscribe(subscriber) {
        const index = this.subscribers.indexOf(subscriber)
        if (index !== -1) {
            this.subscribers.splice(index, 1)
            Log("订阅者取消注册成功,订阅配置:", subscriber.getApiClientInfo())
        } else {
            Log("订阅者取消注册失败,订阅配置:", subscriber.getApiClientInfo())
        }
    }

    // 获取UI信息
    fetchLeaderUI() {
        // 带单者信息
        let tblLeaderInfo = { "type": "table", "title": "Leader Info", "cols": ["带单方案", "计价币种", "跟单者数量", "初始总权益"], "rows": [] }
        tblLeaderInfo.rows.push([this.leaderCfg.type, this.quoteCurrency, this.subscribers.length, this.initEquity])

        // 构造带单者的显示信息:持仓信息
        let tblLeaderPos = { "type": "table", "title": "Leader pos", "cols": ["交易品种", "方向", "数量", "价格"], "rows": [] }
        this.currentPos.forEach(pos => {
            let row = [pos.Symbol, pos.Type == PD_LONG ? "多" : "空", pos.Amount, pos.Price]
            tblLeaderPos.rows.push(row)
        })

        // 构造订阅者的显示信息
        let strFollowerMsg = ""
        this.subscribers.forEach(subscriber => {
            let arrTbl = subscriber.fetchFollowerUI()
            strFollowerMsg += "`" + JSON.stringify(arrTbl) + "`\n"
        })

        return "`" + JSON.stringify([tblLeaderInfo, tblLeaderPos]) + "`\n" + strFollowerMsg
    }

    // 扩展暂停跟单、移除订阅等功能
}

class Subscriber {
    constructor(subscriberCfg, followStrategy = { followMode: "position_ratio", ratio: 1, maxReTries: 3 }) {
        this.subscriberCfg = subscriberCfg
        this.followStrategy = followStrategy

        // 初始化
        let ex = this.subscriberCfg.apiClient
        let currency = ex.GetCurrency()
        let arrCurrency = currency.split("_")
        if (arrCurrency.length !== 2) {
            throw new Error("订阅者配置错误,必须是两种币对")
        }
        this.baseCurrency = arrCurrency[0]
        this.quoteCurrency = arrCurrency[1]

        // 初始获取持仓数据
        this.currentPos = _C(ex.GetPositions)
    }

    setEquityRatio(leaderEquity) {
        // {followMode: "equity_ratio"} 自动根据账户权益比例跟单
        if (this.followStrategy.followMode === "equity_ratio") {
            let ex = this.subscriberCfg.apiClient
            let equity = _C(ex.GetAccount).Equity
            let ratio = equity / leaderEquity
            this.followStrategy.ratio = ratio
            Log("带单者权益:", leaderEquity, "订阅者权益:", equity)
            Log("自动设置,订阅者权益比例:", ratio)
        }
    }

    // 获取订阅者绑定的API客户端信息
    getApiClientInfo() {
        let ex = this.subscriberCfg.apiClient
        let idx = this.subscriberCfg.clientIdx
        if (ex) {
            return { exName: ex.GetName(), exLabel: ex.GetLabel(), exIdx: idx, followStrategy: this.followStrategy }
        } else {
            throw new Error("订阅者没有绑定API客户端")
        }
    }

    // 根据持仓类型、仓位变化,返回交易方向参数
    getTradeSide(type, deltaAmount) {
        if (type == PD_LONG && deltaAmount > 0) {
            return "buy"
        } else if (type == PD_LONG && deltaAmount < 0) {
            return "closebuy"
        } else if (type == PD_SHORT && deltaAmount > 0) {
            return "sell"
        } else if (type == PD_SHORT && deltaAmount < 0) {
            return "closesell"
        }

        return null
    }

    getSymbolPosAmount(symbol, type) {
        let ex = this.subscriberCfg.apiClient
        if (ex) {
            let pos = _C(ex.GetPositions, symbol)
            if (pos.length > 0) {
                // 遍历持仓,查找对应的symbol和type
                for (let i = 0; i < pos.length; i++) {
                    if (pos[i].Symbol === symbol && pos[i].Type === type) {
                        return pos[i].Amount
                    }
                }
            }
            return 0
        } else {
            throw new Error("订阅者没有绑定API客户端")
        }
    }

    // 下单重试
    tryCreateOrder(ex, symbol, side, price, amount, label, maxReTries) {
        for (let i = 0; i < Math.max(maxReTries, 1); i++) {
            let orderId = ex.CreateOrder(symbol, side, price, amount, label)
            if (orderId) {
                return orderId
            }
            Sleep(1000)
        }
        return null
    }

    // 同步持仓变化
    applyPosChanges(diff) {
        let ex = this.subscriberCfg.apiClient
        if (ex) {
            ["added", "removed", "updated"].forEach(key => {
                diff[key].forEach(item => {
                    let side = this.getTradeSide(item.type, item.deltaAmount)
                    if (side) {
                        // 计算跟单比例
                        let ratio = this.followStrategy.ratio
                        let tradeAmount = Math.abs(item.deltaAmount) * ratio
                        if (side == "closebuy" || side == "closesell") {
                            // 获取持仓数量检查
                            let posAmount = this.getSymbolPosAmount(item.symbol, item.type)
                            tradeAmount = Math.min(posAmount, tradeAmount)
                        }
                        // 订单Id
                        // let orderId = ex.CreateOrder(item.symbol, side, -1, tradeAmount, ex.GetLabel())
                        let orderId = this.tryCreateOrder(ex, item.symbol, side, -1, tradeAmount, ex.GetLabel(), this.followStrategy.maxReTries)
                        // 检测订单Id
                        if (orderId) {
                            Log("订阅者下单成功,订单Id:", orderId, ",下单方向:", side, ",下单数量:", Math.abs(item.deltaAmount), ",跟单比例(倍):", ratio)
                        } else {
                            Log("订阅者下单失败,订单Id:", orderId, ",下单方向:", side, ",下单数量:", Math.abs(item.deltaAmount), ",跟单比例(倍):", ratio)
                        }
                    }
                })
            })

            // 更新当前持仓
            this.currentPos = _C(ex.GetPositions)
        } else {
            throw new Error("订阅者没有绑定API客户端")
        }
    }

    // 同步持仓
    syncPositions(leaderPos) {
        let ex = this.subscriberCfg.apiClient
        this.currentPos = _C(ex.GetPositions)

        // 用于存储持仓差异的结果
        let diff = {
            added: [],    // 新增的持仓
            removed: [],  // 移除的持仓
            updated: []   // 更新的持仓(数量或价格变化)
        }
        let leaderPosMap = new Map(leaderPos.map(p => [`${p.Symbol}|${p.Type}`, p]))
        let currentPosMap = new Map(this.currentPos.map(p => [`${p.Symbol}|${p.Type}`, p]))
        // 遍历当前持仓,找出新增和更新的持仓
        for (let [key, leader] of leaderPosMap) {
            if (!currentPosMap.has(key)) {
                diff.added.push({ symbol: leader.Symbol, type: leader.Type, deltaAmount: leader.Amount })
            } else {
                let current = currentPosMap.get(key)
                if (leader.Amount !== current.Amount) {
                    diff.updated.push({ symbol: leader.Symbol, type: leader.Type, deltaAmount: leader.Amount - current.Amount * this.followStrategy.ratio })
                }
                currentPosMap.delete(key)
            }
        }
        for (let [key, current] of currentPosMap) {
            diff.removed.push({ symbol: current.Symbol, type: current.Type, deltaAmount: -current.Amount * this.followStrategy.ratio })
        }
        // 判断是否有变化
        let hasChanged = diff.added.length > 0 || diff.removed.length > 0 || diff.updated.length > 0
        if (hasChanged) {
            // 同步
            this.applyPosChanges(diff)
        }
    }

    // 获取订阅者UI信息
    fetchFollowerUI() {
        // 订阅者信息
        let ex = this.subscriberCfg.apiClient
        let equity = _C(ex.GetAccount).Equity
        let exLabel = ex.GetLabel()
        let tblFollowerInfo = { "type": "table", "title": "Follower Info", "cols": ["交易所对象索引", "交易所对象标签", "计价币种", "跟单模式", "跟单比例(倍)", "最大重试次数", "总权益"], "rows": [] }
        tblFollowerInfo.rows.push([this.subscriberCfg.clientIdx, exLabel, this.quoteCurrency, this.followStrategy.followMode, this.followStrategy.ratio, this.followStrategy.maxReTries, equity])

        // 订阅者持仓信息
        let tblFollowerPos = { "type": "table", "title": "Follower pos", "cols": ["交易品种", "方向", "数量", "价格"], "rows": [] }
        let pos = this.currentPos
        pos.forEach(p => {
            let row = [p.Symbol, p.Type == PD_LONG ? "多" : "空", p.Amount, p.Price]
            tblFollowerPos.rows.push(row)
        })

        return [tblFollowerInfo, tblFollowerPos]
    }
}

// 测试函数,模拟随机开仓,模拟leader仓位变动
function randomTrade(symbol, amount) {
    let randomNum = Math.random()
    if (randomNum < 0.0001) {
        Log("模拟带单交易", "#FF0000")
        let ex = exchanges[0]
        let pos = _C(ex.GetPositions)

        if (pos.length > 0) {
            // 随机平仓
            let randomPos = pos[Math.floor(Math.random() * pos.length)]
            let tradeAmount = Math.random() > 0.7 ? Math.abs(randomPos.Amount * 0.5) : Math.abs(randomPos.Amount)
            ex.CreateOrder(randomPos.Symbol, randomPos.Type === PD_LONG ? "closebuy" : "closesell", -1, tradeAmount, ex.GetLabel())
        } else {
            let tradeAmount = Math.random() * amount
            let side = Math.random() > 0.5 ? "buy" : "sell"
            if (side === "buy") {
                ex.CreateOrder(symbol, side, -1, tradeAmount, ex.GetLabel())
            } else {
                ex.CreateOrder(symbol, side, -1, tradeAmount, ex.GetLabel())
            }
        }
    }
}

// 策略主循环
function main() {
    let leader = new Leader()

    let followStrategyArr = JSON.parse(strFollowStrategyArr)
    if (followStrategyArr.length > 0 && followStrategyArr.length !== exchanges.length - 1) {
        throw new Error("跟单策略配置错误,跟单策略数量和交易所数量不匹配")
    }

    for (let i = 1; i < exchanges.length; i++) {
        let subscriber = null
        if (followStrategyArr.length == 0) {
            subscriber = new Subscriber({ apiClient: exchanges[i], clientIdx: i })
        } else {
            let followStrategy = followStrategyArr[i - 1]
            subscriber = new Subscriber({ apiClient: exchanges[i], clientIdx: i }, followStrategy)
        }
        leader.subscribe(subscriber)
    }

    // 启动监控
    while (true) {
        leader.poll()
        Sleep(1000 * pollInterval)

        // 模拟随机交易
        if (IsVirtual() && isBacktest) {
            randomTrade("BTC_USDT.swap", 0.001)
            randomTrade("ETH_USDT.swap", 0.02)
            randomTrade("SOL_USDT.swap", 0.1)
        }

        LogStatus(_D(), "\n", leader.fetchLeaderUI())
    }
}
  • ڈیزائن پیٹرن ہم نے پہلے پلیٹ فارم پر ایک سے زیادہ کاپی ٹریڈنگ کی حکمت عملی تیار کی ہے، ایک پراسیس پر مبنی ڈیزائن کا استعمال کرتے ہوئے۔ یہ مضمون ایک نئی ڈیزائن کی کوشش ہے، جس میں آبجیکٹ پر مبنی انداز اور مبصر ڈیزائن پیٹرن کا استعمال کیا گیا ہے۔

  • مانیٹرنگ حل نام نہاد کاپی ٹریڈنگ کا نچوڑ ایک قسم کی نگرانی کا رویہ ہے، ہدف کے اعمال کی نگرانی کرنا اور نئی کارروائیاں ملنے پر انہیں نقل کرنا۔

یہ مضمون صرف ایک حل کو نافذ کرتا ہے: تبادلے کی اشیاء کو ترتیب دینے اور ہدف اکاؤنٹ کی پوزیشنوں کی نگرانی کے لیے API KEY کا استعمال۔ درحقیقت، دو دیگر حل ہیں جو ڈیزائن میں زیادہ پیچیدہ ہو سکتے ہیں:

  • FMZ کے توسیعی API کے ذریعے ٹارگٹ اصلی اکاؤنٹ کے لاگ اور اسٹیٹس بار کی معلومات کی نگرانی کریں، اور آپریشنز کریں اور تبدیلیوں کی بنیاد پر آرڈرز کی پیروی کریں۔ اس حل کو استعمال کرنے کا فائدہ یہ ہے کہ یہ API کی درخواستوں کو مؤثر طریقے سے کم کر سکتا ہے۔

  • ہدف اصلی ڈسک پیغام دھکا پر منحصر ہے آپ FMZ پر ٹارگٹ ریئل اکاؤنٹ کے میسج پش کو آن کر سکتے ہیں، اور جب ٹارگٹ ریئل اکاؤنٹ کا آرڈر ہو گا تو ایک پیغام دھکیل دیا جائے گا۔ کاپی ٹریڈنگ کی حکمت عملی یہ پیغامات وصول کر سکتی ہے اور کارروائی کر سکتی ہے۔ اس حل کو استعمال کرنے کے فوائد میں شامل ہیں: API کی درخواستوں کو کم کرنا اور درخواست کے پولنگ میکانزم سے ایونٹ سے چلنے والے میکانزم میں تبدیل کرنا۔

  • تجارتی حکمت عملی کو کاپی کریں۔

کاپی ٹریڈنگ کی حکمت عملیوں کے لیے متعدد تقاضے ہو سکتے ہیں، اور حکمت عملی کا فریم ورک اس لیے ڈیزائن کیا گیا ہے کہ اسے پھیلانا آسان ہو۔

  • پوزیشن کی نقل: پوزیشنز کو 1:1 سے نقل کیا جا سکتا ہے، یا انہیں مخصوص پیمانے کے پیرامیٹرز کے مطابق پیمانہ کیا جا سکتا ہے۔

  • ایکویٹی ریشو آرڈر والے اکاؤنٹ اور مندرجہ ذیل آرڈرز کے اکاؤنٹ کے درمیان ایکویٹی کا تناسب مندرجہ ذیل آرڈرز کے لیے پیرامیٹر کے طور پر خود بخود استعمال کیا جا سکتا ہے۔

  • پوزیشن سنکرونائزیشن اصل استعمال میں، مختلف وجوہات ہو سکتی ہیں جن کی وجہ سے آرڈر لینے والے اور آرڈر کے پیروکار کی پوزیشنیں مختلف ہوتی ہیں۔ سسٹم کو آرڈرز کی پیروی کرتے وقت کاپی کرنے والے اکاؤنٹ اور آرڈر لے جانے والے اکاؤنٹ کے درمیان فرق کا پتہ لگانے کے لیے ڈیزائن کیا جا سکتا ہے، اور خود بخود پوزیشنز کو ہم آہنگ کیا جا سکتا ہے۔

  • آرڈر کی دوبارہ کوشش کریں۔ آپ کاپی ٹریڈنگ کی حکمت عملی میں ناکام آرڈرز کے لیے دوبارہ کوششوں کی مخصوص تعداد بتا سکتے ہیں۔

  • بیک ٹیسٹنگ رینڈم ٹیسٹنگ کوڈ میںfunction randomTrade(symbol, amount)اس فنکشن کو بیک ٹیسٹنگ کے دوران رینڈم اوپننگ ٹیسٹ کے لیے استعمال کیا جاتا ہے تاکہ کاپی ٹریڈنگ اثر کا پتہ لگایا جا سکے۔

حکمت عملی کی بیک ٹیسٹنگ اور تصدیق

FMZ پر مبنی ایک ملٹی اکاؤنٹ کاپی ٹریڈنگ سسٹم بنانا جو میری زبان اور پائن حکمت عملی کی زبان کو سپورٹ کرتا ہے۔

پہلے ایکسچینج آبجیکٹ (آرڈر لینے والے) کے مطابق، بعد میں شامل کردہ ایکسچینج آبجیکٹ آرڈرز (پیروکاروں) کی پیروی کرتے ہیں۔

FMZ پر مبنی ایک ملٹی اکاؤنٹ کاپی ٹریڈنگ سسٹم بنانا جو میری زبان اور پائن حکمت عملی کی زبان کو سپورٹ کرتا ہے۔

ٹیسٹ میں، متعدد قسم کے کاپی ٹریڈنگ کی مانگ کی تصدیق کے لیے تصادفی طور پر تین قسم کے آرڈرز دیے گئے:

randomTrade("BTC_USDT.swap", 0.001)
randomTrade("ETH_USDT.swap", 0.02)
randomTrade("SOL_USDT.swap", 0.1)

حکمت عملی کا اشتراک

https://www.fmz.com/strategy/494950

توسیع اور اصلاح

  • پوزیشنز اور اکاؤنٹ کی معلومات جیسے ڈیٹا کے لیے نگرانی کے حل کو پھیلائیں۔
  • سبسکرائبرز پر کنٹرول بڑھانے کے لیے، آپ کاپی اکاؤنٹس کو موقوف اور ان سبسکرائب کرنے جیسے فنکشنز شامل کر سکتے ہیں۔
  • کاپی ٹریڈنگ حکمت عملی کے پیرامیٹرز کو متحرک طور پر اپ ڈیٹ کریں۔
  • امیر دستاویزی ڈیٹا اور معلوماتی ڈسپلے کو شامل اور پھیلائیں۔

END

آپ کا استقبال ہے کہ آپ پیغامات چھوڑیں اور موجد کوانٹیٹیو (FMZ.COM) لائبریری اور کمیونٹی میں گفتگو کریں۔ آپ مختلف مطالبات اور خیالات پیش کر سکتے ہیں۔ ایڈیٹر پیغامات کی بنیاد پر مزید قیمتی مواد پروڈکشن پلان کے ڈیزائن، وضاحتیں، اور تدریسی مواد کی اسکریننگ کرے گا۔

یہ مضمون صرف ایک نقطہ آغاز ہے۔ یہ ایک ابتدائی کاپی ٹریڈنگ حکمت عملی کے فریم ورک کو ڈیزائن کرنے کے لیے آبجیکٹ پر مبنی انداز اور مبصر موڈ کا استعمال کرتا ہے۔ مجھے امید ہے کہ یہ قارئین کے لیے حوالہ اور ترغیب فراہم کرے گا۔ آپ کے پڑھنے اور تعاون کے لیے آپ کا شکریہ۔