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

لیکس ریپر اسٹریٹیجی تجزیہ (۱)

مصنف:FMZ~Lydia, تخلیق: 2022-11-04 15:42:26, تازہ کاری: 2023-09-15 21:08:48

img

لیکس ریپر اسٹریٹیجی تجزیہ (۱)

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

[ٹرانسپلانٹنگ OKCoin LeeksReaper] حکمت عملی کا ماخذ کوڈ:

function LeeksReaper() {
    var self = {}
    self.numTick = 0
    self.lastTradeId = 0
    self.vol = 0
    self.askPrice = 0
    self.bidPrice = 0
    self.orderBook = {Asks:[], Bids:[]}
    self.prices = []
    self.tradeOrderId = 0
    self.p = 0.5
    self.account = null
    self.preCalc = 0
    self.preNet = 0

    self.updateTrades = function() {
        var trades = _C(exchange.GetTrades)
        if (self.prices.length == 0) {
            while (trades.length == 0) {
                trades = trades.concat(_C(exchange.GetTrades))
            }
            for (var i = 0; i < 15; i++) {
                self.prices[i] = trades[trades.length - 1].Price
            }
        }
        self.vol = 0.7 * self.vol + 0.3 * _.reduce(trades, function(mem, trade) {
            // Huobi not support trade.Id
            if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
                self.lastTradeId = Math.max(trade.Id == 0 ? trade.Time : trade.Id, self.lastTradeId)
                mem += trade.Amount
            }
            return mem
        }, 0)

    }
    self.updateOrderBook = function() {
        var orderBook = _C(exchange.GetDepth)
        self.orderBook = orderBook
        if (orderBook.Bids.length < 3 || orderBook.Asks.length < 3) {
            return
        }
        self.bidPrice = orderBook.Bids[0].Price * 0.618 + orderBook.Asks[0].Price * 0.382 + 0.01
        self.askPrice = orderBook.Bids[0].Price * 0.382 + orderBook.Asks[0].Price * 0.618 - 0.01
        self.prices.shift()
        self.prices.push(_N((orderBook.Bids[0].Price + orderBook.Asks[0].Price) * 0.35 +
            (orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
            (orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.05))
    }
    self.balanceAccount = function() {
        var account = exchange.GetAccount()
        if (!account) {
            return
        }
        self.account = account
        var now = new Date().getTime()
        if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {
            self.preCalc = now
            var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
            if (net != self.preNet) {
                self.preNet = net
                LogProfit(net)
            }
        }
        self.btc = account.Stocks
        self.cny = account.Balance
        self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
        var balanced = false
        
        if (self.p < 0.48) {
            Log("Start balance", self.p)
            self.cny -= 300
            if (self.orderBook.Bids.length >0) {
                exchange.Buy(self.orderBook.Bids[0].Price + 0.00, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.01, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.02, 0.01)
            }
        } else if (self.p > 0.52) {
            Log("Start balance", self.p)
            self.btc -= 0.03
            if (self.orderBook.Asks.length >0) {
                exchange.Sell(self.orderBook.Asks[0].Price - 0.00, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.01, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.02, 0.01)
            }
        }
        Sleep(BalanceTimeout)
        var orders = exchange.GetOrders()
        if (orders) {
            for (var i = 0; i < orders.length; i++) {
                if (orders[i].Id != self.tradeOrderId) {
                    exchange.CancelOrder(orders[i].Id)
                }
            }
        }
    }

    self.poll = function() {
        self.numTick++
        self.updateTrades()
        self.updateOrderBook()
        self.balanceAccount()
        
        var burstPrice = self.prices[self.prices.length-1] * BurstThresholdPct
        var bull = false
        var bear = false
        var tradeAmount = 0
        if (self.account) {
            LogStatus(self.account, 'Tick:', self.numTick, ', lastPrice:', self.prices[self.prices.length-1], ', burstPrice: ', burstPrice)
        }
        
        if (self.numTick > 2 && (
            self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -1)) > burstPrice ||
            self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -2)) > burstPrice && self.prices[self.prices.length-1] > self.prices[self.prices.length-2]
            )) {
            bull = true
            tradeAmount = self.cny / self.bidPrice * 0.99
        } else if (self.numTick > 2 && (
            self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -1)) < -burstPrice ||
            self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -2)) < -burstPrice && self.prices[self.prices.length-1] < self.prices[self.prices.length-2]
            )) {
            bear = true
            tradeAmount = self.btc
        }
        if (self.vol < BurstThresholdVol) {
            tradeAmount *= self.vol / BurstThresholdVol
        }
        
        if (self.numTick < 5) {
            tradeAmount *= 0.8
        }
        
        if (self.numTick < 10) {
            tradeAmount *= 0.8
        }
        
        if ((!bull && !bear) || tradeAmount < MinStock) {
            return
        }
        var tradePrice = bull ? self.bidPrice : self.askPrice
        while (tradeAmount >= MinStock) {
            var orderId = bull ? exchange.Buy(self.bidPrice, tradeAmount) : exchange.Sell(self.askPrice, tradeAmount)
            Sleep(200)
            if (orderId) {
                self.tradeOrderId = orderId
                var order = null
                while (true) {
                    order = exchange.GetOrder(orderId)
                    if (order) {
                        if (order.Status == ORDER_STATE_PENDING) {
                            exchange.CancelOrder(orderId)
                            Sleep(200)
                        } else {
                            break
                        }
                    }
                }
                self.tradeOrderId = 0
                tradeAmount -= order.DealAmount
                tradeAmount *= 0.9
                if (order.Status == ORDER_STATE_CANCELED) {
                    self.updateOrderBook()
                    while (bull && self.bidPrice - tradePrice > 0.1) {
                        tradeAmount *= 0.99
                        tradePrice += 0.1
                    }
                    while (bear && self.askPrice - tradePrice < -0.1) {
                        tradeAmount *= 0.99
                        tradePrice -= 0.1
                    }
                }
            }
        }
        self.numTick = 0
    }
    return self
}

