وسائل لوڈ ہو رہے ہیں... لوڈنگ...

ایف ایم زیڈ اپ گریڈ کے بعد فوری طور پر ایک یونیورسل ملٹی کرنسی ٹریڈنگ کی حکمت عملی کی تعمیر کیسے کریں

مصنف:FMZ~Lydia, تخلیق: 2024-10-08 10:01:41, تازہ کاری: 2024-11-05 17:47:28

img

پیش لفظ

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

ڈوکرز کو اس کی مکمل حمایت کرنے کے لئے 3.7 پر اپ گریڈ کرنے کی ضرورت ہے۔ ایف ایم زیڈ کوانٹ ٹریڈنگ پلیٹ فارم کے API دستاویزات میں API انٹرفیس کی نئی خصوصیات کے بارے میں معلومات کو اپ ڈیٹ کیا گیا ہے:

نحو رہنما:https://www.fmz.com/syntax-guideصارف گائیڈ:https://www.fmz.com/user-guide

درستگی حاصل کریں

فی الحال ، API میں درستگی حاصل کرنے کے لئے ایک متحد فنکشن ہے ، جو یہاں مثال کے طور پر دائمی معاہدے کا استعمال کرتے ہوئے متعارف کرایا گیا ہے۔

//Global variables store data. SYMBOLS represents the currency to be traded, and the format is "BTC,ETH,LTC". QUOTO is the base currency. Common perpetual contracts include USDT and USDC. INTERVAL represents the interval of the cycle.
var Info = { trade_symbols: SYMBOLS.split(","), base_coin: QUOTO, ticker: {}, order: {}, account: {}, precision: {}, 
            position: {}, time:{}, count:{}, interval:INTERVAL}
function InitInfo() {
    //Initialization strategy
    if (!IsVirtual() && Version() < 3.7){
        throw "FMZ platform upgrades API, you need to download the latest docker";
    }
    Info.account = {init_balance:0};
    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,
    };
    for (let i = 0; i < Info.trade_symbols.length; i++) {
        let symbol = Info.trade_symbols[i];
        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] =  {};
    }
}
//Get accuracy
function GetPrecision() {
    let exchange_info = exchange.GetMarkets();
    for (let pair in exchange_info) {
        let symbol = pair.split('_')[0]; //The format of perpetual contract trading pairs is BTC_USDT.swap
        if (Info.trade_symbols.indexOf(symbol) > -1 && pair.split('.')[0].endsWith(Info.base_coin) && pair.endsWith("swap")) {
            Info.precision[symbol].tick_size = exchange_info[pair].TickSize;
            Info.precision[symbol].amount_size = exchange_info[pair].AmountSize;
            Info.precision[symbol].price_precision = exchange_info[pair].PricePrecision
            Info.precision[symbol].amount_precision = exchange_info[pair].AmountPrecision
            Info.precision[symbol].min_qty = exchange_info[pair].MinQty
            Info.precision[symbol].max_qty = exchange_info[pair].MaxQty
            Info.precision[symbol].min_notional = exchange_info[pair].MinNotional
            Info.precision[symbol].ctVal = exchange_info[pair].CtVal; //Contract value, for example, 1 piece represents 0.01 coin
            if (exchange_info[pair].CtValCcy != symbol){ //The currency used to denominate the value. This does not include currency-based situations, for example, 1 note worth 100 USD.
                throw "No support for currency-based"
            }
        }
    }
}

ٹکرز حاصل کریں

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

function UpdateTicker() {
    //Updated prices
    let ticker = exchange.GetTickers();
    if (!ticker) {
        Log("Failed to obtain market information", GetLastError());
        return;
    }
    Info.time.update_ticker_time = Date.now();
    for (let i = 0; i < ticker.length; i++) {
        let symbol = ticker[i].Symbol.split('_')[0];
        if (!ticker[i].Symbol.split('.')[0].endsWith(Info.base_coin) || Info.trade_symbols.indexOf(symbol) < 0) {
            continue;
        }
        Info.ticker[symbol].ask = parseFloat(ticker[i].Sell);
        Info.ticker[symbol].bid = parseFloat(ticker[i].Buy);
        Info.ticker[symbol].last = parseFloat(ticker[i].Last);
    }
}

اکاؤنٹ پوزیشن کی معلومات حاصل کریں

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

