LangChain Deep Agents ile Çoklu Ajanlı Ticaret Araştırma Sistemi Kurulumu

LangChain Deep Agents ile Çoklu LangChain Deep Agents ile Çoklu kapsamında, Bir ticaret araştırma temsilcisi, strateji kodu yazabilir, bir arka test gerçekleştirebilir, sonuçları inceleyebilir ve stratejiyi gözden geçirmeye devam edebilir. Daha zor olan sorun, bu döngünün…

10
Paylaş
LangChain Deep Agents ile Çoklu Ajanlı Ticaret Araştırma Sistemi Kurulumu

LangChain Deep Agents ile Çoklu

LangChain Deep Agents ile Çoklu kapsamında, Bir ticaret araştırma temsilcisi, strateji kodu yazabilir, bir arka test gerçekleştirebilir, sonuçları inceleyebilir ve stratejiyi gözden geçirmeye devam edebilir. Daha zor olan sorun, bu döngünün çekici bir geriye dönük test için kontrolsüz bir aramaya dönüşmemesini sağlamaktır. Bu el kitabında LangChain Deep Agents ile çok temsilcili bir ticaret araştırma sistemi oluşturacağız.

LangChain Deep Agents ile Çoklu kapsamında, EODHD geçmiş piyasa verilerini sağlarken, deterministik bir Python katmanı veri bölümlerini, geriye dönük test mantığını, kıyaslamaları, deney geçmişini ve strateji seçim kurallarını kontrol edecektir. Daha sonra bir koordinatör, strateji mühendisi ve araştırma eleştirmeni bu sınırlar içinde çalışarak üç strateji versiyonunu geliştirecek ve değerlendirecek.

LangChain Deep Agents ile Çoklu kapsamında, Amaç, yapay zeka temsilcilerinin karlı stratejileri güvenilir bir şekilde keşfedebileceğini kanıtlamak değil. Temsilcilerin, fikirleri yargılamak için kullanılan kanıtları kontrol etmelerine izin verilmeden fikirler üretip bunlara meydan okuyabilecekleri bir araştırma iş akışı oluşturmaktır.

Tasarım ve teknik ayrıntılar

LangChain Deep Agents ile Çoklu kapsamında, Paylaşılan Geriye Dönük Test Motoru Oluşturun 2. Portföy Muhasebesini Doğrulayın 3. Sabit Karşılaştırmalar Oluşturun 4. Her Stratejiyi Yalıtılmış Bir Alt Süreçte Çalıştırın 5.

LangChain Deep Agents ile Çoklu kapsamında, Yürütme Eşliğini ve Veri Sınırlarını Doğrulayın Deney ve Karar Katmanını Oluşturun 1. Deney Kaydı Oluşturun 2. Araştırma Araçlarını Oluşturun 3. Stratejiyi Sabitleyin y Seçim Kuralı Manüel Temel Çizgiyi Oluşturun Derin Temsilci Araştırma Ekibini Yapılandırın 1. Temsilci Rollerini ve Sınırlarını Belirleyin 2.

LangChain Deep Agents ile Çoklu

LangChain Deep Agents ile Çoklu kapsamında, Koordinatörü Oluşturun Manuel Temel Çizgiyi v1 olarak Oluşturun Temsilcilerin Stratejiyi Revize Etmesine İzin Verin v2’de Piyasa Rejimi Filtresini Test Edin v3’te Son Revizyonu Çalıştırın Şampiyonu Dondurun ve Bekletmenin Kilidini Açın Tüm Araştırma İzini Denetleyin Sonuç Önkoşullar Başlamadan önce aşağıdakilere sahip olduğunuzdan emin olun: Python 3.11 veya üstü A Python, pandalar ve niceliksel geriye dönük testlerin temel anlayışı Geçmiş pazar verileri için bir EODHD API anahtarı Deep Agents modelleri için bir OpenAI API anahtarı İzlemenin etkinleştirilmesini istiyorsanız bir LangSmith API anahtarı Pandalar, numpy, matplotlib, requestler, python-dotenv, langchain, langgraph ve deepagent’lar dahil olmak üzere yüklü gerekli Python paketleri Ayrıca, ortam değişkenleriyle çalışma ve yerel dosyalar ve alt işlemler oluşturan Python kodunu çalıştırma konusunda rahat olmalısınız.

Bugünden bakınca ne kadar güvenilir?