function main() {
    var reaper = LeeksReaper()
    while (true) {
        reaper.poll()
        Sleep(TickInterval)
    }
}

حکمت عملی کا جائزہ

عام طور پر ، جب آپ کو مطالعہ کرنے کے لئے حکمت عملی مل جاتی ہے تو ، آپ کو پہلے پروگرام کی مجموعی ساخت پر ایک نظر ڈالنی چاہئے۔ حکمت عملی کا کوڈ بہت لمبا نہیں ہے ، جس میں 200 لائنوں سے بھی کم کوڈ ہے ، یہ بہت جامع ہے ، اور اصل حکمت عملی کو بہت زیادہ بحال کیا گیا ہے ، تقریبا ایک ہی ہے۔ حکمت عملی کا کوڈ اس سے چلتا ہےmain()فنکشن. مکمل حکمت عملی کوڈ، سوائےmain()، نامی ایک فنکشن ہےLeeksReaper().LeeksReaper()تقریب سمجھنے کے لئے بہت آسان ہے، یہ leeksreaper حکمت عملی منطق ماڈیول (ایک اعتراض) کے constructor کے طور پر سمجھا جا سکتا ہے. مختصر میں،LeeksReaper()ایک لیس ریپر ٹریڈنگ منطق کی تعمیر کے لئے ذمہ دار ہے.

کلیدی الفاظ:

img

· حکمت عملی کی پہلی لائنmainفنکشن:var reaper = LeeksReaper()، کوڈ ایک مقامی متغیر کا اعلان کرتا ہےreaperاور پھر ایک حکمت عملی منطق اعتراض ہے کہ ایک قدر تفویض کی تعمیر کے لئے LeeksReaper() تقریب بلاتا ہےreaper.

حکمت عملی کا اگلا قدمmainفنکشن:

while (true) {
    reaper.poll()
    Sleep(TickInterval)
}

درج کریںwhileلامتناہی لوپ اور عملدرآمد کی تقریب کو چلانے کے رکھنےpoll()کےreaperاعتراض،poll()فنکشن بالکل جہاں ٹریڈنگ کی حکمت عملی کا بنیادی منطق جھوٹ ہے اور پوری حکمت عملی پروگرام بار بار ٹریڈنگ منطق کو انجام دینے کے لئے شروع ہوتا ہے. اور لائن کے بارے میںSleep(TickInterval)، یہ سمجھنے میں آسان ہے، یہ ٹریڈنگ منطق کی گردش کی تعدد کو کنٹرول کرنے کے مقصد کے ساتھ، مجموعی طور پر ٹریڈنگ منطق کے ہر عمل کے بعد توقف کے وقت کو کنٹرول کرنے کے لئے ہے.

تجزیہLeeksReaper()تعمیر کار

دیکھو کہ کس طرحLeeksReaper()فنکشن ایک حکمت عملی منطقی اعتراض کی تعمیر کرتا ہے.

