স্থায়ী চুক্তি গ্রিড কৌশল পরামিতি অপ্টিমাইজেশান বিস্তারিত ব্যাখ্যা

লেখক:লিডিয়া, তৈরিঃ ২০২৩-১২-১১ ১৫ঃ০৪ঃ২৫, আপডেটঃ ২০২৪-০১-০২ ২১ঃ২৪ঃ৩১

img

চিরস্থায়ী গ্রিড কৌশলটি এফএমজেড প্ল্যাটফর্মে একটি জনপ্রিয় ক্লাসিক কৌশল। স্পট গ্রিডের তুলনায়, মুদ্রার প্রয়োজন নেই এবং লিভারেজ যুক্ত করা যেতে পারে, যা স্পট গ্রিডের চেয়ে অনেক বেশি সুবিধাজনক। তবে, এফএমজেড কোয়ান্ট প্ল্যাটফর্মে সরাসরি ব্যাকটেস্ট করা সম্ভব না হওয়ায়, এটি মুদ্রা স্ক্রিনিং এবং প্যারামিটার অপ্টিমাইজেশান নির্ধারণের পক্ষে অনুকূল নয়। এই নিবন্ধে, আমরা ডেটা সংগ্রহ, ব্যাকটেস্টিং ফ্রেমওয়ার্ক, ব্যাকটেস্টিং ফাংশন, প্যারামিটার অপ্টিমাইজেশন ইত্যাদি সহ সম্পূর্ণ পাইথন ব্যাকটেস্টিং প্রক্রিয়াটি পরিচয় করিয়ে দেব। আপনি এটি নিজেকে juypter নোটবুকে চেষ্টা করতে পারেন।

তথ্য সংগ্রহ

সাধারণভাবে, কে-লাইন ডেটা ব্যবহার করা যথেষ্ট। নির্ভুলতার জন্য, কে-লাইন সময়কাল যত ছোট, তত ভাল। তবে, ব্যাকটেস্ট সময় এবং ডেটা ভলিউম ভারসাম্য বজায় রাখতে, এই নিবন্ধে, আমরা ব্যাকটেস্টিংয়ের জন্য গত দুই বছরের 5 মিনিট ডেটা ব্যবহার করি। চূড়ান্ত ডেটা ভলিউম 200,000 লাইন অতিক্রম করেছে। আমরা মুদ্রা হিসাবে DYDX নির্বাচন করি। অবশ্যই, নির্দিষ্ট মুদ্রা এবং কে-লাইন সময়কাল আপনার নিজস্ব আগ্রহ অনুযায়ী নির্বাচন করা যেতে পারে।

import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests, zipfile, io
%matplotlib inline

def GetKlines(symbol='BTC',start='2020-8-10',end='2021-8-10',period='1h'):
    Klines = []
    start_time = int(time.mktime(datetime.strptime(start, "%Y-%m-%d").timetuple()))*1000
    end_time = int(time.mktime(datetime.strptime(end, "%Y-%m-%d").timetuple()))*1000
    while start_time < end_time:
        res = requests.get('https://fapi.binance.com/fapi/v1/klines?symbol=%sUSDT&interval=%s&startTime=%s&limit=1000'%(symbol,period,start_time))
        res_list = res.json()
        Klines += res_list
        start_time = res_list[-1][0]
    return pd.DataFrame(Klines,columns=['time','open','high','low','close','amount','end_time','volume','count','buy_amount','buy_volume','null']).astype('float')

df = GetKlines(symbol='DYDX',start='2022-1-1',end='2023-12-7',period='5m')
df = df.drop_duplicates()

ব্যাকটেস্টিং ফ্রেমওয়ার্ক

ব্যাকটেস্টিংয়ের জন্য, আমরা সাধারণভাবে ব্যবহৃত ফ্রেমওয়ার্কটি বেছে নিচ্ছি যা একাধিক মুদ্রায় ইউএসডিটি চিরস্থায়ী চুক্তি সমর্থন করে, যা সহজ এবং ব্যবহার করা সহজ।