function UpdateAccount() {
    //Update account
    if (Date.now() - Info.time.update_account_time < 60 * 1000) {
        return;
    }
    Info.time.update_account_time = Date.now();
    let account = exchange.GetAccount();
    if (account === null) {
        Log("Failed to update account");
        return;
    }
    Info.account.margin_used = _N(account.Equity - account.Balance, 2);
    Info.account.margin_balance = _N(account.Equity, 2); //Current balance
    Info.account.margin_free = _N(account.Balance, 2);
    Info.account.wallet_balance = _N(account.Equity - account.UPnL, 2);
    Info.account.unrealised_profit = _N(account.UPnL, 2);
    if (!Info.account.init_balance) {
        if (_G("init_balance") && _G("init_balance") > 0) {
            Info.account.init_balance = _N(_G("init_balance"), 2);
        } else {
            Info.account.init_balance = Info.account.margin_balance;
            _G("init_balance", Info.account.init_balance);
        }
    }
    Info.account.profit = _N(Info.account.margin_balance - Info.account.init_balance, 2);
    Info.account.profit_rate = _N((100 * Info.account.profit) / init_balance, 2);
}

function UpdatePosition() {
    let pos = exchange.GetPositions(Info.base_coin + ".swap");
    if (!pos) {
        Log("Timeout for updating position");
        return;
    }
    Info.time.update_pos_time = Date.now();
    let position_info = {};
    for (let symbol of Info.trade_symbols) {
        position_info[symbol] = {
            amount: 0,
            hold_price: 0,
            unrealised_profit: 0
        }; //Some exchanges have no positions and return empty
    }
    for (let k = 0; k < pos.length; k++) {
        let symbol = pos[k].Symbol.split("_")[0];
        if (!pos[k].Symbol.split(".")[0].endsWith(Info.base_coin) || Info.trade_symbols.indexOf(symbol) < 0) {
            continue;
        }
        if (position_info[symbol].amount != 0){
            throw "One-way position required";
        }
        position_info[symbol] = {
            amount: pos[k].Type == 0 ? pos[k].Amount * Info.precision[symbol].ctVal : -pos[k].Amount * Info.precision[symbol].ctVal,
            hold_price: pos[k].Price,
            unrealised_profit: pos[k].Profit
        };
    }
    Info.count = { long: 0, short: 0, total: 0, leverage: 0 };
    for (let symbol in position_info) {
        let deal_volume = Math.abs(position_info[symbol].amount - Info.position[symbol].amount);
        let direction = position_info[symbol].amount - Info.position[symbol].amount > 0 ? 1 : -1;
        if (deal_volume) {
            let deal_price = direction == 1 ? Info.order[symbol].buy.price : Info.order[symbol].sell.price;
            Log(
                symbol,
                "position update:",
                _N(Info.position[symbol].value, 1),
                " -> ",
                _N(position_info[symbol].amount * Info.ticker[symbol].last, 1),
                direction == 1 ? ", buy" : ", sell",
                ", transaction price:",
                deal_price,
                ", cost price:",
                _N(Info.position[symbol].hold_price, Info.precision[symbol].price_precision),
            );
        }
        Info.position[symbol].amount = position_info[symbol].amount;
        Info.position[symbol].hold_price = position_info[symbol].hold_price;
        Info.position[symbol].value = _N(Info.position[symbol].amount * Info.ticker[symbol].last, 2);
        Info.position[symbol].unrealised_profit = position_info[symbol].unrealised_profit;
        Info.count.long += Info.position[symbol].amount > 0 ? Math.abs(Info.position[symbol].value) : 0;
        Info.count.short += Info.position[symbol].amount < 0 ? Math.abs(Info.position[symbol].value) : 0;
    }
    Info.count.total = _N(Info.count.long + Info.count.short, 2);
    Info.count.leverage = _N(Info.count.total / Info.account.margin_balance, 2);
}

ٹرانزیکشن

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

function Order(symbol, direction, price, amount, msg) {
    let ret = null;
    let pair = symbol + "_" + Info.base_coin + ".swap"
    ret = exchange.CreateOrder(pair, direction, price,  amount, msg)
    if (ret) {
        Info.order[symbol][direction].id = ret;
        Info.order[symbol][direction].price = price;
    }else {
        Log(symbol, direction, price, amount, "abnormal order");
    }
}