کےLeeksReaper()فنکشن خالی چیز کا اعلان کرکے شروع ہوتا ہے،var self = {}، اور عملدرآمد کے دورانLeeksReaper()تقریب آہستہ آہستہ اس خالی شے کے لئے کچھ طریقوں اور صفات کا اضافہ کریں گے، آخر میں اس شے کی تعمیر مکمل کرنے اور اسے واپس (یعنی، قدم کےmain()کے اندر کامvar reaper = LeeksReaper()، لوٹایا اعتراض کے لئے تفویض کیا جاتا ہےreaper).

صفات کو شامل کریںselfچیز اگلا، میں نے بہت سے صفات کو شامل کیاself. میں مندرجہ ذیل کے طور پر ہر ایک وصف کی وضاحت کریں گے، جو ان صفات اور متغیرات کے مقصد اور نیت کو تیزی سے سمجھ سکتے ہیں، حکمت عملی کی تفہیم کو آسان بنانے، اور کوڈ کو دیکھنے پر الجھن سے بچنے کے.

    self.numTick = 0         # It is used to record the number of transactions not triggered when the poll function is called. When the order is triggered and the order logic is executed, self.numTick is reset to 0
    self.lastTradeId = 0     # The transaction record ID of the order that has been transacted in the transaction market. This variable records the current transaction record ID of the market
    self.vol = 0             # Reference to the trading volume of each market inspection after weighted average calculation (market data is obtained once per loop, which can be interpreted as a time of market inspection)
    self.askPrice = 0        # The bill of lading price of the sales order can be understood as the price of the listing order after the strategy is calculated
    self.bidPrice = 0        # Purchase order bill of lading price
    self.orderBook = {Asks:[], Bids:[]}    # Record the currently obtained order book data, that is, depth data (sell one... sell n, buy one... buy n)
    self.prices = []                       # An array that records the prices on the time series after the calculation of the first three weighted averages in the order book, which means that each time the first three weighted averages of the order book are stored, they are placed in an array and used as a reference for subsequent strategy trading signals, so the variable name is prices, in plural form, indicating a set of prices
    self.tradeOrderId = 0    # Record the order ID after the current bill of lading is placed
    self.p = 0.5             # Position proportion: when the value of currency accounts for exactly half of the total asset value, the value is 0.5, that is, the equilibrium state
    self.account = null      # Record the account asset data, which is returned by the GetAccount() function
    self.preCalc = 0         # Record the timestamp of the last time when the revenue was calculated, in milliseconds, to control the frequency of triggering the execution of the revenue calculation code
    self.preNet = 0          # Record current return values

خود اشیاء کے لئے طریقوں کو شامل کریں

خود کو ان صفات کو شامل کرنے کے بعد، میں طریقوں کو شامل کرنے کے لئے شروعselfاعتراض تاکہ یہ اعتراض کچھ کام کر سکتا ہے اور کچھ افعال ہیں.

پہلا فنکشن نے مزید کہا:

    self.updateTrades = function() {
        var trades = _C(exchange.GetTrades)  # Call the FMZ encapsulated interface GetTrades to obtain the latest market transaction data
        if (self.prices.length == 0) {       # When self.prices.length == 0, the self.prices array needs to be filled with numeric values, which will be triggered only when the strategy starts running
            while (trades.length == 0) {     # If there is no recent transaction record in the market, the while loop will keep executing until the latest transaction data is available and update the trades variable
                trades = trades.concat(_C(exchange.GetTrades))   # concat is a method of JS array type, which is used to concatenate two arrays, here is to concatenate the "trades" array and the array data returned by "_C(exchange.GetTrades)" into one array
            }
            for (var i = 0; i < 15; i++) {   # Fill in data to self.prices, and fill in 15 pieces of latest transaction prices
                self.prices[i] = trades[trades.length - 1].Price
            }
        }
        self.vol = 0.7 * self.vol + 0.3 * _.reduce(trades, function(mem, trade) {  # _. Reduce function is used for iterative calculation to accumulate the amount of the latest transaction records
            // Huobi not support trade.Id
            if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
                self.lastTradeId = Math.max(trade.Id == 0 ? trade.Time : trade.Id, self.lastTradeId)
                mem += trade.Amount
            }
            return mem
        }, 0)

    }