class Exchange:
    
    def __init__(self, trade_symbols, fee=0.0004, initial_balance=10000):
        self.initial_balance = initial_balance #Initial assets
        self.fee = fee
        self.trade_symbols = trade_symbols
        self.account = {'USDT':{'realised_profit':0, 'unrealised_profit':0, 'total':initial_balance, 'fee':0}}
        for symbol in trade_symbols:
            self.account[symbol] = {'amount':0, 'hold_price':0, 'value':0, 'price':0, 'realised_profit':0,'unrealised_profit':0,'fee':0}
            
    def Trade(self, symbol, direction, price, amount):
        
        cover_amount = 0 if direction*self.account[symbol]['amount'] >=0 else min(abs(self.account[symbol]['amount']), amount)
        open_amount = amount - cover_amount
        self.account['USDT']['realised_profit'] -= price*amount*self.fee #Deduction of handling fee
        self.account['USDT']['fee'] += price*amount*self.fee
        self.account[symbol]['fee'] += price*amount*self.fee

        if cover_amount > 0: #Close the position first.
            self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount  #Profits
            self.account[symbol]['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount
            
            self.account[symbol]['amount'] -= -direction*cover_amount
            self.account[symbol]['hold_price'] = 0 if self.account[symbol]['amount'] == 0 else self.account[symbol]['hold_price']
            
        if open_amount > 0:
            total_cost = self.account[symbol]['hold_price']*direction*self.account[symbol]['amount'] + price*open_amount
            total_amount = direction*self.account[symbol]['amount']+open_amount
            
            self.account[symbol]['hold_price'] = total_cost/total_amount
            self.account[symbol]['amount'] += direction*open_amount
                    
    
    def Buy(self, symbol, price, amount):
        self.Trade(symbol, 1, price, amount)
        
    def Sell(self, symbol, price, amount):
        self.Trade(symbol, -1, price, amount)
        
    def Update(self, close_price): #Updating of assets
        self.account['USDT']['unrealised_profit'] = 0
        for symbol in self.trade_symbols:
            self.account[symbol]['unrealised_profit'] = (close_price[symbol] - self.account[symbol]['hold_price'])*self.account[symbol]['amount']
            self.account[symbol]['price'] = close_price[symbol]
            self.account[symbol]['value'] = abs(self.account[symbol]['amount'])*close_price[symbol]
            self.account['USDT']['unrealised_profit'] += self.account[symbol]['unrealised_profit']
        self.account['USDT']['total'] = round(self.account['USDT']['realised_profit'] + self.initial_balance + self.account['USDT']['unrealised_profit'],6)

গ্রিড ব্যাকটেস্ট ফাংশন

গ্রিড কৌশলটির নীতিটি খুব সহজ। যখন দাম বেড়ে যায় তখন বিক্রয় করুন এবং যখন দাম কমে যায় তখন কিনুন। এটি বিশেষত তিনটি পরামিতি জড়িতঃ প্রাথমিক মূল্য, গ্রিড স্পেসিং এবং ট্রেডিং মান। ডিডব্লিউডিএক্সের বাজার ব্যাপকভাবে ওঠানামা করে। এটি প্রাথমিক সর্বনিম্ন 8.6U থেকে 1U এ নেমে আসে এবং তারপরে সাম্প্রতিক ষাঁড়ের বাজারে 3U এ ফিরে আসে। কৌশলটির ডিফল্ট প্রাথমিক মূল্য 8.6U, যা গ্রিড কৌশলটির জন্য খুব অনুকূল নয়, তবে ডিফল্ট পরামিতিগুলি ব্যাকটেস্ট করা হয়েছে। দুই বছরে 9200U এর মোট মুনাফা হয়েছিল এবং এই সময়ের মধ্যে 7500U এর ক্ষতি হয়েছিল।

img

symbol = 'DYDX'
value = 100
pct = 0.01

def Grid(fee=0.0002, value=100, pct=0.01, init = df.close[0]):
    e = Exchange([symbol], fee=0.0002, initial_balance=10000)
    init_price = init
    res_list = [] #For storing intermediate results
    for row in df.iterrows():
        kline = row[1] #To backtest a K-line will only generate one buy order or one sell order, which is not particularly accurate.
        buy_price = (value / pct - value) / ((value / pct) / init_price + e.account[symbol]['amount']) #The buy order price, as it is a pending order transaction, is also the final aggregated price
        sell_price = (value / pct + value) / ((value / pct) / init_price + e.account[symbol]['amount'])
        if kline.low < buy_price: #The lowest price of the K-line is lower than the current pending order price, the buy order is filled
            e.Buy(symbol,buy_price,value/buy_price)
        if kline.high > sell_price:
            e.Sell(symbol,sell_price,value/sell_price)
        e.Update({symbol:kline.close})
        res_list.append([kline.time, kline.close, e.account[symbol]['amount'], e.account['USDT']['total']-e.initial_balance,e.account['USDT']['fee'] ])
    res = pd.DataFrame(data=res_list, columns=['time','price','amount','profit', 'fee'])
    res.index = pd.to_datetime(res.time,unit='ms')
    return res

img

প্রাথমিক মূল্যের প্রভাব

প্রাথমিক মূল্যের সেটিং কৌশলটির প্রাথমিক অবস্থানের উপর প্রভাব ফেলে। ব্যাকটেস্টের জন্য ডিফল্ট প্রাথমিক মূল্য এখনই স্টার্টআপের প্রাথমিক মূল্য, অর্থাৎ স্টার্টআপের সময় কোনও অবস্থান অনুষ্ঠিত হয় না। এবং আমরা জানি যে গ্রিড কৌশলটি যখন দাম প্রাথমিক পর্যায়ে ফিরে আসে তখন সমস্ত লাভ অর্জন করবে, সুতরাং কৌশলটি চালু হওয়ার সময় ভবিষ্যতের বাজারটি সঠিকভাবে পূর্বাভাস দিতে পারে তবে আয় উল্লেখযোগ্যভাবে উন্নত হবে। এখানে, আমরা প্রাথমিক মূল্যটি 3U এ সেট করি এবং তারপরে ব্যাকটেস্ট করি। শেষ পর্যন্ত, সর্বাধিক ড্রডাউন ছিল 9200U, এবং চূড়ান্ত মুনাফা ছিল 13372U। চূড়ান্ত কৌশলটি অবস্থানগুলি ধরে রাখে না। মুনাফা হ'ল সমস্ত ওঠানামা মুনাফা, এবং ডিফল্ট পরামিতিগুলির মুনাফার মধ্যে পার্থক্যটি চূড়ান্ত মূল্যের ভুল বিচারের কারণে অবস্থানের ক্ষতি।

যাইহোক, যদি প্রাথমিক মূল্য 3U এ সেট করা হয়, তবে কৌশলটি শুরুতে শর্ট হবে এবং প্রচুর সংখ্যক শর্ট পজিশন ধরে রাখবে। এই উদাহরণে, 17,000 ইউ এর একটি শর্ট অর্ডার সরাসরি রাখা হয়, তাই এটি বৃহত্তর ঝুঁকিগুলির মুখোমুখি হয়।

img

গ্রিড স্পেসিং সেটিংস

গ্রিড স্পেসিং অপেক্ষমান অর্ডারগুলির মধ্যে দূরত্ব নির্ধারণ করে। স্পষ্টতই, স্পেসিং যত ছোট, লেনদেনগুলি তত ঘন ঘন হয়, একক লেনদেনের মুনাফা তত কম হয় এবং হ্যান্ডলিং ফি তত বেশি হয়। তবে, এটি লক্ষণীয় যে গ্রিড স্পেসিং যত ছোট হয় এবং গ্রিডের মান অপরিবর্তিত থাকে, যখন দাম পরিবর্তন হয়, তখন মোট অবস্থানগুলি বৃদ্ধি পাবে এবং সম্মুখীন ঝুঁকিগুলি সম্পূর্ণ আলাদা। অতএব, গ্রিড স্পেসিংয়ের প্রভাব ব্যাকটেস্ট করার জন্য, গ্রিডের মানটি রূপান্তর করা প্রয়োজন।

যেহেতু ব্যাকটেস্টটি 5m কে-লাইন ডেটা ব্যবহার করে এবং প্রতিটি কে-লাইন কেবল একবারই লেনদেন করা হয়, যা অবশ্যই অবাস্তব, বিশেষত যেহেতু ডিজিটাল মুদ্রার অস্থিরতা খুব বেশি। লাইভ ট্রেডিংয়ের তুলনায় একটি ছোট ব্যবধান ব্যাকটেস্টিংয়ে অনেক লেনদেন মিস করবে। কেবলমাত্র একটি বৃহত্তর ব্যবধানের রেফারেন্স মান থাকবে। এই ব্যাকটেস্টিং প্রক্রিয়াতে, উপসংহারগুলি সঠিক নয়। টিক-স্তরের অর্ডার প্রবাহ ডেটা ব্যাকটেস্টিংয়ের মাধ্যমে, সর্বোত্তম গ্রিড স্পেসিং 0.005-0.01 হওয়া উচিত।

for p in [0.0005, 0.001 ,0.002 ,0.005, 0.01, 0.02, 0.05]:
    res = Grid( fee=0.0002, value=value*p/0.01, pct=p, init =3)
    print(p, round(min(res['profit']),0), round(res['profit'][-1],0), round(res['fee'][-1],0))
    
0.0005 -8378.0 144.0 237.0
0.001 -9323.0 1031.0 465.0
0.002 -9306.0 3606.0 738.0
0.005 -9267.0 9457.0 781.0
0.01 -9228.0 13375.0 550.0
0.02 -9183.0 15212.0 309.0
0.05 -9037.0 16263.0 131.0

গ্রিড লেনদেনের মূল্য

যেমনটি পূর্বে উল্লেখ করা হয়েছে, যখন ওঠানামা একই হয়, হোল্ডিংয়ের মূল্য যত বেশি হবে, ঝুঁকি সমানুপাতিক। তবে, যতক্ষণ পর্যন্ত দ্রুত হ্রাস না হয়, মোট তহবিলের 1% এবং গ্রিড স্পেসিংয়ের 1% বেশিরভাগ বাজারের অবস্থার সাথে মোকাবিলা করতে সক্ষম হবে। এই ডিওয়াইডিএক্স উদাহরণে, প্রায় 90% হ্রাসও তরলীকরণ শুরু করে। তবে, এটি লক্ষ করা উচিত যে ডিওয়াইডিএক্স মূলত পড়ে। যখন গ্রিড কৌশলটি পড়ে যায়, তখন এটি সর্বাধিক 100% হ্রাস পাবে, যখন উত্থানের কোনও সীমা নেই, এবং ঝুঁকি অনেক বেশি। অতএব, গ্রিড কৌশল ব্যবহারকারীদের তাদের বিশ্বাসযোগ্য সম্ভাব্য মুদ্রার জন্য কেবল দীর্ঘ অবস্থানের মোডটি বেছে নেওয়ার পরামর্শ দেয়।


আরো