Araştırma İş Akışını Tasarlayın Herhangi bir aracı kodu yazmadan önce, aracıların gerçekte neyi kontrol etmesine izin verildiğine karar vermemiz gerekir. İş akışının tamamı şu şekilde görünecektir: Sürüm akışı kasıtlı olarak sıralıdır. v1 önce uygulanıp test edildi, ardından araştırma eleştirmeni tarafından incelendi ve ilk şampiyon olarak kaydedildi. Ancak bu üç adım tamamlandıktan sonra v2 başlayabilir.

Aynı döngü v2 için tekrarlanır: Mühendis revizyonu uygular ve test eder, eleştirmen ise revizyonu uygular ve test eder. Kanıtları görüntüler ve koordinatör v3’ün başlamasına izin verilmeden önce seçim kuralını uygular. V3 test edilip incelendikten sonra koordinatör son seçimi yapar ve hayatta kalan stratejiyi ve parametreleri donmuş şampiyon olarak yazar.

Ancak o zaman son bir değerlendirme için uzatma verilerinin kilidi açılır. Bu sonuç öğrenildikten sonra strateji revize edilemez ve iş akışı, tüm araştırma izinin donma sonrası denetimiyle sona erer. Python Araştırma Ortamını Kurun İş akışının tamamında kullanılan paketleri içe aktararak başlayacağız.

Okuyucu için pratik anlamı

Deterministik araştırma katmanı, hesaplamalar için esas olarak pandalara ve NumPy’ye, EODHD verileri taleplerine, grafikler için Matplotlib’e ve araştırma eserlerini depolamak ve oluşturulan strateji kodunu ayrı ayrı çalıştırmak için Python’un dosya sistemi ve alt süreç yardımcı programlarına dayanır.

işletim sistemi, json, zaman, kapatma, geçici dosya, alt işlem, sys, traceback’i içe aktar importlib.util’i içe aktar pathlib içe aktarma yolundan içe aktarma istekleri, np olarak numpy, pd olarak pandalar matplotlib.pyplot’u plt olarak içe aktar dotenv içe aktarımından load_dotenv IPython.display’den içe aktarma Markdown, görüntüleme import getpass Yapı üç kimlik bilgisi kullanır: geçmiş pazar verileri için EODHD, aracı modelleri için OpenAI ve geliştirme sırasında iş akışını denetlemek için LangSmith izleme.

Kimlik bilgilerini doğrudan koda yerleştirmek yerine, bunları bir .env dosyasından yükleyeceğim ve ortam değişkenlerinde tutacağım. t’de Aynı zamanda, araştırma görevlilerinin kullanımına sunulan dosyaları, onların erişemeyeceği yerlerde kalması gereken her şeyden ayıracağım. çalışma alanı geliştirme ve doğrulama verilerini, strateji dosyalarını, sonuçları ve incelemeleri içerecektir.

özel, aracı çalışma alanına girmemesi gereken veriler için, en önemlisi de son duraklama için ayrılmıştır.

load_dotenv(geçersiz kılma=Doğru) [“EODHD_API_KEY”, “OPENAI_API_KEY”, “LANGSMITH_API_KEY”] içindeki k için: os.environ.get(k), f”eksik ortam var: {k}” os.environ[“EODHD_API_KEY”] = os.environ[“EODHD_API_KEY”].strip() os.environ[“LANGSMITH_TRACING”] = “doğru” LS_PROJECT = “derin ticaret temsilcisi” os.environ[“LANGSMITH_PROJECT”] = LS_PROJECT ROOT = Yol(“proje”).resolve() RAW = Yol(“raw_cache”).resolve() WS = KÖK / “çalışma alanı” ÖZEL = KÖK / “özel” [RAW, ÖZEL, WS/”veri”, WS/”stratejiler”, WS/”sonuçlar”, WS/”incelemeler”] içindeki p için: p.mkdir(ebeveynler=Doğru, mevcut_ok=Doğru) print(“workspace:”, WS) Buradaki önemli ayrım, klasör adlarının kendisi değildir.

Aracıya bakan dosya sistemi daha sonra çalışma alanına kök salacak, arabulucu ise araştırma süreci tamamlanana kadar onun dışında kalacak. .env kullanılamıyorsa veya kimlik bilgilerinden birinin değiştirilmesi gerekiyorsa bunun yerine anahtarları etkileşimli olarak girebiliriz. getpass bunları girilirken gizler ve sonraki çalıştırmalar için kaydeder.