فنکشنupdateTradesمارکیٹ ٹرانزیکشن کے تازہ ترین اعداد و شمار حاصل کرنے اور اعداد و شمار کی بنیاد پر کچھ حساب کتاب کرنے اور حکمت عملی کے بعد منطق میں استعمال کرنے کے لئے اسے ریکارڈ کرنے کے لئے ہے. لائن کی طرف سے لائن تبصرے میں نے اوپر کے کوڈ میں براہ راست لکھا. کے لئے_.reduce، کسی کو جو کوئی پروگرامنگ بنیادی سیکھنے الجھن میں ہو سکتا ہے. چلو اس کے بارے میں مختصر طور پر بات کرتے ہیں،_.reduceUnderscore.js لائبریری کا ایک فنکشن ہے۔ FMZJS حکمت عملی اس لائبریری کی حمایت کرتی ہے ، لہذا یہ تکرار حساب کتاب کے لئے بہت آسان ہے۔ Underscore.js ڈیٹا لنک (https://underscorejs.net/#reduce)

مطلب بھی بہت آسان ہے، مثال کے طور پر:

function main () {
   var arr = [1, 2, 3, 4]
   var sum = _.reduce(arr, function(ret, ele){
       ret += ele
       
       return ret
   }, 0)

   Log("sum:", sum)    # sum = 10
}

یہ ہے کہ، صف میں ہر نمبر جمع[1, 2, 3, 4]ہماری حکمت عملی پر واپس، ہم میں ہر ٹرانزیکشن ریکارڈ کے اعداد و شمار کے ٹریڈنگ حجم اقدار جمعtradesصف. تازہ ترین ٹرانزیکشن حجم کی کل حاصل کریںself.vol = 0.7 * self.vol + 0.3 * _.reduce (...)، یہاں ہم استعمال کرتے ہیں...کوڈ کو تبدیل کرنے کے لئے.self.volیہ بھی ایک وزن شدہ اوسط ہے۔ یعنی ، نئے پیدا کردہ تجارتی حجم کل کا 30٪ ہے ، اور آخری وزن شدہ تجارتی حجم 70٪ ہے۔ یہ تناسب حکمت عملی کے مصنف نے مصنوعی طور پر طے کیا تھا اور اس کا تعلق مارکیٹ کے قوانین سے ہوسکتا ہے۔ آپ کے سوال کے حوالے سے، اگر تازہ ترین ٹرانزیکشن ڈیٹا حاصل کرنے کے لئے انٹرفیس پرانے ڈیٹا کی نقل پر واپس آ گیا تو کیا ہوگا، پھر مجھے ملنے والا ڈیٹا غلط تھا، اور یہ معنی خیز نہیں ہوگا؟ فکر نہ کریں۔ اس مسئلے کو حکمت عملی کے ڈیزائن میں غور کیا گیا تھا، لہذا کوڈ میں ہے:

if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
    ...
}

فیصلہ۔ اس کا فیصلہ ٹرانزیکشن ریکارڈ میں ٹرانزیکشن آئی ڈی کی بنیاد پر کیا جاسکتا ہے۔ مجموعہ صرف اس وقت شروع ہوتا ہے جب آئی ڈی آخری ریکارڈ کی آئی ڈی سے زیادہ ہو یا اگر ایکسچینج انٹرفیس آئی ڈی فراہم نہیں کرتا ہے ، یعنی ،trade.Id == 0، ٹرانزیکشن ریکارڈ میں ٹائم اسٹیمپ کا استعمال کرتے ہوئے فیصلہ کرنے کے لئے. اس وقت،self.lastTradeIdٹرانزیکشن ریکارڈ کا ٹائم اسٹیمپ آئی ڈی کی بجائے اسٹور کرتا ہے۔

