📱

Get Our Mobile App

Take your business learning on the go!

Download on the App StoreGet it on Google Play

How to Build an AI Trading Bot in Python

Roman Paolucci1:29:21

Transcription

[Zene] Ebben a videóban végigvezetünk egy AI kereskedési bot felépítésén. Összeállítottam egy teendőlista alapvető lépéseit, amelyeket végig fogunk járni. Pythonban fogunk kezdeni egy alapvető felhasználói felület építésével a kereskedéshez, egy olyan hellyel, ahol meghatározhatjuk, mely részvényeket szeretnénk kereskedni, a maximális pozícióméretünket, a stratégiánk különböző paramétereit. A második lépés az lesz, hogy API-n keresztül kapcsolatot létesítsünk valamilyen brókercéggel. Ebben az esetben az Alpacát fogjuk használni, ami meglehetősen könnyen használható. Természetesen ezt helyettesítheted bármelyikkel, amit szeretnél. A harmadik lépés a stratégia kidolgozása lesz. Ebben az esetben egy Martingale DCA stílusú stratégiát fogunk vizsgálni, ahol ahogy egy részvény csökken a kezdeti belépési árunkhoz képest, tovább növeljük a pozícióméretünket. Integrálunk egy LLM-et, ez az AI komponens. Tehát nem használunk AI-t semmilyen jelzésanalízishez, bár a harmadik lépésben megtehetnéd, de ez a pozíciókezeléshez lesz. Kérdezhetjük az LLM-ünket a kockázati kitettségünkről, az ilyesmikről, és természetesen az ötödik lépés a telepítés lesz, ami lényegében az egész rendszer futtatása. Végig fogjuk járni mindegyik lépést együtt, de az egész projektet közzé fogom tenni a GitHub-on is, ha érdekel. Hagyok egy linket az alábbi leírásban. Rendben, kezdjük az első lépéssel. Itt fogok létrehozni egy új Python szkriptet. Ez egy meglehetősen kicsi kereskedési bot, ezért csak bot.py-nak fogom hívni, és mindent bele tudunk írni. Kezdéshez importálnunk kell néhány csomagot. Van néhány jegyzetem itt a szükséges lépésekről ennek a GUI-nak az építéséhez. Tehát végig fogjuk járni ezt együtt, és minden lépést el fogok magyarázni. Tehát először importáljuk a Tkintert mint TK, ez lehetővé teszi számunkra, hogy felépítsük ezt a felhasználói felületet. Importálunk néhány más dolgot a Tkinterből. Importáljuk a JSON-t is, és hamarosan elmagyarázom, miért. Importáljuk az időt is, a szálkezelést. Ez fontos lesz a felhasználói felület frissítéséhez, és importáljuk a véletlenszámot is. Ez minden, amire szükségünk van a kezdéshez. Az egyik első dolog, amit meg kell tennünk, hogy létre kell hoznunk egy fájlt az adatok mentéséhez és betöltéséhez. Ez értelmes, igaz? Ha bezárom a kereskedési rendszert és újra megnyitom, akkor tudnia kell, hogy milyen részvényeket kereskedek és milyen szinteken kereskedem őket. Tehát pontosan ezt fogjuk tenni. Létrehozunk egy új fájlt, equities.json-nak fogjuk hívni, és ez lényegében csak a kereskedett szimbólumokat fogja tárolni, például az Apple, az Amazon, és aztán a szinteket, amelyeken kereskedünk. Tehát rögzíteni fogja az aktív pozícióinkat, rögzíteni fogja a belépési árat, és rögzíteni fogja azokat az árakat, amelyeken belépni szeretnénk az első belépési árunk alá, követve azt a Martingale DCA stílusú stratégiát. Most létrehozunk néhány hamis funkciót, amelyeket később fogunk feltölteni. Hívjuk ezt fetch_mock_api-nak egy szimbólumra, és egyelőre csak egy árat fogunk visszaadni szótárként. Tehát hívjuk ezt price-nak, és azt mondom, talán 100-at egyelőre. def mock_gpt_response. Ez egy hamis üzenet lesz az AI-tól, és így fog kinézni. Csak egy sztringet fogunk visszaadni egy hamis üzenettel, és ezeket később feltöltjük az API-jainkkal. Most el kell kezdenünk felépíteni a kereskedési bot osztályt. Amit tenni fogok, az az, hogy hívni fogom ezt trading_bot_gui_bot kisbetűvel. Létrehozok egy konstruktort. Adok neki egy gyökér ablakot, mivel Tkintert használunk. Tehát ez automatikusan feltöltődött számomra. Azt fogom tenni, hogy self.root = root. A cím AI Trading Bot lesz, és ezek a funkciók nincsenek meg. Tehát ehelyett azt fogjuk mondani, hogy self.equities = self.load_equities. Hamarosan felépítjük ezt a load_equities funkciót, és pontosan erre van ez az equities.json fájlunk. Lényegében be kell töltenünk a felhasználói felületet a mentett információinkkal. Amit a betöltéskor és bezáráskor tenni fogunk, az az, hogy mentjük és betöltjük az információkat ebből az equities.json fájlból. Ez lesz minden, azt hiszem, az elsődleges konstruktorhoz. Lehet, hogy szükségünk lesz egy kapcsolóra is arra vonatkozóan, hogy fut-e a rendszer vagy sem. Tehát ezt itt hagyom egyelőre. Ez lényegében azt mondja nekünk, hogy aktívan kereskedünk-e egy részvényt a rendszerben. Tehát ha például hozzáadom az Apple-t a rendszeremhez, akkor szeretnénk tudni kapcsolni ezt be és ki. Tehát csak azért, mert létezik a rendszerben, nem jelenti azt, hogy aktívan kereskedni akarjuk különböző szinteken, és pontosan ezt tenné egy rendszerkapcsoló. Lehet, hogy beépítjük magába az equity adatba. Majd meglátjuk, hogyan alakul ez. Most szükségünk van egy űrlapra, hogy részvényeket adjunk hozzá a dobozunkhoz. Tehát azt fogom mondani, hogy self.form_frame = tk.Frame, és hozzáadjuk a gyökér ablakhoz. Aztán csak tovább megyünk és becsomagoljuk ezt az űrlapot. Most létrehozzuk a különböző címkéket. Tehát azt fogjuk tenni, hogy tk.Label, self.form_frame, text=symbol. Grid elrendezést fogunk használni, tehát rendben, jó, már megtette nekem. self.symbol_label.grid(row=0, column=0). Ez jó. És most el kell mennünk és hozzá kell adnunk magát az űrlapot hozzá. Vagyis az entry-t kell hozzáadnunk. Tehát ez az AI nem segített sokat. Tehát ezt fogjuk tenni. grid(row=0, column=0). És itt lesz az entry-nk, és itt fogjuk kitölteni a szimbólumrendelést. Részben kitöltve. Úgy tűnik, a kereskedési rendszerem éppen kitöltött egy megbízást az Interactive Brokers-nél. Ez elég klassz. self.symbol_entry.grid(row=0, column=1). Tehát ez lesz egy részvény szimbólumának beírására. Most ezt meg kell tennünk a szintek és a csökkenés szempontjából a stratégiánkban. Tehát ez lesz az űrlap egy új részvény hozzáadásához a kereskedési botunkhoz. Most szükségünk van egy címkére a mennyiség helyett, hanem a szintekre. És a szinteknek új entry-je lesz. self.levels_entry. És aztán meg fogjuk tenni, hogy self.levels_entry.grid(row=1, column=1). És akkor szükségünk van egyre a csökkenéshez. Tehát hozzáadjuk ezt a 2. sorhoz, vagy valójában ennek az oszlopokon kellene átnyúlnia, nem a sorokon. Tehát 0. oszlop, 1. oszlop, 2. oszlop. Ugyanazon a soron akarjuk őket. Igen, ez jól néz ki. 0, 0, 1, 0, 1. Nem, ez kettőnek kellene lennie. Ez kettőnek kellene lennie. Ez háromnak kellene lennie. Ez egynek kellene lennie. Ez négynek kellene lennie. Oké. És akkor self. Nem mennyiség, ez szintek lesznek. Nem csökkenés százalék. self.drawdown_entry. És akkor 1, 5. Rendben, tökéletes. Tehát amit tettünk, az az, hogy létrehoztunk egy űrlapot egy új részvény hozzáadásához a kereskedési botunkhoz. Ez lesz a szimbólum, amit kereskedni fogunk. Ez lesz a szintek száma a kereskedéshez. Tehát feltételezzük az egységes pozícióméretet, egyet. Ezt nagyon könnyen szerkesztheted a háttérben, vagy hozzáadhatsz egy új bejegyzést, ha szeretnél. És akkor a csökkenésről fogunk beszélni, hogy új pozíciót lépjünk be minden szinten. Tehát ez azt jelenti, hogy ha 100-as belépési árnál kereskedünk, akkor ha 10%-os csökkenésünk van, akkor lépünk be egy új pozícióba, és akkor egy újabb 10%-os csökkenésnél lépünk be egy új pozícióba, és így tovább. Tehát ez lesz a kereskedési stratégia ötlete. Rendben, most szükségünk van egy táblázatra a kereskedett részvények nyomon követéséhez. Tehát azt fogom mondani, hogy self.tree = ttk.Treeview. És tovább megyünk és megjelenítjük a fejlécet, de az oszlopaink szimbólumok lesznek. Meg fogjuk tenni a pozíciót. Meg fogjuk tenni a belépési árat. Szintén meg fogjuk tenni a szinteket, ami egy szótár lesz, és az állapotot. Az állapot talán felesleges, de mindenesetre van ez a Treeview, és természetesen megjelenítjük a fejlécet. És most azt fogjuk mondani, hogy for col in, és azt fogjuk mondani, hogy symbol, position, entry_price, levels, status. Akkor azt fogjuk tenni, hogy self.tree.heading(col, text=col). Tehát csak a fejlécet állítjuk ezekre az oszlopfejlécekre, és azt fogjuk mondani, hogy self.tree.column(col, width=120). 120 elegendő lesz. És akkor meg fogjuk tenni, hogy self.tree.pack(). És ott fogjuk látni az aktuális portfóliónkat. Tehát lényegében, ami itt történik, az az, hogy létrehozunk egy táblázatot, és ebben a táblázatban vannak szintek, amelyeken minden részvényt létrehozunk, és az API hívásaink alapján frissítjük ezt a táblázatot, és frissítjük ezt a táblázatot az egyes relatív szimbólumok pozíciójával, a belépési árral, talán a megbízás állapotával és így tovább. És ezen a táblázaton keresztül tudni fogjuk kapcsolni, hogy kereskedünk-e az adott részvényt, és azt hiszem, ez minden, amire szükségünk van. Tehát most hozzá fogunk adni gombokat a hozzáadáshoz és eltávolításhoz. Nem csak hozzáadás és eltávolítás, hanem a részvényeket is kapcsolni kell. Tehát gombok a bot vezérléséhez. Azt fogjuk mondani, hogy self.toggle_system_button = tk.Button(root). Hozzáadjuk a fő ablakhoz. Azt fogjuk mondani, hogy toggle selected system. És akkor azt fogjuk mondani, hogy a gomb parancsa self.toggle_system, ami értelmes lesz. Azt fogjuk mondani, hogy self.toggle_system_button.pack(pady=5). Most hozzáadjuk a törlés gombot. tk.Button(root, text="Remove Selected Equity", command=self.remove_selected_equity). Azt fogjuk mondani, hogy command=self.remove_selected_equity. És ezeket meg fogjuk csinálni. Tehát nincs, nincs parancsunk a részvények betöltésére. Nincs, vagyis azt mondom, hogy nincs funkciónk a részvények betöltésére, és nincs funkciónk a rendszer kapcsolására vagy a kiválasztott részvények eltávolítására. De ezt hamarosan meg fogjuk tenni. A törlés gombot is becsomagoljuk, és ez lehetővé teszi számunkra, hogy hozzáadjunk, vagy nem hozzáadjunk, hanem eltávolítsunk a táblázatból. Ez lehetővé teszi számunkra, hogy eltávolítsunk a táblázatból. Oké, úgy tűnik, elfelejtettem a hozzáadás gombot. Tehát csak fel fogom tenni ide, mert a form részének kell lennie. Az eredeti űrlap a részvények hozzáadásához. Tehát a táblázat fölé létrehozok egy új gombot. self.add_button. És azt fogom mondani, hogy = tk. Nem self.form_frame. Vagyis használhatnánk a form_frame-et, mert ez a gyökér ehhez a konkrét widgethez. Tehát itt a self.form_frame-et fogjuk használni, mert ez a szimbólum, szintek, csökkenés űrlap részét képezi, részvény hozzáadása. Tehát azt fogjuk mondani, és akkor azt fogjuk mondani, hogy self.add_button. És akkor csak 0, 6-ra fogjuk tenni. Tehát ugyanaz a sor, de a hatodik oszlop. És ez értelmes, igaz? Tehát a címkék mind párosak, és ebben az esetben a hozzáadás gomb is páros. Tehát egy vonalban lesz azokkal. És akkor lesz az 1. sor, ami az entry, de eltolva a páratlan oszlopokkal, hogy lássuk a címkét, lássuk az entry-t, lássuk a címkét, lássuk az entry-t, és természetesen adjuk hozzá az equity-t az űrlap végén. Aztán ott van a toggle system gombunk vagy a törlés gombunk, és az összes equity-nk táblázata a rendszerünkben. És ez minden, amire szükségünk van. Most létre kell hoznunk egy felületet az AI komponensünk számára. Tehát azt fogom mondani, hogy ez az AI komponens. Azt fogom mondani, hogy self.chat_frame = tk.Frame(root). És akkor azt fogjuk mondani, hogy self.chat_frame. Csak becsomagoljuk. Pack, és pady=1. Szükségünk van egy bemenetre, és ez csak egy egyszerű entry lesz. És hozzáadjuk a chat_frame-hez. És akkor azt is meg fogjuk tenni, hogy self.chat_input. És nem fogjuk becsomagolni. Grid-et akarok csinálni. Tehát grid(row=0, column=0). Lesz némi pad az x-en. Ez jó lesz. És akkor szükségünk van egy gombra is az üzenet küldéséhez. send_button = tk.Button(chat_frame, text="Send", command=self.send_message). Még nincs parancsunk vagy a send_message funkció. Ezen hamarosan dolgozni fogunk. És akkor természetesen csak becsomagoljuk, vagy grid-et fogunk csinálni a gombnak, és becsomagoljuk a chat output elrendezést. Tehát azt fogjuk tenni, hogy self.send_button.grid(row=0, column=1). És ez csak ugyanaz az ötlet, mint amit itt fent csináltunk a grid elrendezéssel. Most azt fogjuk mondani, hogy self.chat_output = tk.Text(root, height=5, width=50). Mondjuk talán 50, 60, talán. És az állapot tk.DISABLED lesz, mert emlékezz, ez egy válasz. Tehát nem akarjuk, hogy csak szerkeszteni tudjuk a választ az AI-tól. Csak olvasható, egyszerű szöveg legyen. És akkor csak becsomagoljuk ezt a kimenetet. Csak becsomagoljuk ezt a kimenetet. Oké, betöltjük a mentett adatokat. Tehát befejeztük a UI felépítését, lényegében. És most bele akarunk kezdeni a funkcionalitásba. Tehát betöltjük és mentjük az adatokat. Tehát azt fogjuk mondani, hogy self.refresh_table. Ez betölti a JSON-ból. Ezt a funkciót is fel kell építenünk. Aztán azt fogjuk mondani, hogy self.running = True. És ez az automatikus frissítéshez lesz. És akkor van self.auto_update_thread = threading.Thread(target=self.auto_update). Amit szintén létre kell hoznunk. És akkor azt fogjuk mondani, hogy daemon=True. És csak elindítjuk ezt a szálat, amit itt létrehoztunk. Ez lehetővé teszi számunkra, hogy folyamatosan lekérdezzük a frissítéseket. Tehát valamilyen időintervallumon, talán 5 másodperc vagy valami hasonló, amiért korábban importáltuk az időt. Tehát ez csak a táblázat automatikus frissítéséhez lesz az API-ból származó adatokkal. Most létre kell hoznunk azokat a funkciókat, amelyeket korábban használtunk, hogy azt mondjuk, add_equity, save és így tovább. Kezdjük egy funkció létrehozásával egy equity hozzáadásához. Tehát hívom ezt add_equity. def add_equity(self). És azt fogjuk mondani, hogy symbol = self.symbol_entry.get().upper(). levels = self.levels_entry.get(). drawdown = self.drawdown_entry.get(). Tehát itt csak a szimbólumot, a szinteket és a csökkenést szerezzük be a fent említett beviteli űrlapról. Rendben, és ez az add_equity parancs, amit most létrehozunk. Tehát ez is, azt hiszem, még mindig a konstruktoron belül van. Igen, ez még mindig a konstruktoron belül van. Tehát az én hibám. Ki kell húznom. Most használatban van. Tehát ezt befelé húztam. Most, ha ezt kihúzom, láthatod, hogy ez valójában használatban van ez a gomb. Lásd. Tehát most létrehozzuk ezt a funkciót a konstruktoron kívül. Szimbólumok, szintek, csökkenés, minden rendben. Most szükségünk van némi kezelésre az érvényes bemenethez. Tehát ha nem symbol vagy nem levels.isdigit() vagy nem drawdown.replace('.', '', 1).isdigit(). Tehát ezek mind érvénytelen bejegyzések. Ez nem fog mindent elkapni. Ez nem igazán a célja most, de ez egy ésszerű első védelmi vonal. messagebox.showerror. Ez azt jelenti, hogy nem adtál meg semmi érvényeset, és csak visszatérünk belőle. A szintek integer lesznek. Tehát ha van öt szinted, és kereskedsz lefelé egy adott részvényben, akkor ez egy egész szám. Lehetnek tört szintek, nincs értelme. Szeretem ezt a stratégiát példaként is megvalósítani, mert nagyon nehéz csődbe menni. Ha csak vakon követed ezt a tutorialt, tudod, még ha 100 szintet használnál is, nem feltétlenül fogsz 100-as pozíciót belépni, és az API nem fogja megengedni, hogy hatalmas tőkeáttételt használj. Tehát azt hiszem, ez egy nagyon ésszerű stratégia, még akkor is, ha vakon követed, ami jó. Szeretem ezt az aspektust is. De van ez a szint egész szám. Van a csökkenés is, amely meghatározza a belépési árat a következő szintekhez. Természetesen van a belépési árunk, amit az API-ból kell lekérnünk. Most meg kell határoznunk a kereskedési árakat a következő szintekhez. Tehát azt fogom mondani, hogy levels. Azt fogom mondani, hogy level_prices = [round(entry_price * (1 - drawdown * (i + 1)), 2) for i in range(levels)]. Tehát ez az a Martingale stílusú DCA stratégia, ahol veszem azt a csökkenési küszöböt, amit a részvényre beállítottunk, és minden szinten kereskedni fogok, amelyet a belépési ártól való csökkenés határoz meg. Tehát 100-nál lépünk be, ha szintenként 10%-os csökkenésünk van, akkor feltételezzük, hogy az első belépési ár rögzített. Minden 10 dollárért elhelyezünk egy vételt, és ez lényegében az, ami itt történik. Oké, frissítsük az equity-ket most. Ez a mentett adat. Tehát self.equities. Van a szimbólumunk, és azt akarjuk, hogy ez egy szótár legyen, ahol a pozíció nulla, a belépési ár a belépési ár lesz, a szintek a szintek lesznek, és az állapot pedig be vagy ki lesz a rendszerhez. Tehát kikapcsolva kezdjük. Azt hiszem, ahelyett, hogy az állapot az API megbízásának állapota lenne, inkább a rendszer állapotát fogjuk csinálni, ahol a rendszer be- vagy kikapcsolható bármelyik equity-hez a táblázatban. Azt hiszem, ez lesz a legértelmesebb. Bármikor, amikor új szimbólumokat adunk hozzá a szótárhoz, el kell mentenünk az adatokat. Tehát azt fogjuk mondani, hogy self.save_equities, és azt is mondani fogjuk, hogy self.refresh_table. És ez csak elmenti az adatokat és frissíti a táblázatot, ami értelmes számomra. Szeretném ellenőrizni, hogy ez helyes-e. Azt hiszem, ez a jelölés helyes az i és a range, a round. Azt hiszem, ennek itt kell lennie. Igen, nem érte el azt az i-t. A kerekítés függvényem a végén volt, a kettő mellett kellett volna lennie, hogy bezárja azt a függvényt. Nem akarom bezárni a függvényt a megértés köré ezen a ciklusban, ami létrehozza az árszinteket. Tehát ha ezt a figyelmeztetést is kaptad, hogy az i nem volt definiálva, azért van, mert a round függvénynek módosítania kellett volna ezt a zárójelet. Oké, ez lesz az add_equity funkcióhoz. Azt hiszem, ez minden, amit ott tennünk kell. Oké, most létre kell hoznunk egy funkciót egy kiválasztott rendszer kapcsolásához. Tehát hívom ezt toggle_selected_system. És azt fogjuk mondani, hogy görgessek lefelé. toggle_selected_system. Azt fogjuk mondani, hogy selected_items = self.tree.selection. Tehát megkapjuk, mi van kiválasztva a táblázatban. Ha nem selected_items, az azt jelenti, hogy nem választottunk semmit. Tehát lesz egy figyelmeztetésünk. A figyelmeztetés: Nincs kiválasztott equity. Meglepetés. Visszatérünk belőle. Különben, for item in selected_items. Azt fogjuk mondani, hogy symbol = self.tree.item(item)['values'][0]. És azt fogjuk mondani, hogy self.equities. Ez a mi equities szótárunk. Éppen most szereztük meg a szimbólumot a táblázatból. Kapcsoljuk a státuszt. És azt fogjuk mondani, hogy ternary stílusú if utasítás, ha a self.equities[symbol]['status'] == 'off', akkor 'on', különben 'off'. Azt hiszem, fordítva csináltam. Tehát lényegében azt csináljuk, hogy megnézzük, ha ki van kapcsolva, bekapcsoljuk. Különben kapcsoljuk ki. És ez az, amit csinálunk ebben a self.equities szótárban, ami az összes adatunkat menti. És ehhez az adathoz megyünk, és megnézzük a szimbólumot a táblázatban kiválasztott alapján. Ez az első self.tree.selection, és így iterálunk a kiválasztáson, hogy megtaláljuk a megfelelő szimbólumot, és aztán kapcsoljuk azt a rendszert. És ez az, ahogyan meghatározzuk, hogy aktívan kereskedünk-e az adott szimbólummal. Főzünk. Természetesen, mivel frissítettük az adatokat, hívni fogjuk a self.save_equities, és hívni fogjuk a self.refresh_table. És ez megteszi. Most kódot kell írnunk egy equity eltávolításához. Tehát azt fogjuk mondani, hogy def remove_selected_equity(self). És ez nem igazán lehet meglepő. Csak megkapjuk a kiválasztást a táblázatból, pontosan úgy, ahogyan korábban tettük. Ha semmi sincs kiválasztva. Tehát ha nem selected_items, akkor nyilvánvalóan nem tudjuk eltávolítani az equity-t. Tehát figyelmeztetjük őket. Azt fogjuk mondani, hogy Warning: No equity selected. Visszatérünk onnan. Aztán for item in selected_items. Ez pontosan az, amit éppen tettünk. Azt fogjuk mondani, hogy symbol = self.tree.item(item)['values'][0]. És megnézzük a nulladik értéket. Ez lesz a kiválasztott szimbólum. Aztán, ha a symbol szerepel a self.equities-ben, akkor csak töröljük. del self.equities[symbol]. És akkor természetesen mentenünk kell ezt a változást, és frissítenünk kell a táblázatot. Ez nem lehet túl nagy meglepetés. Ez szó szerint az ellenkezője annak, amit itt fent tettünk, amikor hozzáadtuk az equity-t. Csak eltávolítjuk, és ugyanúgy hozzáférünk, mint a kapcsolóhoz. Tehát nem lehet túl nagy meglepetés. Most kitöltünk egyfajta kitöltő funkciót egy üzenet küldéséhez a ChatGPT-n vagy az általad választott LLM-en keresztül. Tehát message = self.chat_input.get(). És a háttérben, miután megkaptuk azt az üzenetet az űrlapról, feltölthetjük portfólió információkkal, és aztán bármit kérdezhetünk az AI-tól a portfóliónkról. Ez lényegében az AI portfóliókezelőnk. Tehát ha nincs üzenet, akkor nem csinálunk semmit. Tehát visszatérünk. response = mock_gpt_response(). Ezt az üzenetet, ez a bemenet. Értelmes. chat_output.config(state=tk.NORMAL). self.chat_output.insert(tk.END, f"You: {message}\n") és akkor van egy válaszunk az AI-tól. Akár fel is bonthatjuk több új sorra. Ez rendben lesz. Természetesen ez ki van kapcsolva. Tehát a kimenet. chat_output.config(state=tk.DISABLED). És akkor azt fogjuk tenni, hogy self.chat_input. Töröljük, ami el lett küldve. És ez a várt funkcionalitás, igaz? Tehát ha beírsz valamit egy bemenetbe, és elküldöd a ChatGPT-nek, a szöveged nem marad abban a bemeneti űrlapon. Ezt csináljuk itt. Csak töröljük ezt nullától a végéig. És itt beszúrunk a kimeneti mező végére az üzenetet, amit küldtünk, és a választ az AI-tól. Természetesen meg kell szereznünk ezt a választ ebből a funkcióból, amit később építünk meg, ahogy haladunk az API munkával. De majdnem ott vagyunk. Csak néhány további funkciót kell felépítenünk. Ez lesz minden a send_message-hez. Most megyünk és frissítjük a táblázatot. Tehát a def refresh_table funkció. self.tree. A táblázathoz férünk hozzá. Azt fogjuk mondani, hogy for row in self.tree.get_children(): self.tree.delete(row). Mindent törölnünk kell, igaz? És újra feltöltjük néhány új információval. Tehát for symbol, data in self.equities.items(): És ez csak végigmegy az összes mentett adatunkon. Tehát azt fogjuk mondani, hogy self.tree.insert('', tk.END, values=(symbol, data['position'], data['entry_price'], data['levels'], data['status'])). Beillesztjük a táblázatba. Az értékek ebben a tuple-ban, amelyek a szimbólum lesznek, a pozíció, a belépési ár, a szintek, és a rendszer állapota lesznek. És ez minden lesz a refresh_table-hez. Csak töröljük az összes sort a táblázatban, és frissítjük az új információkkal. És mindig mehetünk és frissíthetjük az equities szótárat, amikor csak akarunk, bármelyik funkcióban. Természetesen az API-ban, az élő adatokhoz, visszamehetünk és frissíthetjük ezeket az adatokat itt. És minden alkalommal, amikor ezt a refresh_table-t hívjuk, frissül a megfelelő információkkal. Ez pontosan az, amit keresünk, igaz? Frissíteni akarjuk az equities szótárat élő adatokkal. Most ki kell találnunk, hogy milyen adatokat kell lekérnünk a brókertől, az API-tól, ami pontosan az, amiért mentjük és betöltjük ezt. Nem különösebben érdekelnek minket az elavult árinformációk, de tudnunk kell, hogy milyen ticker-eket kereskedünk, és hogy aktívan kereskedünk-e velük, amiért megtartjuk az állapotot. Azt is fenn akarom tartani a csökkenést és a szinteket, ezért van ez. Most hozzáadunk egy automatikus frissítést. def auto_update(self). És ez csak a felhasználói felület automatikus frissítéséhez van. Azt fogjuk mondani, hogy while self.running: Csak tovább megyünk és csinálunk time.sleep(5). Talán 5 másodpercnek hívjuk. És self.update_prices(). Frissíthetjük az árakat. Szükségünk van a save_equities funkciónkra. Ez lehetővé teszi számunkra, hogy elmentsük azt a szótárat. Tehát azt fogjuk mondani, hogy with open(self.data_file, 'w') as f: json.dump(self.equities, f). Ez lehetővé teszi számunkra az equity-k mentését. Most be kell töltenünk őket. Tehát a equities betöltése. Azt fogjuk tenni, hogy with open(self.data_file, 'r') as f: return json.load(f). Valószínűleg szükségünk van egy try-except köré. Tehát megpróbáljuk. Ez nem Java. Tehát try blokkot fogunk használni, hogy megpróbáljuk betölteni ezt a fájlt, és elfogunk egy FileNotFoundError-t és egy json.JSONDecodeError-t. Tehát ha valamilyen okból probléma van a JSON elemzésével, akkor ezt elkaphatjuk. Üres szótárat fogunk visszaadni. Ez valójában figyelmeztetést is kellene, hogy dobjon. Ez soha nem igazán fordulhat elő. Semmi sem indíthatja el ezt, hacsak nem mész be, szerkeszted a JSON-t, és nem tudja beleolvasni a szótárba. De ez elegendő lesz ahhoz, amit csinálunk. def on_close(self). Szükségünk van mentésre bezáráskor. Tehát azt fogjuk mondani, hogy self.running = False. self.save_equities(). self.root.destroy(). Némi házimunkát. És akkor ez minden, amire szükségünk van. Tehát akkor azt mondhatjuk, hogy if __name__ == "__main__": root = tk.Tk(). Ez a mi fő ablakunk. Ezt át fogjuk adni a trading_bot_gui-nak. Ott van a gyökér. Aztán meg fogjuk tenni, hogy root.protocol("WM_DELETE_WINDOW", self.on_close). Ez az on_close funkció, amit éppen felépítettünk. Tehát menteni fogunk. Biztos, hogy a futás hamis, és elpusztítjuk a gyökeret. És akkor csak futtatjuk a main loop-ot. Futtassuk ezt a main loop-ot. Tehát futtassuk ezt a srácot. Oké, úgy tűnik, hogy a trading_bot-nak nincs attribútuma a toggle_system-re. Tehát menjünk vissza, és próbáljuk meg kitalálni, hol van ez a probléma. toggle. [Zene] system. toggle_selected_system. Tehát csak toggle_selected_system-nek fogom hívni. Ez volt a probléma. Tehát ha emlékszel, amikor létrehoztuk ezt a toggle_system gombot, toggle_system-nek hívtam. Ez toggle_selected_system. toggle_selected_system. És most van a felhasználói felületünk az AI kereskedési botunkhoz. A felhasználói felületünk úgy tűnik, hogy egyel eltoltam ezeket a bejegyzéseket a szintekhez és a csökkenéshez, ami nem rossz az első futáshoz. Elég lenyűgözött, hogy ilyen strukturálisan jól sikerült, csak kódolással. Tehát itt van az 1. sor. Ezt 0. sornak fogjuk csinálni. Ezt 0. sornak fogjuk csinálni. És ez megoldja az eltolt bejegyzéseket. Ha újra futtatom, van egy szép felhasználói felületünk. Próbáljuk meg hozzáadni egy szimbólumot. Apple. Szintek, csináljunk 5 szintet 5%-os csökkenéssel. Add Equity. Úgy tűnik, hogy véletlenül levels_entry-nek hívtam a levels_entry helyett. Tehát javítsuk ki. levels_entry. Futtassuk újra ezt a srácot. Tehát azt mondjuk, Apple. Mondjuk 5 és 5. És a tuple nem határoz meg kerekítési módszert. Úgy tűnik, hogy ki kell javítanom a tuple-omat. round(entry_price * (1 - drawdown * (i + 1)), 2). Látom. Round 2. Tessék. Azt hiszem, rosszul tettem a zárójeleket. Próbáljuk meg ezt. Tehát ez a round függvényhez volt. Van ez a hiba: a tuple nem határoz meg kerekítési módszert. Természetesen még mindig hozzá kell adnunk az update_prices funkciót. De ha megnézed, ez meg fogja javítani a kerekítést. Azt hiszem, csak véletlenül egymásra raktam a zárójeleket. Csináljuk ezt. Tehát szimbólum Apple, szintek 5, csökkenés 5. Add Equity. Tessék. Tehát itt van a hamis belépési árunk 100. A szintek, amelyeken kereskedni fogunk. Függetlenül attól, hogy a rendszer be van-e kapcsolva vagy ki. Ezt itt kapcsolhatjuk. Bekapcsolás. Kikapcsolás. Van a chat komponensünk. Tehát beírhatunk egy üzenetet az AI chatbotunknak. Itt válaszolni fog. És ez minden lesz a felhasználói felületünkhöz. Tehát ez nem a legszexisebb felhasználói felület a világon. Mindesetre ezt fejlesztheted, ha tudod, hogy minden funkcionalitás olyan, amilyet szeretnél. Nem fogok túl sok időt tölteni a felhasználói felülettel. Igazán bele akarok kezdeni a rendszer többi funkcionalitásába. De ez elegendő lesz ahhoz, amit csinálni akarunk. Tehát amikor bezárom a rendszert, látni fogod, hogy van egy equities.json fájlunk. Amikor újra futtatom a rendszert, betölti az információkat. Ez pontosan az, amit keresünk. Tehát vannak ezek a szimbólumok, amelyeket kereskedünk. A rendszer állapota. Mentve bezáráskor. És amikor futtatjuk, láthatod, hogy újra feltöltődik. El is távolíthatjuk. Elmenti. Újra futtatjuk. És már nem létezik. Tehát minden a tervek szerint működik. Természetesen nincs integrálva a ChatGPT-nk. De ha ezt beírom, kapok egy hamis üzenetet. És ez te vagy. És akkor a hamis válasz. Emlékszel, hogy felküldtük az üzenetet, ha emlékszel a hamis API hívásunkra itt fent. Pontosan ez volt. Csak vissza fogja adni az üzenetet. Tehát most visszamegyünk az ellenőrzőlistához. És bumm. Ez kész. Első lépés. Második lépés egy brókercéghez való csatlakozás API-n keresztül. Tehát ebben az esetben az Alpacát fogjuk használni. És tovább megyünk, és elkezdjük az Alpaca API-val. Létrehozok egy új szkriptet itt, vagy talán létrehozok egy új Jupiter notebookot az Alpacához, csak hogy végigvezessem az első kapcsolatot együtt. Megnyitom az Alpacát nagyon gyorsan, és végigvezetem a kezdeti kapcsolat beállításán, és aztán hogyan integrálhatjuk ezt a botunkba. Menj az Alpacához, és hozz létre egy ingyenes fiókot. Le tudsz görgetni, és generálni néhány API kulcsot. Én most regeneráltam a kulcsaimat. Van ez a kulcs és ez a titkos kulcs. Természetesen a titkos kulcsod eltűnik. Tehát győződj meg róla, hogy nyomon követed. Visszamegyek a kódba, és hozzáadom a kulcsomat, és a titkos kulcsomat is hozzáadom. Tehát ez valójában a titkos kulcsom, és ez a kulcsom. Tehát ezt a kulcsot is lemásolom. Beillesztem ezt a kulcsot ide. És miután ezt megtettük, elkezdhetjük hozzáadni a keresett funkcionalitást. Lekérdezni az árakat, és kereskedéseket is elhelyezni. Ez az, hogy ezek a vételi megbízások a szinteken, a beállított szintek és a csökkenés szerint minden részvényhez a kereskedési botunkban. Mert tudom, hogy fel fog merülni. Szinte minden Python videóban felmerül, amit készítettem. Ha van egy ModuleNotFoundError hibád, az azt jelenti, hogy telepítened kell a csomagot vagy a modult pip-en keresztül. Tehát megnyitottam a parancssoromat. Van Pip install alpaca-trade-api, például. És ez telepíti az Alpaca API-t. Ez lehetővé teszi számomra, hogy Pythonban használjam. Tehát amikor importálom, és azt mondom, hogy import alpaca_trade_api as tradeapi, nem fogok ModuleNotFoundError hibákat kapni. Tehát ez vonatkozik minden modulra, ami nincs beépítve a Python verziódban. Ebben az esetben az alpaca-create-api valószínűleg nincs beépítve. Tehát csak ezt akartam érinteni, mielőtt belekezdenénk az API megvalósításába. A leglogikusabb a Jupiter notebookban kezdeni. Tehát csak átmásolom ezt az egészet a Jupiter notebookomba. És az API-hoz lesz egy alap URL. És hiszem, hogy ez az alap URL, csak másolom és beillesztem. Az lesz a paper-alpaca, vagy a paper.api.alpaca.markets. Nagyon fontos, mert nem hiszem, hogy említettem, de kérlek, győződj meg róla, hogy a papírkereskedésen vagy. Nem fogsz messzire jutni, ha nem a papírkereskedésen vagy. És természetesen finanszírozhatsz egy élő számlát, és ugyanabban a kapacitásban kereskedhetsz élő számlával. De a fejlesztés kedvéért kezdjük a papír számlával. Tehát menj a papír számládhoz. Generálj API kulcsokat a papír számládhoz. Ha nem működik, és az élő számlán vagy, az valószínűleg azért van, mert nincs elegendő alapod. Csak győződj meg róla, hogy a papíron vagy, és görgesd le a végpontig. Ez lesz a végpont. alpaca.markets/v2. Tehát ezt lemásolom. Ezt ide illesztem be. És ezt fogjuk használni, hogy megpróbáljunk lekérdezni néhány adatot az Alpacától. Tehát azt fogom mondani, hogy api = tradeapi.REST. És használni fogom a kulcsomat, a titkos kulcsomat. Használni fogom az alap URL-t, és az API verzió valójában a kettő. Tehát ezt futtatni fogom. Minden rendben működik. És most ténylegesen létre fogunk hozni egy alap kérést ebből a trade API-ból, és megnézzük, kaphatunk-e néhány adatot. Adatok lekéréséhez létrehozunk egy funkciót. def get_data(self, symbol): Azt fogjuk mondani, hogy try: barset = api.get_latest_trade(symbol=symbol). Vissza fogjuk adni a price. barset.price. És akkor elfogadunk egy kivételt, mint e. Csak minden hibát elkapunk, és -1 árat adunk vissza. Most tesztelhetjük ezt a funkciót. Azt fogom mondani, hogy get_data('AAPL'). Nézzük meg az adatokat az Apple-hez. 213.96. És nézzük meg, hogy itt tudunk-e megnézni. [Zene] Apple 213.96. Körülbelül helyesnek tűnik. Tehát sikeresen lekérjük az élő adatokat az Alpacától. Most az a dolgunk, hogy integráljuk ezt a botunkba. Tehát ha itt megyünk az ellenőrzőlistánkra, csatlakoztunk egy brókercéghez API-n keresztül. Ez pontosan az, amit itt tettünk. Most ténylegesen integrálnunk kell a botunkba, hogy biztosítsuk, hogy vételi megbízásokat helyezünk el minden általunk létrehozott szinten. Azt is biztosítanunk kell, hogy helyesen frissítsük a belépési árat az adatainkban. Tehát ha emlékszel, amikor futtatjuk ezt a kereskedési botot, jelenleg, amikor létrehozok egy Apple-t, hozzunk létre egy rendszert az Apple-hez. Itt létrehozza a szintjeimet, de a belépési ár nyilvánvalóan rossz. A rendszer állapota természetesen ki van kapcsolva. De amit tennünk kell, az az, hogy amikor bekapcsoljuk, szeretnénk biztosítani, hogy vételi megbízásokat helyezzünk el minden szinten, és szeretnénk frissíteni ezt a belépési árat a tényleges belépési árral, amit kitöltöttünk. És ehhez azt tehetjük, hogy egyszerűen végigmegyünk az Alpaca-tól az összes belépési áron a részvényünkhöz az adott rendszerben. Tehát ebben az esetben a rendszer az Apple-hez van. Végigmegyünk az összes belépési áron, vesszük a maximumot, és ez lesz az első belépési ár. Aztán lesznek ezek a szintek, amelyek megbízásokat töltenek ki, és nyomon követjük a mennyiséget minden szinten, hogy biztosítsuk, hogy ne helyezzünk el több mint egy megbízást. Biztosítani fogjuk, hogy minden alkalommal, amikor futtatjuk ezt a rendszert, végigmegyünk az első belépési ártól, és biztosítjuk, hogy oké, ha vannak aktív megbízások, nem fogunk több aktív megbízást elhelyezni. És akkor minden rendben lesz a kereskedési oldalon, és eljuthatunk az AI komponenshez. Oké, az első dolog, amit hozzá kell adnunk a kereskedési botunkhoz, egy funkció, amely ellenőrzi, hogy létezik-e már egy megbízás egy adott ár szinten. Tehát azt fogjuk tenni, hogy hozzáadjuk, talán alulra adjuk hozzá. Adjuk hozzá itt, a send_message után. Azt fogjuk mondani, hogy def check_existing_orders(self, symbol, price): Azt fogjuk mondani, hogy try. És itt fogjuk ténylegesen használni az Alpaca API-t. Tehát ha itt felgörgetünk, tudnod kell, hogy hozzá kell adnunk az Alpaca API-t, ahogyan itt használtuk. Tehát ezt a kódsort fogom másolni. Ezt a titkos kulcs alá fogom beilleszteni, hogy használhassuk. Szükségem van az alap URL-re is, hogy használhassuk ezt az API végpontot. Aztán görgessek lefelé, és megpróbáljuk lekérni a megbízásokat a fiókunkból. api.list_orders(status='open', symbol=symbol). For order in orders: Ellenőrizni fogjuk, hogy a float(order.limit_price) megegyezik-e az általunk ellenőrzött árral. Ebben az esetben true-t adunk vissza, és ez azt jelenti, hogy egy megbízás már létezik ehhez a szinthez, és nem akarjuk. Csak egy általános kivételt fogunk elkapni, és azt fogjuk mondani, hogy API hiba van, és van egy hiba a megbízások ellenőrzésében. És ez a hiba az e lesz. Hozzáadhatjuk ezt f-stringként. Különben false-t adunk vissza, és ez azt jelenti, hogy ebben a szinten megbízást kell elhelyeznünk. Oké, ez az első használata az API-nak a kereskedési botunkban. Tudnod kell, hogy ha itt felmegyünk, láthatod, hogy ott van a kulcsunk, titkos kulcsunk, alap URL-ünk és az API a beimportálások alatt. Aztán ha legörgetsz oda, ahol hozzáadtuk ezt a funkciót a kereskedési bot osztályhoz, akkor láthatod, hogy van egy szimbólumunk, egy ár. Végigmegyünk az összes megbízáson a szimbólum alapján, amelyek nyitva vannak, és ellenőrizzük, hogy oké, a megbízás limit ára megegyezik-e az általunk a funkcióban megadott árral. Ha igen, true-t adunk vissza, és hé, nem fogunk megbízást elhelyezni ebben a szinten. Különben false-t adhatunk vissza, és bármilyen hibát csak egy üzenetdobozban jelenítünk meg, amely jelzi, hogy API hiba van. Ez az első használata az Alpaca-nak a kereskedési botunkban. Szükségünk lesz az aktuális árazási információk lekérésére is egy kezdeti megbízás beállításához. Tehát azt fogjuk mondani, hogy def fetch_market_data. Azt hiszem, fetch_alpaca_data-nak kellene hívnunk. Tudom, hogy get_data-nak hívtuk a jupyter notebookunkban. Ez igazán önkényes. fetch_alpaca_data. Azt fogjuk mondani, hogy self, symbol. Aztán azt fogjuk mondani, hogy try. És ez pontosan ugyanaz, mint amit itt írtunk. Tehát csak másolom és beillesztem. Tehát a get_data funkciót fogjuk használni a barset lekéréséhez egy szimbólumhoz, és ez lehetővé teszi számunkra az aktuális árazási információk lekérését. Oké, most már van árazási információnk. Van lehetőségünk ellenőrizni a megbízásokat, és létre kell hoznunk a funkcionalitást egy megbízás elküldéséhez egy kezdeti belépési árhoz, és aztán ezen a kezdeti belépési áron alapulva frissítenünk kell az adatokat a háttérben, beállítani a szintjeinket, és aztán több kereskedést elhelyezni. Oké, úgy tűnik, szükségünk van még néhány dologra. Létrehozunk egy segédfunkciót a maximális belépési ár lekéréséhez. get_max_entry_price(self, symbol). Azt fogjuk mondani, hogy try. orders = api.list_orders(status='filled', symbol=symbol, limit=50). A szintek lesznek a megbízások átlagos kitöltési ára. order.filled_average_price. És ez lesz for order in orders. Ha order.filled_average_price van, más szóval, feltételezve, hogy van egy átlagos kitöltési ár, akkor végigmegyünk, és ellenőrizzük, hogy melyik a legmagasabb, mert ott léptünk be először a részvény pozícióba. És a csökkenés alapján kereskedni fogunk. Vissza fogjuk adni a max(prices). Ha prices, különben csak nullát fogunk csinálni. Tehát ha üres, csak nullát fogunk visszaadni. Igazából valószínűleg -1-et kellene visszaadnunk. Oké. except Exception as e. És ez csak egy üzenetdoboz lesz, amely jelzi, hogy API hiba történt. És ez egy hiba lesz. affection orders as e. És akkor csak nullát fogunk visszaadni onnan, mint egy másik hibakódot. És ez az, amit használni fogunk a maximális belépési ár lekéréséhez. Tehát van lehetőségünk ellenőrizni a meglévő megbízásokat, van lehetőségünk lekérni az árinformációkat, és a maximális belépési ár ellenőrzésének képességét egy szimbólumhoz. Oké, némi házimunkát. Úgy tűnik, hogy a v2 kétszer van megadva. Ez volt a hibám. Tehát ez valójában hozzá fogja fűzni ezt az URL-hez. Tehát eltávolíthatjuk ezt a v2-t innen. Továbbá, ha legörgetünk, azt hiszem, elfelejtettem az első add funkcióban a csökkenés hozzáadását. Ostoba. Adjunk hozzá csökkenést, ahogy csökkenünk. Így elmenthetjük azt az értéket, és később felhasználhatjuk. Frissítjük ezt a get_max_entry_price funkciót is. Ahelyett, hogy a szimbólumot szűrnék az API hívásban, eltávolítom azt, és azt fogom mondani, hogy ha az order.average_price létezik, és az order.symbol megegyezik a szimbólummal, amit szűrünk, akkor figyelembe vesszük az árlistában, és vesszük a maximális árat. Ez lesz az első.