[“EODHD_API_KEY”, “OPENAI_API_KEY”, “LANGSMITH_API_KEY”] içindeki k için: os.env iron[k] = getpass.getpass(f”{k}: “).strip() Path(“.env”).write_text(“n”.join(f”{k}={os.environ[k]}” for k in [“EODHD_API_KEY”, “OPENAI_API_KEY”, “LANGSMITH_API_KEY”]) + “n”) print(“openai doğru görünüyor:”, os.environ[“OPENAI_API_KEY”].startswith(“sk-“), len(os.environ[“OPENAI_API_KEY”])) Anahtarların kendileri hiçbir zaman çıktıda görünmez: Ortam hazır olduğunda, araştırma sisteminin üzerinde çalışacağı pazar veri setini oluşturmaya başlayabiliriz.

EODHD Araştırma Verilerini Hazırlayın Araştırma döngüsü, aracıların anlamlı tahsis kararları alabilmesi için yeterli çeşitliliğe ihtiyaç duyar, ancak evren deney boyunca sabit kalmalıdır.

Dokuz ABD hisse senedi ETF’si kullanacağım: TICKERS = [“SPY”, “QQQ”, “IWM”, “XLE”, “XLF”, “XLK”, “XLV”, “XLP”, “XLY”] BAŞLANGIÇ, BİTİŞ = “2004-01-01”, “2026-12-31” SPY, QQQ ve IWM bize geniş pazarda görünürlük sağlarken, geri kalan ETF’ler birkaç büyük sermaye sektörünü kapsamaktadır. Günlük geçmişleri EODHD’nin Tarihsel EOD uç noktasından alacağız.

Gerçek geliştirme dönemi 2005’te başlıyor, ancak indirme 2004’te başlıyor çünkü stratejiler daha sonra yuvarlanan momentum ve hacim hesaplamalarını başlatmak için daha erken gözlemlere ihtiyaç duyacak.

def fetch_eod(sembol, başlangıç=START, bitiş=END): params = {“api_token”: os.environ[“EODHD_API_KEY”], “from”: start, “to”: end, “period”: “d”, “fmt”: “json”} r = request.get(f”https://eodhd.com/api/eod/{symbol}.US”, params=params, timeout=60) r.json()’u döndür TICKERS’taki s için: f = RAW / f”{s}.json” f.exists() değilse: f.write_text(json.dumps(fetch_eod(s))); time.sleep(0.3) pd.DataFrame([{“symbol”: s, “rows”: len(j := json.loads((RAW/f”{s}.json”).read_text()))), “first”: j[0][“date”], “last”: j[-1][“date”]} for s in TICKERS]) Dokunulmamış her yanıt, biz onu dönüştürmeden önce saklanır.

Ham dosya zaten mevcutsa kod, aynı API isteğini tekrar yapmak yerine onu yeniden kullanır. İndirme bize dokuz ETF’nin tamamında aynı kapsamı sağlıyor: Bu strateji için her geçmişten üç alana ihtiyacımız var. justed_close momentumu ve portföy getirilerini artıracak, ham kapanış ve hacim ise daha sonra dolar hacmini hesaplamak için birleştirilecek.

Bu araştırma panellerini oluşturmadan önce, her yanıtı tarih endeksli bir DataFrame’e dönüştüreceğim ve arka testi sessizce bozabilecek sorunları kontrol edeceğim.

def to_frame(sembol): df = pd.DataFrame(json.loads((RAW / f”{symbol}.json”).read_text())) df[“tarih”] = pd.to_datetime(df[“tarih”]) return df.set_index(“date”).sort_index()[[“close”,”adjusted_close”,”volume”]].astype(float) çerçeveleri, rapor = {}, [] TICKERS’taki s için: d = to_frame(s) report.append({“sembol”: s, “satırlar”: len(d), “duplicate_dates”: int(d.index.duplicated().sum()), “eksik”: int(d.isna().sum().sum()), “pozitif olmayan_fiyat”: int((d[[“close”,”adjusted_close”]] <= 0).sum().sum()), "sıfır_hacim_günler": int((d["hacim"] <= 0).sum())}) çerçeveler[s] = d[~d.i ndex.duplicated(keep="son")] pd.DataFrame(report) Kontroller mükerrer işlem tarihlerini, eksik gözlemleri, geçersiz fiyatları ve pozitif olmayan hacmi kapsar: Dokuz geçmişin tümü kontrolleri geçer, böylece bunları işlem tarihine göre hizalayabilir ve üç araştırma dönemi oluşturabiliriz.

def paneli(alan): return pd.concat({s:frames[s][field] for s in TICKERS}, axis=1)[TICKERS] adj_close = panel(“adjusted_close”).dropna() kapat = panel(“kapat”).loc[adj_close.index] hacim = panel(“ses seviyesi”).loc[adj_close.index] şunu döndürür: adj_close.pct_change().fillna(0.0) SPLITS = {“dev”: (“2005-01-01”, “2017-12-31”), “val”: (“2018-01-01”, “2026-12-31”), “uzatma”: (“2026-01-01”, “2026-12-31”)} WARMUP = 250 def make_split(isim): lo, merhaba = BÖLMELER[isim]; idx = adj_close.index ilk = idx[max(0, idx.searchsorted(pd.Timestamp(lo)) – ISINMA)] keep = (idx >= ilk) & (idx <= pd.Timestamp(hi)) return {"adj_close": adj_close[keep], "close": close[keep], "volume": hacim[keep], "döndürür": döndürür[keep], "eval_start": pd.Timestamp(lo)} DATA = {name: make_split(name) SPLITS'deki ad için}, ["dev", "val"] içindeki ad için: ["adj_close", "close", "volume"] içindeki alan için: DATA[name][field].to_parquet(WS/"data"/f"{name}__{field}.parquet") json.dump({k: v[0] for k, v in SPLITS.items()}, open(WS/"data"/"splits.json","w")) DELETE_RAW_CACHE = Yanlış ise DELETE_RAW_CACHE: Shutil.rmtree(RAW, görmezden_hatalar=True) print("Diskteki dosyaları beklet:", list(ROOT.rg lob("bekletme*")) veya "YOK") pd.DataFrame({n: {"rows": len(DATA[n]["adj_close"]), "eval_start": DATA[n]["eval_start"].date(), "end": DATA[n]["adj_close"].index[-1].date()}, SPLITS'te n için}).T Üç periyodun farklı görevleri vardır.

