एथेरियम पर अपना खुद का AI ट्रेडिंग एजेंट बनाएं
इस ट्यूटोरियल में आप सीखते हैं कि एक सरल AI ट्रेडिंग एजेंट कैसे बनाया जाए। यह एजेंट इन चरणों का उपयोग करके काम करता है:
- एक टोकन की वर्तमान और पिछली कीमतों को पढ़ें, साथ ही अन्य संभावित रूप से प्रासंगिक जानकारी
- इस जानकारी के साथ एक क्वेरी बनाएं, साथ ही यह समझाने के लिए पृष्ठभूमि की जानकारी दें कि यह कैसे प्रासंगिक हो सकता है
- क्वेरी सबमिट करें और एक अनुमानित मूल्य वापस प्राप्त करें
- सिफारिश के आधार पर ट्रेड करें
- प्रतीक्षा करें और दोहराएं
यह एजेंट प्रदर्शित करता है कि जानकारी कैसे पढ़ें, इसे एक ऐसी क्वेरी में अनुवाद करें जो एक उपयोगी उत्तर देती है, और उस उत्तर का उपयोग करें। ये सभी एक AI एजेंट के लिए आवश्यक कदम हैं। यह एजेंट Python में लागू किया गया है क्योंकि यह AI में इस्तेमाल होने वाली सबसे आम भाषा है।
ऐसा क्यों करें?
स्वचालित ट्रेडिंग एजेंट डेवलपर्स को एक ट्रेडिंग रणनीति चुनने और निष्पादित करने की अनुमति देते हैं। AI एजेंट अधिक जटिल और गतिशील ट्रेडिंग रणनीतियों की अनुमति देते हैं, संभावित रूप से उन सूचनाओं और एल्गोरिदम का उपयोग करते हैं जिनका उपयोग करने पर डेवलपर ने विचार भी नहीं किया है।
उपकरण
यह ट्यूटोरियल कोट्स और ट्रेडिंग के लिए Python (opens in a new tab), Web3 लाइब्रेरी (opens in a new tab), और Uniswap v3 (opens in a new tab) का उपयोग करता है।
Python क्यों?
AI के लिए सबसे व्यापक रूप से इस्तेमाल की जाने वाली भाषा Python (opens in a new tab) है, इसलिए हम इसे यहाँ इस्तेमाल करते हैं। अगर आप Python नहीं जानते हैं तो चिंता न करें। भाषा बहुत स्पष्ट है, और मैं ठीक से समझाऊंगा कि यह क्या करती है।
Web3 लाइब्रेरी (opens in a new tab) सबसे आम Python एथेरियम API है। इसका उपयोग करना बहुत आसान है।
ब्लॉकचेन पर ट्रेडिंग
कई वितरित एक्सचेंज (DEX) हैं जो आपको एथेरियम पर टोकन ट्रेड करने की सुविधा देते हैं। हालांकि, आर्बिट्रेज के कारण उनकी विनिमय दरें समान होती हैं।
Uniswap (opens in a new tab) एक व्यापक रूप से उपयोग किया जाने वाला DEX है जिसका उपयोग हम कोट्स (टोकन के सापेक्ष मान देखने के लिए) और ट्रेड्स दोनों के लिए कर सकते हैं।
OpenAI
एक बड़े भाषा मॉडल के लिए, मैंने OpenAI (opens in a new tab) के साथ शुरुआत करने का फैसला किया। इस ट्यूटोरियल में एप्लिकेशन को चलाने के लिए आपको API एक्सेस के लिए भुगतान करना होगा। $5 का न्यूनतम भुगतान पर्याप्त से अधिक है।
विकास, चरण-दर-चरण
विकास को सरल बनाने के लिए, हम चरणों में आगे बढ़ते हैं। प्रत्येक चरण GitHub में एक शाखा है।
शुरुआत करना
UNIX या Linux (जिसमें WSL (opens in a new tab) शामिल है) के तहत आरंभ करने के लिए कुछ चरण हैं
-
यदि आपके पास यह पहले से नहीं है, तो Python (opens in a new tab) डाउनलोड और इंस्टॉल करें।
-
GitHub रिपॉजिटरी को क्लोन करें।
1git clone https://github.com/qbzzt/260215-ai-agent.git -b 01-getting-started2cd 260215-ai-agent -
uv(opens in a new tab) इंस्टॉल करें। आपके सिस्टम पर कमांड अलग हो सकता है।1pipx install uv -
लाइब्रेरी डाउनलोड करें।
1uv sync -
वर्चुअल एनवायरनमेंट को सक्रिय करें।
1source .venv/bin/activate -
यह सत्यापित करने के लिए कि Python और Web3 सही ढंग से काम कर रहे हैं,
python3चलाएं और इसे यह प्रोग्राम प्रदान करें। आप इसे>>>प्रॉम्प्ट पर दर्ज कर सकते हैं; फ़ाइल बनाने की कोई आवश्यकता नहीं है।1from web3 import Web32MAINNET_URL = "https://eth.drpc.org"3w3 = Web3(Web3.HTTPProvider(MAINNET_URL))4w3.eth.block_number5quit()
ब्लॉकचेन से पढ़ना
अगला कदम ब्लॉकचेन से पढ़ना है। ऐसा करने के लिए, आपको 02-read-quote शाखा में बदलना होगा और फिर प्रोग्राम चलाने के लिए uv का उपयोग करना होगा।
1git checkout 02-read-quote2uv run agent.pyआपको Quote ऑब्जेक्ट की एक सूची मिलनी चाहिए, प्रत्येक में एक टाइमस्टैम्प, एक मूल्य और एसेट (वर्तमान में हमेशा WETH/USDC) होता है।
यहाँ पंक्ति-दर-पंक्ति स्पष्टीकरण है।
1from web3 import Web32from web3.contract import Contract3from decimal import Decimal, ROUND_HALF_UP4from dataclasses import dataclass5from datetime import datetime, timezone6from pprint import pprint7import time8import functools9import sysसभी दिखाएँहमें जिन पुस्तकालयों की आवश्यकता है, उन्हें आयात करें। उपयोग किए जाने पर उन्हें नीचे समझाया गया है।
1print = functools.partial(print, flush=True)Python के print को एक ऐसे संस्करण से बदल देता है जो हमेशा आउटपुट को तुरंत फ्लश करता है। यह एक लंबे समय तक चलने वाली स्क्रिप्ट में उपयोगी है क्योंकि हम स्थिति अपडेट या डिबगिंग आउटपुट के लिए इंतजार नहीं करना चाहते हैं।
1MAINNET_URL = "https://eth.drpc.org"मेननेट तक पहुंचने के लिए एक URL। आप नोड एज़ ए सर्विस से एक प्राप्त कर सकते हैं या चेनलिस्ट (opens in a new tab) में विज्ञापित लोगों में से एक का उपयोग कर सकते हैं।
1BLOCK_TIME_SECONDS = 122MINUTE_BLOCKS = int(60 / BLOCK_TIME_SECONDS)3HOUR_BLOCKS = MINUTE_BLOCKS * 604DAY_BLOCKS = HOUR_BLOCKS * 24एथेरियम मेननेट ब्लॉक आमतौर पर हर बारह सेकंड में होता है, इसलिए यह उन ब्लॉकों की संख्या है जिनकी हम एक समय अवधि में होने की उम्मीद करते हैं। ध्यान दें कि यह एक सटीक आंकड़ा नहीं है। जब ब्लॉक प्रस्तावक डाउन होता है, तो उस ब्लॉक को छोड़ दिया जाता है, और अगले ब्लॉक का समय 24 सेकंड होता है। यदि हम एक टाइमस्टैम्प के लिए सटीक ब्लॉक प्राप्त करना चाहते हैं, तो हम बाइनरी सर्च (opens in a new tab) का उपयोग करेंगे। हालांकि, यह हमारे उद्देश्यों के लिए काफी करीब है। भविष्य की भविष्यवाणी करना कोई सटीक विज्ञान नहीं है।
1CYCLE_BLOCKS = DAY_BLOCKSचक्र का आकार। हम प्रति चक्र एक बार कोट्स की समीक्षा करते हैं और अगले चक्र के अंत में मूल्य का अनुमान लगाने का प्रयास करते हैं।
1# उस पूल का पता जिसे हम पढ़ रहे हैं2WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")कोट मूल्य Uniswap 3 USDC/WETH पूल से पते 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 (opens in a new tab) पर लिए गए हैं। यह पता पहले से ही चेकसम प्रारूप में है, लेकिन कोड को पुन: प्रयोज्य बनाने के लिए Web3.to_checksum_address (opens in a new tab) का उपयोग करना बेहतर है।
1POOL_ABI = [2 { "name": "slot0", ... },3 { "name": "token0", ... },4 { "name": "token1", ... },5]67ERC20_ABI = [8 { "name": "symbol", ... },9 { "name": "decimals", ... }10]सभी दिखाएँये उन दो कॉन्ट्रैक्ट के लिए ABI (opens in a new tab) हैं जिनसे हमें संपर्क करने की आवश्यकता है। कोड को संक्षिप्त रखने के लिए, हम केवल उन कार्यों को शामिल करते हैं जिन्हें हमें कॉल करने की आवश्यकता है।
1w3 = Web3(Web3.HTTPProvider(MAINNET_URL))Web3 (opens in a new tab) लाइब्रेरी शुरू करें और एथेरियम नोड से कनेक्ट करें।
1@dataclass(frozen=True)2class ERC20Token:3 address: str4 symbol: str5 decimals: int6 contract: Contractयह Python में डेटा क्लास बनाने का एक तरीका है। Contract (opens in a new tab) डेटा प्रकार का उपयोग कॉन्ट्रैक्ट से कनेक्ट करने के लिए किया जाता है। (frozen=True) पर ध्यान दें। Python में बूलियन (opens in a new tab) को True या False, कैपिटलाइज़्ड के रूप में परिभाषित किया गया है। यह डेटा क्लास frozen है, जिसका अर्थ है कि फ़ील्ड को संशोधित नहीं किया जा सकता है।
इंडेंटेशन पर ध्यान दें। C-व्युत्पन्न भाषाओं (opens in a new tab) के विपरीत, Python ब्लॉक को दर्शाने के लिए इंडेंटेशन का उपयोग करता है। Python इंटरप्रेटर जानता है कि निम्नलिखित परिभाषा इस डेटा क्लास का हिस्सा नहीं है क्योंकि यह डेटा क्लास फ़ील्ड के समान इंडेंटेशन पर शुरू नहीं होती है।
1@dataclass(frozen=True)2class PoolInfo:3 address: str4 token0: ERC20Token5 token1: ERC20Token6 contract: Contract7 asset: str8 decimal_factor: Decimal = 1Decimal (opens in a new tab) प्रकार का उपयोग दशमलव भिन्नों को सटीक रूप से संभालने के लिए किया जाता है।
1 def get_price(self, block: int) -> Decimal:यह Python में फ़ंक्शन को परिभाषित करने का तरीका है। परिभाषा यह दिखाने के लिए इंडेंट की गई है कि यह अभी भी PoolInfo का हिस्सा है।
डेटा क्लास का हिस्सा होने वाले फ़ंक्शन में पहला पैरामीटर हमेशा self होता है, जो डेटा क्लास इंस्टेंस है जिसे यहाँ कॉल किया गया है। यहाँ एक और पैरामीटर है, ब्लॉक नंबर।
1 assert block <= w3.eth.block_number, "Block is in the future"अगर हम भविष्य पढ़ सकते, तो हमें ट्रेडिंग के लिए AI की ज़रूरत नहीं होती।
1 sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0])Web3 से EVM पर किसी फ़ंक्शन को कॉल करने का सिंटैक्स यह है: <contract object>.functions.<function name>"().call(<parameters>)। पैरामीटर EVM फ़ंक्शन के पैरामीटर हो सकते हैं (यदि कोई हो; यहाँ नहीं हैं) या ब्लॉकचेन व्यवहार को संशोधित करने के लिए नामित पैरामीटर (opens in a new tab) हो सकते हैं। यहाँ हम एक, block_identifier, का उपयोग ब्लॉक नंबर को निर्दिष्ट करने के लिए करते हैं जिसमें हम चलाना चाहते हैं।
परिणाम यह स्ट्रक्ट, ऐरे रूप में (opens in a new tab) है। पहला मान दो टोकन के बीच विनिमय दर का एक कार्य है।
1 raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2ऑन-चेन गणनाओं को कम करने के लिए, Uniswap v3 वास्तविक विनिमय कारक को संग्रहीत नहीं करता है, बल्कि इसके वर्गमूल को संग्रहीत करता है। क्योंकि EVM फ्लोटिंग पॉइंट गणित या भिन्नों का समर्थन नहीं करता है, वास्तविक मान के बजाय, प्रतिक्रिया है
1 # (टोकन1 प्रति टोकन0)2 return 1/(raw_price * self.decimal_factor)जो कच्चा मूल्य हमें मिलता है, वह प्रत्येक token1 के लिए मिलने वाले token0 की संख्या है। हमारे पूल में token0 USDC (एक अमेरिकी डॉलर के समान मूल्य वाला स्थिर मुद्रा) है और token1 WETH (opens in a new tab) है। जो मूल्य हम वास्तव में चाहते हैं वह प्रति WETH डॉलर की संख्या है, न कि इसका व्युत्क्रम।
दशमलव कारक दो टोकन के दशमलव कारकों (opens in a new tab) के बीच का अनुपात है।
1@dataclass(frozen=True)2class Quote:3 timestamp: str4 price: Decimal5 asset: strयह डेटा क्लास एक उद्धरण का प्रतिनिधित्व करता है: किसी दिए गए समय पर किसी विशिष्ट संपत्ति की कीमत। इस बिंदु पर, एसेट फ़ील्ड अप्रासंगिक है क्योंकि हम एक ही पूल का उपयोग करते हैं और इसलिए हमारे पास एक ही एसेट है। हालांकि, हम बाद में और एसेट्स जोड़ेंगे।
1def read_token(address: str) -> ERC20Token:2 token = w3.eth.contract(address=address, abi=ERC20_ABI)3 symbol = token.functions.symbol().call()4 decimals = token.functions.decimals().call()56 return ERC20Token(7 address=address,8 symbol=symbol,9 decimals=decimals,10 contract=token11 )सभी दिखाएँयह फ़ंक्शन एक पता लेता है और उस पते पर टोकन अनुबंध के बारे में जानकारी देता है। एक नया Web3 Contract (opens in a new tab) बनाने के लिए, हम w3.eth.contract को पता और ABI प्रदान करते हैं।
1def read_pool(address: str) -> PoolInfo:2 pool_contract = w3.eth.contract(address=address, abi=POOL_ABI)3 token0Address = pool_contract.functions.token0().call()4 token1Address = pool_contract.functions.token1().call()5 token0 = read_token(token0Address)6 token1 = read_token(token1Address)78 return PoolInfo(9 address=address,10 asset=f"{token1.symbol}/{token0.symbol}",11 token0=token0,12 token1=token1,13 contract=pool_contract,14 decimal_factor=Decimal(10) ** Decimal(token0.decimals - token1.decimals)15 )सभी दिखाएँयह फ़ंक्शन एक विशिष्ट पूल (opens in a new tab) के बारे में हमें जो कुछ भी चाहिए वह सब कुछ देता है। सिंटैक्स f"<string>" एक फ़ॉर्मेटेड स्ट्रिंग (opens in a new tab) है।
1def get_quote(pool: PoolInfo, block_number: int = None) -> Quote:Quote ऑब्जेक्ट प्राप्त करें। block_number का डिफ़ॉल्ट मान None (कोई मान नहीं) है।
1 if block_number is None:2 block_number = w3.eth.block_numberयदि कोई ब्लॉक नंबर निर्दिष्ट नहीं किया गया था, तो w3.eth.block_number का उपयोग करें, जो नवीनतम ब्लॉक नंबर है। यह एक if स्टेटमेंट (opens in a new tab) का सिंटैक्स है।
ऐसा लग सकता है कि डिफ़ॉल्ट को w3.eth.block_number पर सेट करना बेहतर होता, लेकिन यह अच्छी तरह से काम नहीं करता क्योंकि यह फ़ंक्शन को परिभाषित करते समय ब्लॉक नंबर होगा। एक लंबे समय तक चलने वाले एजेंट में, यह एक समस्या होगी।
1 block = w3.eth.get_block(block_number)2 price = pool.get_price(block_number)3 return Quote(4 timestamp=datetime.fromtimestamp(block.timestamp, timezone.utc).isoformat(),5 price=price.quantize(Decimal("0.01")),6 asset=pool.asset7 )इसे मनुष्यों और बड़े भाषा मॉडल (LLM) के लिए पठनीय प्रारूप में प्रारूपित करने के लिए datetime लाइब्रेरी (opens in a new tab) का उपयोग करें। मान को दो दशमलव स्थानों तक गोल करने के लिए Decimal.quantize (opens in a new tab) का उपयोग करें।
1def get_quotes(pool: PoolInfo, start_block: int, end_block: int, step: int) -> list[Quote]:Python में आप एक सूची (opens in a new tab) परिभाषित करते हैं जिसमें list[<type>] का उपयोग करके केवल एक विशिष्ट प्रकार हो सकता है।
1 quotes = []2 for block in range(start_block, end_block + 1, step):Python में एक for लूप (opens in a new tab) आमतौर पर एक सूची पर पुनरावृति करता है। उद्धरणों को खोजने के लिए ब्लॉक नंबरों की सूची रेंज (opens in a new tab) से आती है।
1 quote = get_quote(pool, block)2 quotes.append(quote)3 return quotesप्रत्येक ब्लॉक नंबर के लिए, एक Quote ऑब्जेक्ट प्राप्त करें और इसे quotes सूची में जोड़ें। फिर उस सूची को वापस करें।
1pool = read_pool(WETHUSDC_ADDRESS)2quotes = get_quotes(3 pool,4 w3.eth.block_number - 12*CYCLE_BLOCKS,5 w3.eth.block_number,6 CYCLE_BLOCKS7)89pprint(quotes)सभी दिखाएँयह स्क्रिप्ट का मुख्य कोड है। पूल की जानकारी पढ़ें, बारह उद्धरण प्राप्त करें, और उन्हें pprint (opens in a new tab) करें।
एक प्रॉम्प्ट बनाना
अगला, हमें उद्धरणों की इस सूची को एक एलएलएम के लिए एक संकेत में बदलने और भविष्य के अपेक्षित मूल्य प्राप्त करने की आवश्यकता है।
1git checkout 03-create-prompt2uv run agent.pyआउटपुट अब LLM के लिए एक संकेत होने जा रहा है, इसके समान:
1इन उद्धरणों को देखते हुए:2एसेट: WETH/USDC3 2026-01-20T16:34 3016.214 .5 .6 .7 2026-02-01T17:49 2299.1089एसेट: WBTC/WETH10 2026-01-20T16:34 29.8411 .12 .13 .14 2026-02-01T17:50 33.46151617समय 2026-02-02T17:56 पर WETH/USDC का मूल्य क्या होने की उम्मीद करेंगे?1819अपना उत्तर दो दशमलव स्थानों पर गोल की गई एक ही संख्या के रूप में प्रदान करें,20बिना किसी अन्य पाठ के।सभी दिखाएँध्यान दें कि यहां दो संपत्तियों, WETH/USDC और WBTC/WETH के लिए उद्धरण हैं। किसी अन्य संपत्ति से उद्धरण जोड़ने से भविष्यवाणी की सटीकता में सुधार हो सकता है।
प्रॉम्प्ट कैसा दिखता है
इस प्रॉम्प्ट में तीन खंड हैं, जो एलएलएम प्रॉम्प्ट में बहुत आम हैं।
-
जानकारी। LLMs के पास अपने प्रशिक्षण से बहुत सारी जानकारी होती है, लेकिन उनके पास आमतौर पर नवीनतम जानकारी नहीं होती है। यही कारण है कि हमें यहां नवीनतम उद्धरण प्राप्त करने की आवश्यकता है। प्रॉम्प्ट में जानकारी जोड़ने को पुनर्प्राप्ति संवर्धित पीढ़ी (RAG) (opens in a new tab) कहा जाता है।
-
वास्तविक प्रश्न। यही हम जानना चाहते हैं।
-
आउटपुट स्वरूपण निर्देश। आम तौर पर, एक LLM हमें इस बात के स्पष्टीकरण के साथ एक अनुमान देगा कि यह इस पर कैसे पहुंचा। यह मनुष्यों के लिए बेहतर है, लेकिन एक कंप्यूटर प्रोग्राम को केवल बॉटम लाइन की आवश्यकता होती है।
कोड स्पष्टीकरण
यहाँ नया कोड है।
1from datetime import datetime, timezone, timedeltaहमें LLM को उस समय के बारे में बताने की आवश्यकता है जिसके लिए हम एक अनुमान चाहते हैं। भविष्य में "n मिनट/घंटे/दिन" का समय प्राप्त करने के लिए, हम timedelta वर्ग (opens in a new tab) का उपयोग करते हैं।
1# उन पूलों के पते जिन्हें हम पढ़ रहे हैं2WETHUSDC_ADDRESS = Web3.to_checksum_address("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")3WETHWBTC_ADDRESS = Web3.to_checksum_address("0xCBCdF9626bC03E24f779434178A73a0B4bad62eD")हमें दो पूल पढ़ने हैं।
1@dataclass(frozen=True)2class PoolInfo:3 .4 .5 .6 reverse: bool = False78 def get_price(self, block: int) -> Decimal:9 assert block <= w3.eth.block_number, "Block is in the future"10 sqrt_price_x96 = Decimal(self.contract.functions.slot0().call(block_identifier=block)[0])11 raw_price = (sqrt_price_x96 / Decimal(2**96)) ** 2 # (token1 per token0)12 if self.reverse:13 return 1/(raw_price * self.decimal_factor)14 else:15 return raw_price * self.decimal_factorसभी दिखाएँWETH/USDC पूल में, हम जानना चाहते हैं कि token1 (WETH) में से एक को खरीदने के लिए हमें कितने token0 (USDC) की आवश्यकता है। WETH/WBTC पूल में, हम जानना चाहते हैं कि एक token0 (WBTC, जो रैप्ड बिटकॉइन है) खरीदने के लिए हमें कितने token1 (WETH) की आवश्यकता है। हमें यह ट्रैक करने की आवश्यकता है कि क्या पूल के अनुपात को उलटने की आवश्यकता है।
1def read_pool(address: str, reverse: bool = False) -> PoolInfo:2 .3 .4 .56 return PoolInfo(7 .8 .9 .1011 asset= f"{token1.symbol}/{token0.symbol}" if reverse else f"{token0.symbol}/{token1.symbol}",12 reverse=reverse13 )सभी दिखाएँयह जानने के लिए कि क्या किसी पूल को उलटने की आवश्यकता है, हम इसे read_pool में इनपुट के रूप में प्राप्त करते हैं। इसके अलावा, संपत्ति प्रतीक को सही ढंग से स्थापित करने की आवश्यकता है।
वाक्यविन्यास <a> if <b> else <c> टर्नेरी कंडीशनल ऑपरेटर (opens in a new tab) के पायथन समकक्ष है, जो सी-व्युत्पन्न भाषा में <b> ? <a> : <c> होगा।
1def format_quotes(quotes: list[Quote]) -> str:2 result = f"Asset: {quotes[0].asset}\n"3 for quote in quotes:4 result += f"\t{quote.timestamp[0:16]} {quote.price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)}\n"5 return resultयह फ़ंक्शन एक स्ट्रिंग बनाता है जो Quote ऑब्जेक्ट की एक सूची को प्रारूपित करता है, यह मानते हुए कि वे सभी एक ही संपत्ति पर लागू होते हैं।
1def make_prompt(quotes: list[list[Quote]], expected_time: str, asset: str) -> str:2 return f"""Python में मल्टी-लाइन स्ट्रिंग लिटरल (opens in a new tab) """ के रूप में लिखे जाते हैं .... """.
1इन उद्धरणों को देखते हुए:2{3 functools.reduce(lambda acc, q: acc + '\n' + q,4 map(lambda q: format_quotes(q), quotes))5}यहां, हम प्रत्येक उद्धरण सूची के लिए format_quotes के साथ एक स्ट्रिंग उत्पन्न करने के लिए MapReduce (opens in a new tab) पैटर्न का उपयोग करते हैं, फिर उन्हें प्रॉम्प्ट में उपयोग के लिए एक एकल स्ट्रिंग में कम करते हैं।
1{asset} का मान समय {expected_time} पर क्या होने की उम्मीद करेंगे?23अपना उत्तर दो दशमलव स्थानों पर गोल की गई एक ही संख्या के रूप में प्रदान करें,4बिना किसी अन्य पाठ के।5 """प्रॉम्प्ट का बाकी हिस्सा अपेक्षित है।
1wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True)2wethusdc_quotes = get_quotes(3 wethusdc_pool,4 w3.eth.block_number - 12*CYCLE_BLOCKS,5 w3.eth.block_number,6 CYCLE_BLOCKS,7)89wethwbtc_pool = read_pool(WETHWBTC_ADDRESS)10wethwbtc_quotes = get_quotes(11 wethwbtc_pool,12 w3.eth.block_number - 12*CYCLE_BLOCKS,13 w3.eth.block_number,14 CYCLE_BLOCKS15)सभी दिखाएँदो पूलों की समीक्षा करें और दोनों से उद्धरण प्राप्त करें।
1future_time = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()[0:16]23print(make_prompt(wethusdc_quotes + wethwbtc_quotes, future_time, wethusdc_pool.asset))भविष्य का समय बिंदु निर्धारित करें जिसके लिए हम अनुमान चाहते हैं, और प्रॉम्प्ट बनाएं।
एक LLM के साथ इंटरफेसिंग
अगला, हम एक वास्तविक एलएलएम को संकेत देते हैं और एक अपेक्षित भविष्य मूल्य प्राप्त करते हैं। मैंने यह प्रोग्राम OpenAI का उपयोग करके लिखा है, इसलिए यदि आप किसी भिन्न प्रदाता का उपयोग करना चाहते हैं, तो आपको इसे समायोजित करने की आवश्यकता होगी।
-
OpenAI खाता (opens in a new tab) प्राप्त करें
-
खाता फंड करें (opens in a new tab)—लिखने के समय न्यूनतम राशि $5 है
-
कमांड लाइन में, एपीआई कुंजी को निर्यात करें ताकि आपका प्रोग्राम इसका उपयोग कर सके
1export OPENAI_API_KEY=sk-<बाकी कुंजी यहाँ जाती है> -
एजेंट को चेकआउट करें और चलाएं
1git checkout 04-interface-llm2uv run agent.py
यहाँ नया कोड है।
1from openai import OpenAI23open_ai = OpenAI() # क्लाइंट OPENAI_API_KEY पर्यावरण चर पढ़ता हैOpenAI API को आयात करें और इंस्टैंशिएट करें।
1response = open_ai.chat.completions.create(2 model="gpt-4-turbo",3 messages=[4 {"role": "user", "content": prompt}5 ],6 temperature=0.0,7 max_tokens=16,8)प्रतिक्रिया बनाने के लिए OpenAI API (open_ai.chat.completions.create) को कॉल करें।
1expected_price = Decimal(response.choices[0].message.content.strip())2current_price = wethusdc_quotes[-1].price34print ("वर्तमान मूल्य:", wethusdc_quotes[-1].price)5print(f"भविष्य में {future_time}, अपेक्षित मूल्य: {expected_price} USD")67if (expected_price > current_price):8 print(f"खरीदें, मुझे उम्मीद है कि कीमत {expected_price - current_price} USD तक बढ़ जाएगी")9else:10 print(f"बेचें, मुझे उम्मीद है कि कीमत {current_price - expected_price} USD तक गिर जाएगी")सभी दिखाएँकीमत का आउटपुट दें और खरीदें या बेचें की सिफारिश करें।
भविष्यवाणियों का परीक्षण
अब जब हम भविष्यवाणियां उत्पन्न कर सकते हैं, तो हम यह आकलन करने के लिए ऐतिहासिक डेटा का भी उपयोग कर सकते हैं कि क्या हम उपयोगी भविष्यवाणियां उत्पन्न करते हैं।
1uv run test-predictor.pyअपेक्षित परिणाम इसके समान है:
12026-01-05T19:50 के लिए भविष्यवाणी: भविष्यवाणी 3138.93 USD, वास्तविक 3218.92 USD, त्रुटि 79.99 USD22026-01-06T19:56 के लिए भविष्यवाणी: भविष्यवाणी 3243.39 USD, वास्तविक 3221.08 USD, त्रुटि 22.31 USD32026-01-07T20:02 के लिए भविष्यवाणी: भविष्यवाणी 3223.24 USD, वास्तविक 3146.89 USD, त्रुटि 76.35 USD42026-01-08T20:11 के लिए भविष्यवाणी: भविष्यवाणी 3150.47 USD, वास्तविक 3092.04 USD, त्रुटि 58.43 USD5.6.7.82026-01-31T22:33 के लिए भविष्यवाणी: भविष्यवाणी 2637.73 USD, वास्तविक 2417.77 USD, त्रुटि 219.96 USD92026-02-01T22:41 के लिए भविष्यवाणी: भविष्यवाणी 2381.70 USD, वास्तविक 2318.84 USD, त्रुटि 62.86 USD102026-02-02T22:49 के लिए भविष्यवाणी: भविष्यवाणी 2234.91 USD, वास्तविक 2349.28 USD, त्रुटि 114.37 USD1129 भविष्यवाणियों पर औसत भविष्यवाणी त्रुटि: 83.87103448275862068965517241 USD12प्रति अनुशंसा औसत परिवर्तन: 4.787931034482758620689655172 USD13परिवर्तनों का मानक विचरण: 104.42 USD14लाभदायक दिन: 51.72%15नुकसान वाले दिन: 48.28%सभी दिखाएँपरीक्षक का अधिकांश भाग एजेंट के समान है, लेकिन यहां वे हिस्से हैं जो नए या संशोधित हैं।
1CYCLES_FOR_TEST = 40 # बैकटेस्ट के लिए, हम कितने चक्रों का परीक्षण करते हैं23# बहुत सारे उद्धरण प्राप्त करें4wethusdc_pool = read_pool(WETHUSDC_ADDRESS, True)5wethusdc_quotes = get_quotes(6 wethusdc_pool,7 w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST,8 w3.eth.block_number,9 CYCLE_BLOCKS,10)1112wethwbtc_pool = read_pool(WETHWBTC_ADDRESS)13wethwbtc_quotes = get_quotes(14 wethwbtc_pool,15 w3.eth.block_number - CYCLE_BLOCKS*CYCLES_FOR_TEST,16 w3.eth.block_number,17 CYCLE_BLOCKS18)सभी दिखाएँहम CYCLES_FOR_TEST (यहाँ 40 के रूप में निर्दिष्ट) दिन पीछे देखते हैं।
1# भविष्यवाणियां बनाएं और उन्हें वास्तविक इतिहास के विरुद्ध जांचें23total_error = Decimal(0)4changes = []दो प्रकार की त्रुटियां हैं जिनमें हम रुचि रखते हैं। पहला, टोटल_एरर, भविष्यवक्ता द्वारा की गई त्रुटियों का योग है।
दूसरा, परिवर्तन को समझने के लिए, हमें एजेंट के उद्देश्य को याद रखने की आवश्यकता है। यह WETH/USDC अनुपात (ETH मूल्य) की भविष्यवाणी करने के लिए नहीं है। यह बेचने और खरीदने की सिफारिशें जारी करने के लिए है। यदि कीमत वर्तमान में $2000 है और यह कल $2010 की भविष्यवाणी करता है, तो हमें कोई आपत्ति नहीं है यदि वास्तविक परिणाम $2020 है और हम अतिरिक्त पैसा कमाते हैं। लेकिन हमें _ आपत्ति है _ यदि इसने $2010 की भविष्यवाणी की, और उस सिफारिश के आधार पर ETH खरीदा, और कीमत $1990 तक गिर जाती है।
1for index in range(0,len(wethusdc_quotes)-CYCLES_BACK):हम केवल उन मामलों को देख सकते हैं जहां पूरा इतिहास (भविष्यवाणी के लिए उपयोग किए गए मान और वास्तविक-विश्व मान जिसके साथ इसकी तुलना की जानी है) उपलब्ध है। इसका मतलब है कि सबसे नया मामला वह होना चाहिए जो CYCLES_BACK पहले शुरू हुआ था।
1 wethusdc_slice = wethusdc_quotes[index:index+CYCLES_BACK]2 wethwbtc_slice = wethwbtc_quotes[index:index+CYCLES_BACK]एजेंट द्वारा उपयोग किए जाने वाले नमूनों की संख्या के समान संख्या प्राप्त करने के लिए स्लाइस (opens in a new tab) का उपयोग करें। यहां और अगले खंड के बीच का कोड वही गेट-ए-प्रेडिक्शन कोड है जो हमारे पास एजेंट में है।
1 predicted_price = Decimal(response.choices[0].message.content.strip())2 real_price = wethusdc_quotes[index+CYCLES_BACK].price3 prediction_time_price = wethusdc_quotes[index+CYCLES_BACK-1].priceअनुमानित मूल्य, वास्तविक मूल्य और भविष्यवाणी के समय मूल्य प्राप्त करें। यह निर्धारित करने के लिए कि क्या सिफारिश खरीदने या बेचने की थी, हमें भविष्यवाणी के समय मूल्य की आवश्यकता है।
1 error = abs(predicted_price - real_price)2 total_error += error3 print (f"भविष्यवाणी के लिए {prediction_time}: भविष्यवाणी की गई {predicted_price} USD, वास्तविक {real_price} USD, त्रुटि {error} USD")त्रुटि का पता लगाएं, और इसे कुल में जोड़ें।
1 recomended_action = 'buy' if predicted_price > prediction_time_price else 'sell'2 price_increase = real_price - prediction_time_price3 changes.append(price_increase if recomended_action == 'buy' else -price_increase)बदलाव के लिए, हम एक ETH खरीदने या बेचने के मौद्रिक प्रभाव चाहते हैं। इसलिए सबसे पहले, हमें सिफारिश निर्धारित करने की आवश्यकता है, फिर यह आकलन करें कि वास्तविक मूल्य कैसे बदला, और क्या सिफारिश ने पैसा बनाया (सकारात्मक परिवर्तन) या पैसे की लागत (नकारात्मक परिवर्तन)।
1print (f"Mean prediction error over {len(wethusdc_quotes)-CYCLES_BACK} predictions: {total_error / Decimal(len(wethusdc_quotes)-CYCLES_BACK)} USD")23length_changes = Decimal(len(changes))4mean_change = sum(changes, Decimal(0)) / length_changes5print (f"Mean change per recommendation: {mean_change} USD")6var = sum((x - mean_change) ** 2 for x in changes) / length_changes7print (f"Standard variance of changes: {var.sqrt().quantize(Decimal("0.01"))} USD")परिणामों की रिपोर्ट करें।
1print (f"लाभदायक दिन: {len(list(filter(lambda x: x > 0, changes)))/length_changes:.2%}")2print (f"नुकसान वाले दिन: {len(list(filter(lambda x: x < 0, changes)))/length_changes:.2%}")लाभदायक दिनों की संख्या और महंगे दिनों की संख्या की गणना करने के लिए filter (opens in a new tab) का उपयोग करें। परिणाम एक फ़िल्टर ऑब्जेक्ट है, जिसे लंबाई प्राप्त करने के लिए हमें एक सूची में बदलने की आवश्यकता है।
लेन-देन जमा करना
अब हमें वास्तव में लेन-देन जमा करने की आवश्यकता है। हालांकि, मैं इस समय असली पैसा खर्च नहीं करना चाहता, जब तक कि सिस्टम साबित न हो जाए। इसके बजाय, हम मेननेट का एक स्थानीय फोर्क बनाएंगे, और उस नेटवर्क पर "ट्रेड" करेंगे।
यहां एक स्थानीय फोर्क बनाने और ट्रेडिंग को सक्षम करने के चरण दिए गए हैं।
-
फाउंड्री (opens in a new tab) इंस्टॉल करें
-
अनविल(opens in a new tab) शुरू करें1anvil --fork-url https://eth.drpc.org --block-time 12अनविलफाउंड्री के लिए डिफ़ॉल्ट URL, http://localhost:8545 (opens in a new tab) पर सुन रहा है, इसलिए हमेंकास्टकमांड (opens in a new tab) के लिए URL निर्दिष्ट करने की आवश्यकता नहीं है जिसका उपयोग हम ब्लॉकचेन में हेरफेर करने के लिए करते हैं। -
अनविलमें चलने पर, दस परीक्षण खाते होते हैं जिनमें ETH होता है - पहले वाले के लिए पर्यावरण चर सेट करें1PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff802ADDRESS=`cast wallet address $PRIVATE_KEY` -
ये वे अनुबंध हैं जिनका हमें उपयोग करने की आवश्यकता है।
SwapRouter(opens in a new tab) Uniswap v3 कॉन्ट्रैक्ट है जिसका उपयोग हम वास्तव में व्यापार करने के लिए करते हैं। हम सीधे पूल के माध्यम से व्यापार कर सकते हैं, लेकिन यह बहुत आसान है।दो नीचे के चर WETH और USDC के बीच स्वैप करने के लिए आवश्यक Uniswap v3 पथ हैं।
1WETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc22USDC_ADDRESS=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB483POOL_ADDRESS=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f56404SWAP_ROUTER=0xE592427A0AEce92De3Edee1F18E0157C058615645WETH_TO_USDC=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB486USDC_TO_WETH=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 -
प्रत्येक परीक्षण खाते में 10,000 ETH हैं। ट्रेडिंग के लिए 1000 WETH प्राप्त करने के लिए WETH अनुबंध का उपयोग करके 1000 ETH को रैप करें।
1cast send $WETH_ADDRESS "deposit()" --value 1000ether --private-key $PRIVATE_KEY -
USDC के लिए 500 WETH का व्यापार करने के लिए
SwapRouterका उपयोग करें।1cast send $WETH_ADDRESS "approve(address,uint256)" $SWAP_ROUTER 500ether --private-key $PRIVATE_KEY2MAXINT=`cast max-int uint256`3cast send $SWAP_ROUTER \4 "exactInput((bytes,address,uint256,uint256,uint256))" \5 "($WETH_TO_USDC,$ADDRESS,$MAXINT,500ether,1000000)" \6 --private-key $PRIVATE_KEYअनुमोदनकॉल एक भत्ता बनाता है जोSwapRouterको हमारे कुछ टोकन खर्च करने की अनुमति देता है। कॉन्ट्रैक्ट्स इवेंट्स की निगरानी नहीं कर सकते हैं, इसलिए यदि हम सीधेSwapRouterकॉन्ट्रैक्ट में टोकन स्थानांतरित करते हैं, तो उसे पता नहीं चलेगा कि उसे भुगतान किया गया है। इसके बजाय, हमSwapRouterकॉन्ट्रैक्ट को एक निश्चित राशि खर्च करने की अनुमति देते हैं, और फिरSwapRouterऐसा करता है। यहSwapRouterद्वारा बुलाए गए फ़ंक्शन के माध्यम से किया जाता है, इसलिए यह जानता है कि यह सफल रहा या नहीं। -
सत्यापित करें कि आपके पास दोनों टोकन पर्याप्त हैं।
1cast call $WETH_ADDRESS "balanceOf(address)" $ADDRESS | cast from-wei2echo `cast call $USDC_ADDRESS "balanceOf(address)" $ADDRESS | cast to-dec`/10^6 | bc
अब जब हमारे पास WETH और USDC हैं, तो हम वास्तव में एजेंट चला सकते हैं।
1git checkout 05-trade2uv run agent.pyआउटपुट इसके समान दिखेगा:
1(ai-trading-agent) qbzzt@Ori-Cloudnomics:~/260215-ai-agent$ uv run agent.py2वर्तमान मूल्य: 1843.1632026-02-06T23:07 में, अपेक्षित मूल्य: 1724.41 USD4ट्रेड से पहले खाते की शेष राशि:5USDC शेष: 927301.5782726WETH शेष: 5007बेचें, मुझे उम्मीद है कि कीमत 118.75 USD तक गिर जाएगी8अनुमोदन लेनदेन भेजा गया: 74e367ddbb407c1aaf567d87aa5863049991b1d2aa092b6b85195d925e2bd41f9अनुमोदन लेनदेन खनन किया गया।10विक्रय लेनदेन भेजा गया: fad1bcf938585c9e90364b26ac7a80eea9efd34c37e5db81e58d7655bcae28bf11विक्रय लेनदेन खनन किया गया।12व्यापार के बाद खाता शेष:13USDC शेष: 929143.79711614WETH शेष: 499सभी दिखाएँवास्तव में इसका उपयोग करने के लिए, आपको कुछ छोटे बदलावों की आवश्यकता है।
- लाइन 14 में,
MAINNET_URLको वास्तविक एक्सेस प्वाइंट में बदलें, जैसेhttps://eth.drpc.org - लाइन 28 में,
PRIVATE_KEYको अपनी निजी चाबी में बदलें - जब तक आप बहुत अमीर नहीं हैं और एक अप्रमाणित एजेंट के लिए हर दिन 1 ETH खरीद या बेच सकते हैं, तब तक आप
WETH_TRADE_AMOUNTको कम करने के लिए 29 को बदलना चाह सकते हैं।
कोड स्पष्टीकरण
यहाँ नया कोड है।
1SWAP_ROUTER_ADDRESS=Web3.to_checksum_address("0xE592427A0AEce92De3Edee1F18E0157C05861564")2WETH_TO_USDC=bytes.fromhex("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001F4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")3USDC_TO_WETH=bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB480001F4C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")4PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"वही चर जो हमने चरण 4 में उपयोग किए थे।
1WETH_TRADE_AMOUNT=1ट्रेड करने की राशि।
1ERC20_ABI = [2 { "name": "symbol", ... },3 { "name": "decimals", ... },4 { "name": "balanceOf", ...},5 { "name": "approve", ...}6]वास्तव में व्यापार करने के लिए, हमें अनुमोदन फ़ंक्शन की आवश्यकता है। हम पहले और बाद में शेष राशि भी दिखाना चाहते हैं, इसलिए हमें बैलेंसऑफ़ की भी आवश्यकता है।
1SWAP_ROUTER_ABI = [2 { "name": "exactInput", ...},3]SwapRouter ABI में हमें बस exactInput की आवश्यकता है। एक संबंधित फ़ंक्शन है, exactOutput, जिसका उपयोग हम ठीक एक WETH खरीदने के लिए कर सकते हैं, लेकिन सरलता के लिए हम दोनों मामलों में exactInput का उपयोग करते हैं।
1account = w3.eth.account.from_key(PRIVATE_KEY)2swap_router = w3.eth.contract(3 address=SWAP_ROUTER_ADDRESS,4 abi=SWAP_ROUTER_ABI5)खाता (opens in a new tab) और SwapRouter अनुबंध के लिए Web3 परिभाषाएँ।
1def txn_params() -> dict:2 return {3 "from": account.address,4 "value": 0,5 "gas": 300000,6 "nonce": w3.eth.get_transaction_count(account.address),7 }लेन-देन के पैरामीटर। हमें यहां एक फ़ंक्शन की आवश्यकता है क्योंकि नोंस (opens in a new tab) हर बार बदलना चाहिए।
1def approve_token(contract: Contract, amount: int):SwapRouter के लिए एक टोकन भत्ते को मंजूरी दें।
1 txn = contract.functions.approve(SWAP_ROUTER_ADDRESS, amount).build_transaction(txn_params())2 signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY)3 tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction)यह है कि हम Web3 में एक लेनदेन कैसे भेजते हैं। सबसे पहले हम लेन-देन बनाने के लिए कॉन्ट्रैक्ट ऑब्जेक्ट (opens in a new tab) का उपयोग करते हैं। फिर हम लेन-देन पर हस्ताक्षर करने के लिए web3.eth.account.sign_transaction (opens in a new tab) का उपयोग करते हैं, PRIVATE_KEY का उपयोग करके। अंत में, हम लेन-देन भेजने के लिए w3.eth.send_raw_transaction (opens in a new tab) का उपयोग करते हैं।
1 print(f"अनुमोदन लेनदेन भेजा गया: {tx_hash.hex()}")2 w3.eth.wait_for_transaction_receipt(tx_hash)3 print("अनुमोदन लेनदेन खनन किया गया।")w3.eth.wait_for_transaction_receipt (opens in a new tab) तब तक प्रतीक्षा करता है जब तक कि लेनदेन खनन न हो जाए। यदि आवश्यक हो तो यह रसीद लौटाता है।
1SELL_PARAMS = {2 "path": WETH_TO_USDC,3 "recipient": account.address,4 "deadline": 2**256 - 1,5 "amountIn": WETH_TRADE_AMOUNT * 10 ** wethusdc_pool.token1.decimals,6 "amountOutMinimum": 0,7}ये WETH बेचते समय के पैरामीटर हैं।
1def make_buy_params(quote: Quote) -> dict:2 return {3 "path": USDC_TO_WETH,4 "recipient": account.address,5 "deadline": 2**256 - 1,6 "amountIn": int(quote.price*WETH_TRADE_AMOUNT) * 10**wethusdc_pool.token0.decimals,7 "amountOutMinimum": 0,8 }SELL_PARAMS के विपरीत, खरीद पैरामीटर बदल सकते हैं। इनपुट राशि 1 WETH की लागत है, जैसा कि उद्धरण में उपलब्ध है।
1def buy(quote: Quote):2 buy_params = make_buy_params(quote)3 approve_token(wethusdc_pool.token0.contract, buy_params["amountIn"])4 txn = swap_router.functions.exactInput(buy_params).build_transaction(txn_params())5 signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY)6 tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction)7 print(f"Buy transaction sent: {tx_hash.hex()}")8 w3.eth.wait_for_transaction_receipt(tx_hash)9 print("Buy transaction mined.")101112def sell():13 approve_token(wethusdc_pool.token1.contract,14 WETH_TRADE_AMOUNT * 10**wethusdc_pool.token1.decimals)15 txn = swap_router.functions.exactInput(SELL_PARAMS).build_transaction(txn_params())16 signed_txn = w3.eth.account.sign_transaction(txn, private_key=PRIVATE_KEY)17 tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction)18 print(f"Sell transaction sent: {tx_hash.hex()}")19 w3.eth.wait_for_transaction_receipt(tx_hash)20 print("Sell transaction mined.")सभी दिखाएँbuy() और sell() फ़ंक्शन लगभग समान हैं। पहले हम SwapRouter के लिए पर्याप्त भत्ते को मंजूरी देते हैं, और फिर हम इसे सही पथ और राशि के साथ बुलाते हैं।
1def balances():2 token0_balance = wethusdc_pool.token0.contract.functions.balanceOf(account.address).call()3 token1_balance = wethusdc_pool.token1.contract.functions.balanceOf(account.address).call()45 print(f"{wethusdc_pool.token0.symbol} Balance: {Decimal(token0_balance) / Decimal(10 ** wethusdc_pool.token0.decimals)}")6 print(f"{wethusdc_pool.token1.symbol} Balance: {Decimal(token1_balance) / Decimal(10 ** wethusdc_pool.token1.decimals)}")दोनों मुद्राओं में यूज़र शेष राशि की रिपोर्ट करें।
1print("ट्रेड से पहले खाते की शेष राशि:")2शेष राशि()34if (expected_price > current_price):5 print(f"खरीदें, मुझे उम्मीद है कि कीमत {expected_price - current_price} USD तक बढ़ जाएगी")6 buy(wethusdc_quotes[-1])7else:8 print(f"बेचें, मुझे उम्मीद है कि कीमत {current_price - expected_price} USD तक गिर जाएगी")9 sell()1011print("ट्रेड के बाद खाते की शेष राशि:")12balances()सभी दिखाएँयह एजेंट वर्तमान में केवल एक बार काम करता है। हालांकि, आप इसे क्रॉन्टैब (opens in a new tab) से चलाकर या लूप में 368-400 लाइनों को लपेटकर और अगले चक्र के लिए समय होने तक प्रतीक्षा करने के लिए टाइम.स्लीप (opens in a new tab) का उपयोग करके इसे लगातार काम करने के लिए बदल सकते हैं।
संभावित सुधार
यह एक पूर्ण उत्पादन संस्करण नहीं है; यह केवल मूल बातें सिखाने के लिए एक उदाहरण है। यहां सुधार के लिए कुछ विचार दिए गए हैं।
स्मार्ट ट्रेडिंग
दो महत्वपूर्ण तथ्य हैं जिन्हें एजेंट क्या करना है यह तय करते समय अनदेखा करता है।
- प्रत्याशित परिवर्तन की भयावहता। एजेंट
WETHकी एक निश्चित राशि बेचता है यदि कीमत में गिरावट की उम्मीद है, गिरावट की भयावहता की परवाह किए बिना। तर्कसंगत रूप से, मामूली बदलावों को अनदेखा करना और कीमत में गिरावट की उम्मीद के आधार पर बेचना बेहतर होगा। - वर्तमान पोर्टफोलियो। यदि आपके पोर्टफोलियो का 10% WETH में है और आपको लगता है कि कीमत बढ़ेगी, तो शायद अधिक खरीदना समझ में आता है। लेकिन अगर आपके पोर्टफोलियो का 90% WETH में है, तो आप पर्याप्त रूप से उजागर हो सकते हैं, और अधिक खरीदने की कोई आवश्यकता नहीं है। यदि आप कीमत में गिरावट की उम्मीद करते हैं तो विपरीत सच है।
क्या होगा यदि आप अपनी ट्रेडिंग रणनीति को गुप्त रखना चाहते हैं?
AI विक्रेता आपके द्वारा उनके LLMs को भेजी गई क्वेरी देख सकते हैं, जो आपके एजेंट के साथ विकसित की गई जीनियस ट्रेडिंग प्रणाली को उजागर कर सकती है। एक ट्रेडिंग सिस्टम जिसका बहुत से लोग उपयोग करते हैं वह बेकार है क्योंकि बहुत से लोग तब खरीदने की कोशिश करते हैं जब आप खरीदना चाहते हैं (और कीमत बढ़ जाती है) और तब बेचने की कोशिश करते हैं जब आप बेचना चाहते हैं (और कीमत गिर जाती है)।
आप इस समस्या से बचने के लिए स्थानीय रूप से एक LLM चला सकते हैं, उदाहरण के लिए, LM-Studio (opens in a new tab) का उपयोग करके।
AI बॉट से AI एजेंट तक
आप एक अच्छा मामला बना सकते हैं कि यह एक AI बॉट है, AI एजेंट नहीं। यह एक अपेक्षाकृत सरल रणनीति लागू करता है जो पूर्वनिर्धारित जानकारी पर निर्भर करती है। हम स्व-सुधार को सक्षम कर सकते हैं, उदाहरण के लिए, Uniswap v3 पूलों की एक सूची और उनके नवीनतम मूल्यों को प्रदान करके और यह पूछकर कि किस संयोजन का सबसे अच्छा पूर्वानुमान मूल्य है।
स्लिपेज सुरक्षा
वर्तमान में कोई स्लिपेज सुरक्षा (opens in a new tab) नहीं है। यदि वर्तमान उद्धरण $2000 है, और अपेक्षित मूल्य $2100 है, तो एजेंट खरीदेगा। हालांकि, यदि एजेंट खरीदने से पहले लागत $2200 तक बढ़ जाती है, तो अब और खरीदने का कोई मतलब नहीं है।
स्लिपेज सुरक्षा को लागू करने के लिए, agent.py (opens in a new tab) की पंक्तियों 325 और 334 में amountOutMinimum मान निर्दिष्ट करें।
निष्कर्ष
उम्मीद है, अब आप AI एजेंटों के साथ शुरुआत करने के लिए पर्याप्त जानते हैं। यह विषय का एक व्यापक अवलोकन नहीं है; इसके लिए पूरी किताबें समर्पित हैं, लेकिन यह आपको शुरू करने के लिए पर्याप्त है। शुभकामनाएँ!
मेरे और काम के लिए यहाँ देखें (opens in a new tab)।
पेज का अंतिम अपडेट: 10 फ़रवरी 2026