belépési ár, majd vásárlási megbízásokat fogunk elhelyezni minden szinten, amely megfelel az általunk kezdetben beállított csökkenésnek, rendben, a kereskedési rendszer utolsó szakasza önmagában, itt létre kell hoznunk egy új függvényt, ez valószínűleg a legösszetettebb függvény lesz, ezt trade system-nek fogjuk hívni, és végigmegyünk az összes soron, tehát azt fogjuk mondani, hogy a symbol data a self. equities do items-ben, akkor azt fogjuk mondani, hogy ha a rendszer állapota egyenlő a bekapcsolttal, ez azt jelenti, hogy kereskedünk, azt fogjuk mondani, hogy kezdetben nincs pozíció, megpróbáljuk lekérni a pozíciót az API-ból, a belépési árat fogjuk lekérni a maximális belépési árként, beállítjuk a pozíciót, a pozíció létezik zászlót igazra állítjuk, mindennek hiba nélkül kell futnia, ha nincsenek aktív pozícióink, nem találunk adatokat, tehát elfogadhatjuk a kivételt e-ként, és azt mondhatjuk, hogy api. submit order, és itt elhelyezünk egy kezdeti piaci megbízást, tehát azt mondjuk, hogy a szimbólum egyenlő a szimbólummal, ez az a szimbólum, amit ebben a rendszerben létrehozunk, a mennyiség egyenlő eggyel, ez az oldal vásárlás lesz, piaci megbízást fogunk használni, és az idő és az erő jó lesz a törlésig, tehát ez a mi kezdeti megbízásunk, hozzáadhatunk egy üzenetdobozt az általunk elhelyezett információk megjelenítéséhez, tehát ezt a megbízást elhelyezettnek hívjuk, ez a mi kezdeti megbízásunk, tehát azt mondhatjuk, hogy kezdeti megbízás elhelyezve a szimbólumra, alszunk 2 másodpercet, hogy kitöltődjön, majd azt mondhatjuk, hogy a belépési ár egyenlő a self. Max entry price szimbólummal, és ez remélhetőleg a mi kezdeti belépési árunk lesz a megbízás alapján, az általunk itt benyújtott kezdeti megbízás alapján, kinyomtathatnánk a belépési árat is, tehát kinyomtathatjuk a belépési árat, most ezen alapul generáljuk a szinteket, tehát ez nagyjából az, amit korábban írtunk, de valójában az igazi árra alkalmazzuk, tehát azt fogjuk mondani, hogy a szintárak egyenlőek lesznek az I + 1-gyel, majd kerekítjük a belépési árat * 1 mínusz a megadott csökkenés, amikor létrehoztuk azt az equity rendszer időt I + 1, majd kerekítjük azt kettőre, és ez az I tartományban lesz, és ez lesz a szintek hossza, tehát az adatszintek, tehát a szintek száma alapján meg akarjuk őrizni a meglévő szintjeinket, tehát azt fogjuk mondani, hogy a meglévő szintek egyenlőek a self. equities do get symbol egy üres szótárral. getet levels, és most végigmegyünk a szintárakon, tehát azt fogjuk mondani, hogy a szint az vagy azt mondjuk, hogy szint és ár a szintárak. do items-ben, azt fogjuk mondani, hogy ha a szint a self. equities symbol alapján, amit kereskedünk a szintek alapján, ha ez létezik, akkor megbízást fogunk elhelyezni, megbízást fogunk elhelyezni a szimbólumon az áron és természetesen azon a szinten, amint ezt megtesszük, biztosítani akarjuk, hogy [Zene] mentsünk, biztosítani akarjuk, hogy mentsük ezt az információt, tehát self. save equities, azt is frissíteni akarjuk a táblát, és ez a for ciklusban lesz, tehát ez biztosítja, hogy összhangban legyen az if utasítással itt, biztosítani fogjuk, hogy mentsük az információt és frissítsük a táblát a szintárhoz, gondolom, frissítenünk kell az equity adatokat is, tehát ezt valóban el kell végeznem mentés előtt, tehát azt mondom, hogy a szint és a szintek, megvannak a meglévő szintjeink, igaz, tehát a szint és a szintárak esetén, ha a szint rendben, látom, mi történik itt, tehát valójában ez a szintárak és a szint elemeknek kellene lennie, ha a szint nincs a meglévő szintekben, és a negatív szint nincs a meglévő szintekben, akkor a meglévő szintek egyenlőek lesznek a szintárral, ez értelmes, és akkor a self. equities symbol a belépési ár, és itt fogjuk frissíteni az adatokat az igazi belépési árra, self. self. equities symbol, ez lesznek a szintek, frissítjük a szinteket a meglévő szintekre, és akkor frissítjük a pozíciót egy zászlóval, hogy jelezzük, hogy aktív pozícióban vagyunk, most elhelyezzük a megbízást, tehát most, hogy megvannak a szintek, amelyeken a megbízásokat el kell helyezni a kezdeti belépési ár alapján, és ez a kezdeti belépési ár a maximális belépésen alapul, végigmehetünk itt, és azt mondhatjuk, hogy a szintárak és a szintár. do items, azt fogjuk mondani, hogy ha a szint a self. equities symbol levels létezik, akkor elhelyezhetünk egy megbízást, place order, és elhelyezünk egy megbízást a szimbólumon az áron és a szinten, csodálatos, és akkor továbbmegyünk, és elmentjük az itt frissített equity adatokat, frissítjük a táblát, és azt is visszaadjuk, ha a rendszer ki van kapcsolva, tehát ez az, ha a rendszer be van kapcsolva, akkor végigmegyünk ezen az argumentumon, hogy megpróbáljuk kereskedni, egyébként csak semmit sem adunk vissza, most írni kell egy függvényt a megbízás elhelyezésére, tehát veszünk egy szimbólumot, egy árat és egy szintet, és ez lehetővé teszi az adatok frissítését a háttérben, tehát azt fogjuk mondani, hogy ha van egy negatív szint a self. equities-ben, ez azt jelenti, hogy van egy aktív megbízásunk azon a szinten, és nem akarunk kereskedni, és ez lehet sztring vagy egész szám reprezentáció, tehát mindkettőt tartalmazni fogom attól függően, hogy újra betöltötted-e a rendszert, rendben, tehát ha vannak aktív megbízásaink, akkor csak visszaadjuk, egyébként megpróbálhatjuk benyújtani a megbízást, és benyújtjuk a megbízást minden szinten iteratívan, ez az, amit ez a trade system függvény csinál, végigmegy minden szinten, és itt azt fogjuk mondani, hogy try API submit order, benyújtunk egy megbízást, ahol a szimbólum egyenlő a megadott szimbólummal, és akkor a mennyiség egyenlő eggyel, az oldal buy, a típus limit, az idő és az erő jó lesz a törlésig, és a limit ár természetesen az az ár lesz, amit argumentumként átadtunk ennek a függvénynek a trade system függvényből, és most meg kell jelölnünk a szintet az adatokban, hogy frissíthessük a felhasználói felületet, tehát azt mondjuk, hogy self. equities symbol, frissítjük a szinteket, negatív szintté tesszük, hogy jelezzük, hogy aktív pozícióban vagyunk, beállítjuk az árat az árra, töröljük az eredeti pozitív szintet, töröljük az eredeti pozitív szintet, és akár nyomtathatunk is, ha úgy döntünk, hogy megbízást helyezünk a szimbólumra, és csak a limit árat adjuk meg, és ha ez nem működik, akkor csak egy üzenetdobozt fogunk megjeleníteni. show error, és akkor a hiba a megbízási hiba lesz, és bármi is legyen a válasz, és ez megteszi, tehát ezek valószínűleg a legösszetettebb függvények, nem meglepő módon, ellenőrizni fogjuk, hogy a pozíció létezik-e, tudod, ez valahogy be van építve ebbe a függvényhívásba, tehát tudod, hogy nem igazán szükségünk van egy if utasításra közvetlenül, és akkor végigmegyünk ezen az egész argumentumon, hogy beállítsunk egy kezdeti megbízást, azt állítsuk be belépési árként, hozzunk létre szinteket az új belépési ár alapján a csökkenésünk alapján, hogy több pozíciót helyezzünk el abban az equity-ben, és akkor létrehozzuk ezt a függvényt itt, amely iteratívan frissíti, sajnálom, a trade system iteratívan helyezi el a megbízásokat, és frissítjük a szintet a place order függvényben, és ez a szint pozitív lesz, ha nyitott megbízást kell létrehozni, vagy negatív, ha nyitott megbízás már létezik, az utolsó dolog, amit tenni kell, úgy tűnik, elfelejtettem egy for-t, egy col-t ide, az utolsó dolog, amit itt tennünk kell, az az, hogy görgetünk lefelé a scroll down to the def auto update függvényhez, és már frissítettem itt self. trade systems, azt hiszem, ez self. update prices volt, tehát csak ezt fogod lecserélni self. trade systems-re, rendben, úgy tűnik, ezt trade systems-nek hívtam, és ez valójában trade systems-nek kellene lennie, mert minden rendszert iterálunk, rendben, tehát most van trade system systems trade system, ha ezt a srácot futtatom, akkor létrehozok egy alma kereskedést öt szinten, 5%-os csökkenéssel a kezdeti belépési ártól, hozzáadjuk, az állapota jelenleg ki van kapcsolva, tehát nem fogunk semmit kereskedni minden alkalommal, amikor a rendszer frissíteni próbál, tehát bekapcsolom, kapok egy kezdeti elhelyezett megbízás üzenetet, ha megyek az alpakához, láthatjuk, hogy elhelyeztem egy megbízást az almára itt, úgy tűnik, hogy kapunk egy kis kulcshibát, tehát van egy kulcshibánk a szinthez, mert a szinthez van egy kulcshiba, mert a szinteknek kellene lennie, nem a szintnek, elnézést kérek, ez szinteknek kellene lennie, nem szintnek, el fogom távolítani ezt az alma ticker-t, törölni fogom azt a megbízást az alpakán, hogy töröljünk egy megbízást az alpakán, csak annyit kell tenned, hogy elmész a pozícióidhoz, törlés, törlés, minden nyitott, és akkor újra próbálkozhatunk, tehát futtassam ezt újra, futtassam ezt a srácot, hozzunk létre egy új alma kereskedést, öt szint, 5% csökkenés, adjuk hozzá az equity-t, ott vannak az alapértelmezett adatok, alapértelmezett szintek, bekapcsoljuk, kapunk egy kezdeti belépési árat, jó, ott van a kezdeti megbízásunk, megyünk az alpakához, látjuk, hogy az alma kereskedésünk kitöltődött, és most látjuk, hogy megbízásokat helyeztünk el a következő szinteken, tehát ha visszamegyünk a [Zene] az alpakánkba, itt láthatod a legutóbbi megbízásokban az 1, 2, 3, 4, 5 megbízásunkat, és ezek a limiteken vannak elhelyezve a felhasználói felületünkön beállított csökkenés alapján, és amint láthatod, most nem helyezünk el több megbízást, minden helyesnek kell lennie, és készen állunk arra, hogy ezek a megbízások kitöltődjenek, és módosíthatjuk őket tetszés szerint, új rendszereket adhatunk hozzá a kereskedési botunkhoz, ha akarnánk, kilépési feltételeket adhatnánk hozzá, bármit tehetnénk, itt vannak a szintárak, amelyek megfelelnek a limitároknak, negatív kulcsok annak biztosítására, hogy ne helyezzünk el újra megbízásokat, sőt, ha kikapcsolom és újra bekapcsolom, látni fogod, hogy újra gyűjti a megfelelő szinteket és szintinformációkat, azt is látni fogod, hogy nem helyez véletlenül több kereskedést, nem helyezi el ezeket a kereskedéseket a szinteken, tehát sikeresen megépítettük a kereskedési botunkat, hozzáadhatok más equity-ket is, itt van egy a J&J-re, ez is elhelyez egy kezdeti kereskedést, ha bekapcsolom, tehát amint bekapcsoljuk, itt van a kezdeti megbízásunk a Johnson & Johnson-ra, majd frissíti a szinteket, és boom, készen állunk, tehát most sikeresen megépítettük a botunk kereskedési komponensét, és továbbléphetünk a mesterséges intelligencia komponenshez, az AI portfóliókezelő komponenshez, rendben, tehát két dolgot elintéztünk, hármat elintéztünk, négyet fogunk csinálni, és készen állunk, futtathatjuk ezt a srácot, tehát természetesen telepítenünk kell az open AI-t, hogy ne kapjunk modul nem található hibát, tehát telepíteni fogjuk az open AI-t, miután ez rendben van, azt fogjuk csinálni, amit korábban tettünk, és létrehozunk egy új Jupiter notebookot, és ott lesz az open. iynb, és itt tesztelhetjük az API-t, mielőtt integrálnánk a botunkba ebben a jupyter notebookban megpróbáljuk integrálni az open AI API-t, és szükséged lesz egy API kulcsra az openai-től, ez a platform. open.com API keys, ahová elmehetsz és megszerezheted, én ezt a titkos kulcsot fogom használni itt, ezt később törölni fogom, de ez az a kulcs, amit használni fogok, lehet, hogy fizetős fiókra lesz szükséged ehhez, van egy fizetős chat GPT előfizetésem, de ettől függetlenül bármilyen LLM-et használhatsz, amit szeretnél, nem kell, hogy chat GPT legyen, én csak az egyszerűség kedvéért fogom használni, rendben, importáljuk az open AI-t, és az open AI futtatja ezt a srácot, győződjünk meg róla, hogy minden helyesen importálódott, jó, és most létrehozunk egy függvényt def get, talán hívjuk send, talán analyze message, hívjuk analyze message, vegyünk egy üzenetet bemenetként, és ez az, ahol valójában [Zene] küldjük ezt a bemeneti üzenetet, de előre is megadunk az LLM-nek az információt, amiről spekulálnia kell, ez egy pillanat múlva értelmet fog nyerni, tehát tudod, hogy létre kell hoznunk valamilyen portfólió adatot, és a nyitott megbízásainkat is figyelembe kell vennünk, tehát amit tenni fogok, azt mondom, hogy a portfólió adatok egyenlőek a fetch portfolio-val, és akkor azt mondom, hogy a nyitott megbízások egyenlőek a fetch open orders-szel, és ez fogja megkapni a fiókunk aktuális információit, és lehetővé teszi az LLM számára, hogy lényegében a portfóliókezelőnkként működjön, az előre megadott utasításaink sztringek lesznek, csak sztringgé tesszük, és minden információt tartalmazni fog a fiókunkról, de adunk neki egyfajta blanket utasítást is, tehát azt mondjuk, hogy te egy AI portfóliókezelő vagy, aki felelős a portfólióm elemzéséért, a feladataid a következők: 1. Értékeld a jelenlegi birtokaim kockázati kitettségét. 2. Elemezd a nyitott limit megbízásaimat és azok lehetséges hatását. 3. Adj betekintést a portfólió egészségébe, diverzifikációjába, kereskedési kiigazításaiba stb. 4. mondhatjuk, talán össze fogom ezt csukni, hogy lássuk, stb. 5. Spekulálj a piaci kilátásokról a jelenlegi piaci feltételek alapján, és talán 5. azonosítsd a lehetséges piaci kockázatokat és javasolj kockázatkezelési stratégiákat, összességében válaszolj a következő kérdésre prioritással, figyelembe véve ezt a hátteret, és ez csak az üzeneted lesz, rendben, hozzáadhatod ide is: itt van a portfólióm, és ez lesz a mi portfólió adatunk, itt van a mi portfólióm, itt vannak a nyitott megbízásaim, hoppá, le kell görgetnem, itt vannak a nyitott megbízásaim, add meg a nyitott megbízásokat, tehát megkapjuk a nyitott megbízásokat, megkapjuk a portfólió adatokat, megadjuk a promptnak, és akkor azt akarjuk, hogy válaszoljanak a felhasználó üzenetére a űrlapba bevitt alapján, rendben, ez megteszi, most a válasz lesz az open ai. chat completion. create, és létrehozunk egy új munkamenetet itt, a modell egyenlő gp4, majd azt mondjuk, hogy üzenetek egyenlőek lesznek, lesz ez a szótár szabály, és akkor ott van a rendszer, és akkor a tartalom az előre megadott utasítás lesz, és akkor azt mondhatjuk, hogy az API kulcs egyenlő ez az őrült API kulcs, amit ebből a fejlesztői portálról másoltam, rendben, akkor az elemzésnek csak [Zene] egyenlőnek kell lennie a Gap portfólióval, vagy mit hívunk ennek az analyze message-nek, hogyan van a portfólióm, hogyan van a [Zene] portfólióm, most létre kell hoznunk ezeket a függvényeket az adatok tényleges lekéréséhez, tehát a portfólió adatok lekéréséhez létre kell hoznunk a def portfolio-t, és ez csak pozíciók lesznek, egyenlő api. list positions, portfolio egyenlő semmi, és akkor azt mondjuk, hogy a pozíció pozícióban, csak hozzáadjuk az összes információt a portfólióhoz, szótárként, tehát a szimbólum egyenlő lesz a position. symbol, a mennyiség egyenlő lesz a position. quantity, a belépési ár egyenlő lesz a pos. average entry price, az aktuális ár egyenlő lesz az aktuális árral, az unrealizált pnl egyenlő lesz az unrealizált pnl-lel a pozíciónkból, illetve, és akkor természetesen az oldal, amely hosszú vagy rövid lesz, ebben a rendszerben mindent csak hosszú lehet, rendben, tehát ez lesz a mi portfólió, és ezt a portfóliót adjuk vissza, és ezt a portfóliót használjuk az előre megadott utasításunkban, és akkor pontosan ugyanazt tesszük a nyitott megbízásokkal, és ez sokkal könnyebb, mert tudod, hogy csak annyit kell tennünk, hogy orders equal to api. list orders status equal to open, és akkor csak azt mondhatjuk, hogy open orders equal to egy üres lista, és akkor azt mondjuk, hogy a rend order in orders, csak csinálhatjuk az open orders. append, csak hozzáadjuk azt a szótárat, ahogy korábban tettük, ahol a szimbólumunk az order. symbol, a mennyiség az order. quantity, a limit ár az order. limit price, és az oldal mindig hosszú lesz itt, tehát azt hiszem, hogy buy ebben az API-ban, tehát csak hagyom az oldalt buy-ként, ez rendben lesz, rendben, és akkor nyilvánvalóan az API nincs ebben a jupyter notebookban, tehát visszamegyek az alpakka notebookba, és kimásolom az összes információt, ami létrehozta azt az objektumot, futtatom itt, és képesnek kell lennünk arra, hogy ténylegesen választ kapjunk ettől a srácról, tehát nézzük meg, rendben, ez az API eltávolítva a V1-ben, tehát telepítenem kell a 28-as verziót, tehát ezt fogom tenni, open AI egyenlő egyenlő 0.28, tehát ezt a pip install-t fogom futtatni helyette, és akkor újraindítom ezt, tehát csak ezt a pip install-t futtattam, pip install openingi egyenlő egyenlő 0.28, mert verzióproblémám volt, úgy tűnik, futtatom ezt a srácot, futtatom ezt a srácot, futtatom ezt a srácot, nézzük meg, kapunk-e választ a portfóliónk alapján, rendben, nézzük meg az elemzést, és elfelejtettem visszaadni a választ, tehát ez azt fogja eredményezni, hogy az elemzés üres lesz, tehát visszaadom a válasz választásokat, ezt a részt szerkeszteni fogom, mert ott ültünk kb. 20 másodpercig, tehát choices zero message és content, ez fogja ténylegesen visszaadni az információt ehhez az elemzéshez, tehát próbáljuk meg újra, nem hiszem el, hogy elfelejtettem a visszatérési utasítást, ez magyarázza, miért volt ez üres, egy kis időbe telik, futtatom ezt, elemeztem a portfóliómat, és boom, itt vannak a kockázati kitettségek, használj koncentrált pozíciót, és így tovább, szóval elég klassz, most van egy módunk arra, hogy az AI spekuláljon a portfólióról, rendben, integrálnunk kell ezt a kereskedési botunkba, hogy működjön, és akkor készen leszünk, és van egy AI kereskedési botunk, amely képes kereskedéseket elhelyezni és kezelni a portfóliómat, elemezni a portfóliómat, tehát amit tenni fogok, először is bemásolom ezeket a fetch portfolio függvényeket, ezek csak olyan függvények, amelyek létezhetnek a kereskedési bot osztályon kívül, és én fogom helyettesíteni, valójában nincs szükségünk ezekre többé, még mindig vannak helyőrzők különböző kezdeti hívásokhoz a kereskedési bot osztályunkban, tehát hagyom őket egyelőre, és ezeket a fetch portfolio és fetch open orders függvényeket közvetlenül az alpaca API definíciója alá helyezem, hasonlóan, definiálom az open AI csomagot is, tehát azt mondom, hogy import open Ai, és visszamegyek ide, és csak létrehozom ezt a függvényt, analyze message, tehát csak bemásolom az egész srácot ide, turn response, minden rendben kell, hogy legyen, tehát bemásolom, visszajövök a botba, és vegyük figyelembe, hogy ez a mock válasz a kezdeti üzenetre, ehelyett tényleges választ adhatunk, tehát a válasz itt, ez az elemzés, amit elemzésbe tároltunk, és ez volt a válasz, tehát valójában a megfelelő választ adja vissza az LLM-től, tehát ide jövök, és csak lecserélem ezt a mock chat GPT response-ra, tudod, ha különösen lusta vagyunk, csak így hagyhatjuk, de ezt hívom track GPT response-nak, megtalálom azt a mock track GPT response-t, ahol valójában definiáltuk azt a send message függvényt, és hívom azt cck GPT response-nak, mert ez már nem egy mock függvényhívás, ez egy igazi függvényhívás, és ez megteszi, ez megteszi, tehát ez lesz az igazság pillanata, nézzük meg, futtathatjuk-e ezt, létrehozunk egy rendszert, megvan az AI portfóliókezelőnk itt, megkérdezhetjük, hogy néz ki a kockázati kitettségem, ha J&J-t és almát is tartok, tehát elküldhetjük ezt, ez eltart egy ideig, amíg feltöltődik, és itt van, az AI portfóliókezelőnk válaszol a kérdésünkre az előre megadott utasításunk alapján, és ez egy elég terjedelmes válasz, előre megadhatod, hogy rövidebb legyen, kérdezhetsz célzottabb kérdéseket, vagy akár általánosabbá teheted, de ez egy AI kereskedési bot, van egy kereskedési botunk, amely sikeres, vagy valóban egy rendszert építettünk a semmiből, megépítettük a felhasználói felületünket, megépítettük a kereskedési komponenst, tehát ott van az automatizált kereskedési komponens, és van a portfóliókezelő komponensünk is, az AI portfóliókezelő, aki elemezheti a kockázatunkat és a kockázati kitettségeinket, annyi mindent lehet építeni erre az alapvető platformra, kilépési feltételeket adhatsz hozzá, eseményeket adhatsz hozzá, hogy a nagy nyelvi modell ténylegesen végrehajthasson kereskedéseket, annyi mindent tehetsz, élő hírfolyamok alapján, aktuális makro tényezők alapján, csak végigmehetsz a soron, de ez valószínűleg a legtöbb, ez egy workshop videó, valóban, ezt az egész rendszert a semmiből építettük fel, ezt a GitHub-ra fogom feltenni, tehát természetesen hozzáférhetsz az összes kódhoz, de ez valami elég klassz dolog, ember, nagyon remélem, hogy élvezted ennek a srácnak az építését velem, vagy ha csak a végeredményt nézed, remélem, hogy élvezed a funkcionalitás látványát, lényegében azt tettük, hogy ezt a felhasználói felületet a semmiből építettük fel, van lehetőségünk kereskedési rendszert definiálni egy adott equity-re, meghatározzuk azokat a szinteket, amelyeken kereskedni akarunk, az egyes szintekhez tartozó csökkenési százalékot, majd a rendszerünk automatikusan elhelyezi ezeket a kereskedéseket az alpakával, elhelyez egy kezdeti megbízást, ez a mi belépési árunk, és meghatározza a szinteket a belépési ár alatt, és ezt minden equity-re elvégzi a portfóliónkban, itt, be- és kikapcsolhatjuk a rendszereket tetszés szerint, és akár el is távolíthatjuk őket, és így tovább, és van ez az AI portfóliókezelő komponensünk is, ez az AI, ez az AI aspektus, ahol van egy LLM, LLM integrálva a kereskedési rendszerünkbe, és valós időben kapja meg a portfóliómat és a kereskedéseimet, tudod, ahogy kérdéseket teszünk fel neki, tudja, mi történik az előre megadott utasításunk alapján, tehát ezt mondva, remélem, hogy élvezted ezt a videót, ahol együtt építettünk egy AI kereskedési botot, ha érdekelnek hasonló videók a jövőben, kérlek, szólj, és szívesen elkészítem őket, tudom, hogy ez elég hosszú volt, de szerintem a végeredmény elég klassz, és akár építhetünk is rá, talán csinálunk valamilyen jel feldolgozást egy talán csinálunk valamilyen belépési kilépési feltételt az LLM alapján, igazán végtelen számú módon mehetünk tovább, tehát remélem, hogy élvezted ezt a videót, ez egy elég hosszú volt, de mint mondtam, szerintem a végeredmény elég klassz, és csak szeretnék nagyon megköszönni a nézést, és a következő videóban találkozunk.