Geliştirme, stratejinin oluşturulabileceği ve revize edilebileceği yerdir. Doğrulama, farklı sürümlerin tanıtım için yarışacağı yerdir. Şampiyonun dondurulmasının ardından, uzatma son bir değerlendirme için ayrılmıştır. Her bölünme aynı zamanda ısınma geçmişi olarak 250 önceki işlem seansını da taşır.

Bu satırlar, döngüsel göstergelerin bir değerlendirme döneminin başlangıcından itibaren mevcut olmasına izin verir, ancak eval_start, arka testi yapan kişiye performans ölçümünün gerçekten ne zaman başlaması gerektiğini söyler. Ortaya çıkan bölünmeler şunlardır: Buradaki önemli satır, diskteki bekletme dosyalarıdır: YOK.

Geliştirme ve doğrulama, araştırma çalışma alanına yazıldı ancak 2026’den 2026’e kadar olan gecikme hâlâ yalnızca devam eden süreçte mevcut. Bu nedenle daha sonraki aracılar bunu yalnızca dosya sistemlerine göz atarak keşfedemezler.

Araştırma başlamadan önce, daha önceki bir yürütmeden kalan tüm strateji, sonuç, inceleme veya karar eserlerini de temizleyeceğim: d için [WS/”stratejiler”, WS/”sonuçlar”, WS/”incelemeler”, ÖZEL]: Shutil.rmtree(d, görmezden_hatalar=Doğru) d.mkdir(ebeveynler=Doğru, mevcut_ok=Doğru) f için [WS/”registry.csv”, WS/”decisions.jsonl”, WS/”report.md”, WS/”frozen.json”, WS/”strategies”/”frozen.json”]: f.bağlantıyı kaldır(eksik _ok=Doğru) WS.glob’daki f için(“data/holdout_.parquet”): f.bağlantıyı kaldır() print(“özel:”, list(PRIVATE.iterdir()) veya “boş”) print(“diskte bekletme:”, list(ROOT.rglob(‘bekletme‘)) veya “YOK”) print(“workspace reset”) Artık temiz bir araştırma durumumuz, hizalanmış EODHD verimiz ve yalnızca aracılara yönelik bir talimat olmaktan ziyade sistemde var olan bir engel sınırımız var.