function Trade(symbol, direction, price, amount, msg) {
    price = _N(price - (price % Info.precision[symbol].tick_size), Info.precision[symbol].price_precision);
    amount = amount / Info.precision[symbol].ctVal;
    amount = _N(amount - (amount % Info.precision[symbol].amount_size), Info.precision[symbol].amount_precision);
    amount = Info.precision[symbol].max_qty > 0 ? Math.min(amount, Info.precision[symbol].max_qty) : amount;
    let new_order = false;
    if (price > 0 && Math.abs(price - Info.order[symbol][direction].price) / price > 0.0001) { //The order will be cancelled only if there is a price difference between the two orders.
        new_order = true;
    }
    if (amount <= 0 || Info.order[symbol][direction].id == 0) { //The amount passed in is 0 to cancel the order
        new_order = true;
    }
    if (new_order) {
        if (Info.order[symbol][direction].id) { //Cancellation of existing order
            CancelOrder(symbol, direction, Info.order[symbol][direction].id);
            Info.order[symbol][direction].id = 0;
        }
        if ( //The delay is too high and the order is not placed
            Date.now() - Info.time.update_pos_time > 2 * Info.interval * 1000 ||
            Date.now() - Info.time.update_ticker_time > 2 * Info.interval * 1000 ||
        ) {
            return;
        }
        if (price * amount <= Info.precision[symbol].min_notional || amount < Info.precision[symbol].min_qty) {
            Log(symbol, "the order quantity is too small", price * amount);
            return;
        }
        Order(symbol, direction, price, amount, msg);
    }
}

حالت دکھانا

عام طور پر دو ٹیبلز دکھائی جاتی ہیں: اکاؤنٹ کی معلومات اور ٹریڈنگ جوڑی کی معلومات۔

function UpdateStatus() {
    if (Date.now() - Info.time.update_status_time < 4000) {
        return;
    }
    Info.time.update_status_time = Date.now();
    let table1 = {
        type: "table",
        title: "Account info",
        cols: [
            "Initial balance",
            "Wallet balance",
            "Margin balance",
            "Used margin",
            "Avaiable margin",
            "Total profit",
            "Profit rate",
            "Unrealised profit",
            "Total position",
            "Leverage-used",
            "Loop delay",
        ],
        rows: [
            [
                Info.account.init_balance,
                Info.account.wallet_balance,
                Info.account.margin_balance,
                Info.account.margin_used,
                Info.account.margin_free,
                Info.account.profit,
                Info.account.profit_rate + "%",
                _N(Info.account.unrealised_profit, 2),
                _N(Info.count.total, 2),
                Info.count.leverage,
                Info.time.loop_delay + "ms",
            ],
        ],
    };
    let table2 = {
        type: "table",
        title: "Trading pair information",
        cols: [
            "Symbol",
            "Direction",
            "Amount",
            "Position price",
            "Position value",
            "Current price",
            "Buy price",
            "Sell price",
            "Unrealised profit / loss",
        ],
        rows: [],
    };
    for (let i in Info.trade_symbols) {
        let symbol = Info.trade_symbols[i];
        table2.rows.push([
            symbol,
            Info.position[symbol].amount > 0 ? "LONG" : "SHORT",
            _N(Info.position[symbol].amount, Info.precision[symbol].amount_precision+2),
            _N(Info.position[symbol].hold_price, Info.precision[symbol].price_precision),
            _N(Info.position[symbol].value, 2),
            _N(Info.ticker[symbol].last, Info.precision[symbol].price_precision),
            Info.order[symbol].buy.price,
            Info.order[symbol].sell.price,
            _N(Info.position[symbol].unrealised_profit, 2),
        ]);
    }

    LogStatus(
        "Initial date: " + _D(new Date(Info.time.start_time)) + "\n",
        "`" + JSON.stringify(table1) + "`" + "\n" + "`" + JSON.stringify(table2) + "`\n",
        "Last execution time: " + _D() + "\n",
    );
    if (Date.now() - Info.time.update_profit_time > 5 * 60 * 1000) {
        UpdateAccount();
        LogProfit(_N(Info.account.profit, 3));
        Info.time.update_profit_time = Date.now();
    }
}

تجارتی منطق

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

function MakeOrder() {
    for (let i in Info.trade_symbols) {
        let symbol = Info.trade_symbols[i];
        let buy_price = Info.ticker[symbol].bid;
        let buy_amount = 50 / buy_price;
        if (Info.position[symbol].value < 2000){
            Trade(symbol, "buy", buy_price, buy_amount, symbol);
        }
    }
}

مین لوپ

function OnTick() {
    try {
        UpdateTicker();
        UpdatePosition();
        MakeOrder();
        UpdateStatus();
    } catch (error) {
        Log("Loop error: " + error);
    }
}

function main() {
    InitInfo();
    while (true) {
        let loop_start_time = Date.now();
        if (Date.now() - Info.time.last_loop_time > Info.interval * 1000) {
            OnTick();
            Info.time.last_loop_time = Date.now();
            Info.time.loop_delay = Date.now() - loop_start_time;
        }
        Sleep(5);
    }
}

خلاصہ

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


مزید