دوسرا فنکشن نے مزید کہا:

    self.updateOrderBook = function() {
        var orderBook = _C(exchange.GetDepth)
        self.orderBook = orderBook
        if (orderBook.Bids.length < 3 || orderBook.Asks.length < 3) {
            return
        }
        self.bidPrice = orderBook.Bids[0].Price * 0.618 + orderBook.Asks[0].Price * 0.382 + 0.01
        self.askPrice = orderBook.Bids[0].Price * 0.382 + orderBook.Asks[0].Price * 0.618 - 0.01
        self.prices.shift()
        self.prices.push(_N((orderBook.Bids[0].Price + orderBook.Asks[0].Price) * 0.35 +
            (orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
            (orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.05))
    }

اگلا، چلو فنکشن پر نظر ڈالیںupdateOrderBookفنکشن کے نام سے ، ہم دیکھ سکتے ہیں کہ اس کا استعمال آرڈر بک کو اپ ڈیٹ کرنے کے لئے کیا جاتا ہے۔ تاہم ، یہ صرف آرڈر بک کو اپ ڈیٹ نہیں کرتا ہے۔ فنکشن FMZ API فنکشن کو کال کرنا شروع کرتا ہے۔GetDepth()موجودہ مارکیٹ آرڈر بک کے اعداد و شمار حاصل کرنے کے لئے (ایک فروخت... فروخت ن ، ایک خریدنے... خریدنے ن) ، اور میں آرڈر بک کے اعداد و شمار کو ریکارڈself.orderBookاگلا، فیصلہ اگر آرڈر بک کے اعداد و شمار کی خریداری کے حکم اور فروخت کے حکم 3 سے کم ہیں، اگر ایسا ہے تو، غلط تقریب براہ راست واپس آ جائے گا.

اس کے بعد، دو اعداد و شمار کا حساب لگایا جاتا ہے:

· نوٹس آف کنسائنمنٹ کی قیمت کا حساب لگائیں سامان کی فہرست کی قیمت کا حساب بھی وزن شدہ اوسط طریقہ کار کا استعمال کرتے ہوئے کیا جاتا ہے۔ خریداری کے آرڈر کا حساب لگاتے وقت ، لین دین کی قیمت سے قریب ترین خریداری کی قیمت کو 61.8٪ (0.618) اور لین دین کی قیمت سے قریب ترین فروخت کی قیمت کو دیا جانے والا وزن 38.2٪ (0.382) ہے لیز کی قیمت کا حساب لگاتے وقت ، لین دین کی قیمت کے قریب فروخت کی قیمت کو بھی وہی وزن دیا جاتا ہے۔ کیوں 0.618 ہے ، اس کے بارے میں ، یہ ہوسکتا ہے کہ مصنف سنہری حصے کے تناسب کو ترجیح دیتا ہے۔ آخری قیمت (0.01) کے بارے میں ، یہ افتتاحی مرکز کی طرف تھوڑا سا آفسیٹ کرنا ہے۔

· ٹائم سیریز پر آرڈر بک کی پہلی تین سطحوں کی وزن شدہ اوسط قیمت کو اپ ڈیٹ کریں آرڈر بک میں خریداری اور فروخت کے آرڈر کی قیمتوں کی پہلی تین سطحوں کے لئے ، وزن شدہ اوسط کا حساب لگایا جاتا ہے۔ پہلی سطح کا وزن 0.7 ہے ، دوسری سطح کا وزن 0.2 ہے ، اور تیسری سطح کا وزن 0.1 ہے۔ کوئی کہہ سکتا ہے ، اوہ ، نہیں ، کوڈ میں 0.7 ، 0.2 ، 0.1 ہیں۔ آئیے حساب کو بڑھا دیں:

(Buy one+Sell one) * 0.35+(Buy two+Sell two) * 0.1+(Buy three+Sell three) * 0.05
->
(Buy one+sell one)/2 * 2 * 0.35+(Buy two+sell two)/2 * 2 * 0.1+(Buy three+sell three)/2 * 2 * 0.05
->
(Buy one+sell one)/2 * 0.7+(Buy two+sell two)/2 * 0.2+(Buy three+sell three)/2 * 0.1
->
Average price of the first level * 0.7+average price of the second level * 0.2+average price of the third level * 0.1

جیسا کہ ہم یہاں دیکھ سکتے ہیں، حتمی حساب قیمت اصل میں موجودہ مارکیٹ میں تیسری افتتاحی کے وسط کی قیمت کی پوزیشن کا جواب ہے. پھر صف کو اپ ڈیٹ کرنے کے لئے اس حساب قیمت کا استعمال کریںself.prices، سب سے پرانی اعداد و شمار میں سے ایک کو باہر نکالنے (کے ذریعےshift()فنکشن) اور اس میں تازہ ترین اعداد و شمار میں سے ایک کو اپ ڈیٹ کر رہا ہے ((کے ذریعےpush()تقریب، شفٹ اور دھکا افعال JS زبان صف اعتراض کے طریقوں ہیں، آپ تفصیلات کے لئے JS ڈیٹا کی جانچ پڑتال کر سکتے ہیں). اس طرح صف تشکیلself.prices، جو کہ وقت کی سیریز کے حکم کے ساتھ ڈیٹا کا ایک سلسلہ ہے.

تو چلو یہاں آرام کرتے ہیں، اور ہم آپ کو اگلے شمارہ میں دیکھیں گے ~


متعلقہ

مزید