Deterministik Bir Strateji Değerlendirme Katmanı Oluşturun Aracılar eninde sonunda strateji mantığını kontrol edeceklerdir ancak bir stratejinin nasıl yürütüldüğünü veya puanlandığını kontrol etmemelidirler. Her revizyon kendi getirisini, cirosunu veya Sharpe oranını hesaplamakta özgürse, versiyonları karşılaştırmanın pek bir anlamı kalmaz.

Bu nedenle temsilci ekibini oluşturmadan önce tüm deneme boyunca sabit kalacak bir değerlendirme yolu oluşturacağız. Her strateji portföy ağırlıklarını döndürecek ve aynı Python motoru yürütme zamanlamasını, portföy muhasebesini, işlem maliyetlerini ve performans ölçümlerini oradan yönetecek. Paylaşılan motor, Engine.py’de bulunur.

Hem doğrudan strateji değerlendirmesi hem de daha sonra oluşturacağımız izole yürütme yolu aynı dosyayı içe aktarır, dolayısıyla muhasebe mantığının yalnızca bir uygulaması vardır. MOTOR = ”’ “””Sabit geriye dönük test motoru ve standart ölçümler.

Dizüstü bilgisayar VE dizüstü bilgisayar tarafından içe aktarıldı izole koşucu, böylece her ikisi de aynı koddan aynı sayıları hesaplıyor.””” json’u içe aktar numpy’yi np olarak, pandaları pd olarak içe aktar pathlib’den içe aktarma Pat h PERIODS, RF_ANNUAL, MAR_ANNUAL = 252, 0,0, 0,0 def backtest(ağırlıklar, getiriler, maliyet_bps=10,0): planlanmış = pd.Series(returns.index.isin(weights.index), index=returns.index, dtype=bool) w = ağırlıklar.reindex(returns.index).ffill().shift(1).fillna(0,0) is_rebal = planlanan.shift(1, fill_value=False) tutulan = pd.Series(0.0, index=returns.columns) return.index’teki d için satırlar = []: hedef = w.loc[d] if is_rebal.loc[d] else tutulan işlem gören = float((hedef – tutulan).abs().sum()) maliyet = işlem gören maliyet_bps / 1e4 r = getiriler.loc[d] brüt = float((hedef r).sum()) net = brüt – maliyet satırları.append((net, işlem gören, maliyet, kayan nokta(1,0 – hedef.sum()))) payda = 1,0 + brüt payda <= 0 ise: Raise RuntimeError(f"Brüt portföy değeri {d} tarihinde pozitif olmayan hale geldi: brüt getiri={brüt}") tutulan = (hedef (1,0 + r)) / payda return pd.DataFrame(rows, index=returns.index, sütunlar=[“ret”, “ciro”, “maliyet”, “nakit”],) def metrics(bt, kıyaslama=Yok, rf_annual=RF_ANNUAL, mar_annual=MAR_ANNUAL): r = bt[“geri”] rf_d = (1 + rf_annual) (1/PERIODS) – 1 mar_d = (1 + mar_annual) (1/PERIODS) – 1 örneğin = r – rf_d eq = (1 + r).cumprod(); yıl = uzunluk(r)/PERIODS sd = ex.std(ddof=1) dd = np.sqrt((np.minimum(r – mar_d, 0,0) 2).mean()) np.sqrt(PERIODS) m = {“cagr”: eq.iloc[-1] (1/yıl) – 1, “ann_ret”: r.mean() PERİYODLAR, “hac”: r.std(ddof=1) np.sqrt(PERIODS), “keskin”: (örn.mean()/sd) * np.sqrt(PERIODS) if sd

Ek okuma: MDN Web Docs

Editörün Notu

Çoklu ajanlı sistemlerde koordinasyon ve sınırlandırmalar, verimli ve güvenilir ticaret stratejileri geliştirmek için kritik öneme sahiptir; bu yaklaşım, yapay zekanın karar süreçlerinde tutarlılık ve kontrol sağlar.

Emre Demir
Yazar

Yazılım Editörü

Yazılım editörü ve full-stack geliştirici. Uygulama incelemeleri, kodlama rehberleri ve verimlilik araçları üzerine yazıyor. Açık kaynak projelere katkıda bulunuyor; karmaşık konuları yeni başlayanların anlayacağı şekilde anlatmaya özen gösteriyor.

Tüm yazıları gör →