تجارتی تحقیقی ایجنٹ حکمت عملی کوڈ لکھ سکتے ہیں، بیک ٹیسٹ چلا سکتے ہیں، نتائج کا معائنہ کر سکتے ہیں، اور حکمت عملی میں ترمیم کرنا جاری رکھ سکتے ہیں۔ ایک زیادہ مشکل مسئلہ اس بات کو یقینی بنانا ہے کہ یہ لوپ کسی پرکشش بیک ٹیسٹ کی بے قابو تلاش میں تبدیل نہ ہو۔
اس ہینڈ بک میں، ہم ایک ملٹی ایجنٹ ٹریڈنگ ریسرچ سسٹم بنانے کے لیے LangChain ڈیپ ایجنٹس کا استعمال کریں گے۔ EODHD تاریخی مارکیٹ کا ڈیٹا فراہم کرتا ہے، اور ایک متعین Python پرت ڈیٹا کی تقسیم، بیک ٹیسٹنگ منطق، بینچ مارکس، تجرباتی تاریخ، اور حکمت عملی کے انتخاب کے قواعد کو کنٹرول کرتی ہے۔ کوآرڈینیٹر، حکمت عملی انجینئر، اور تحقیقی نقاد پھر حکمت عملی کے تین ورژن تیار کرنے اور جانچنے کے لیے ان حدود میں کام کرتے ہیں۔
مقصد یہ ثابت کرنا نہیں ہے کہ ایک AI ایجنٹ قابل اعتماد طریقے سے منافع بخش حکمت عملیوں کو دریافت کر سکتا ہے۔ خیال یہ ہے کہ ایک تحقیقی کام کا فلو بنایا جائے جہاں ایجنٹ ان کا فیصلہ کرنے کے لیے استعمال ہونے والے شواہد کو کنٹرول کیے بغیر آئیڈیاز تیار اور چیلنج کر سکیں۔
انڈیکس
شرطیں
شروع کرنے سے پہلے، درج ذیل کو چیک کریں:
-
Python 3.11 یا اس سے زیادہ
-
ازگر، پانڈوں، اور مقداری بیک ٹیسٹنگ کی بنیادی تفہیم
-
تاریخی مارکیٹ ڈیٹا کے لیے EODHD API کلید
-
ڈیپ ایجنٹس ماڈلز کے لیے OpenAI API کیز
-
اگر آپ ٹریکنگ کو فعال کرنا چاہتے ہیں تو LangSmith API کلید
-
مطلوبہ ازگر پیکجز انسٹال ہیں، بشمول:
pandas،numpy،matplotlib،requests،python-dotenv،langchain،langgraphاورdeepagents
آپ کو ماحولیاتی متغیرات کے ساتھ کام کرنے اور Python کوڈ کو چلانے میں بھی ماہر ہونا چاہئے جو مقامی فائلوں اور ذیلی عمل کو تخلیق کرتا ہے۔
ریسرچ ورک فلو ڈیزائن
ایجنٹ کوڈ لکھنے سے پہلے، آپ کو یہ تعین کرنے کی ضرورت ہے کہ ایجنٹ اصل میں کیا کنٹرول کر سکتا ہے۔ مکمل ورک فلو مندرجہ ذیل ہے:
ورژن کا بہاؤ ڈیزائن کے لحاظ سے ترتیب وار ہے۔ v1 انہیں پہلے لاگو کیا جاتا ہے اور تجربہ کیا جاتا ہے، پھر تحقیقی جائزہ لینے والوں کے ذریعہ ان کا جائزہ لیا جاتا ہے اور ابتدائی چیمپئن کے طور پر ریکارڈ کیا جاتا ہے۔ تینوں مراحل مکمل کرنے کے بعد v2 شروع ایک ہی چکر دہرایا جاتا ہے۔ v2: انجینئر نظرثانی کو لاگو کرتے ہیں اور جانچتے ہیں، ناقدین شواہد کا جائزہ لیتے ہیں، اور رابطہ کار انتخاب کے قواعد کو لاگو کرنے سے پہلے لاگو کرتے ہیں۔ v3 آپ شروع کر سکتے ہیں۔
بعد میں v3 جانچ اور جائزہ لینے کے بعد، کوآرڈینیٹر حتمی انتخاب کرتا ہے اور ایک منجمد چیمپئن کے طور پر آپ کی بقا کے لیے حکمت عملی اور پیرامیٹرز لکھتا ہے۔ اس کے بعد ہی ہولڈ آؤٹ ڈیٹا کو حتمی تشخیص کے لیے کھول دیا جائے گا۔ نتائج معلوم ہونے کے بعد حکمت عملی میں کوئی ترمیم نہیں کی جا سکتی ہے، اور ورک فلو پورے اسٹڈی ٹریل کے منجمد اور چلائے جانے والے آڈٹ کے ساتھ ختم ہوتا ہے۔
ازگر کے تحقیقی ماحول کو ترتیب دینا
آئیے پورے ورک فلو میں استعمال ہونے والے پیکجوں کو درآمد کرکے شروع کریں۔ ڈیٹرمنسٹک ریسرچ پرت بنیادی طور پر حساب کے لیے پانڈوں اور NumPy پر انحصار کرتی ہے۔ requests EODHD ڈیٹا کے لیے، چارٹس کے لیے Matplotlib، Python میں ایک فائل سسٹم، اور ریسرچ آؤٹ پٹ کو ذخیرہ کرنے اور تیار کردہ حکمت عملی کوڈ کو الگ سے چلانے کے لیے ایک ذیلی عمل کی افادیت۔
import os, json, time, shutil, tempfile, subprocess, sys, traceback
import importlib.util
from pathlib import Path
import requests, numpy as np, pandas as pd
import matplotlib.pyplot as plt
from dotenv import load_dotenv
from IPython.display import Markdown, display
import getpass
اس تعمیر میں تین اسناد کا استعمال کیا گیا ہے: تاریخی مارکیٹ ڈیٹا کے لیے EODHD، ایجنٹ ماڈلز کے لیے OpenAI، اور ترقی کے دوران ورک فلو کی جانچ کے لیے LangSmith ٹریس۔ میں اسے اس سے لوڈ کروں گا: .env اپنی اسناد کو براہ راست اپنے کوڈ میں رکھنے کے بجائے، ایک فائل بنائیں اور اسے ماحولیاتی متغیر میں اسٹور کریں۔
ایک ہی وقت میں، ہم ان فائلوں کو الگ کریں گے جنہیں محققین استعمال کر سکتے ہیں اور جن تک وہ رسائی نہیں کر سکتے۔ workspace ترقی اور توثیق کا ڈیٹا، حکمت عملی کی فائلیں، نتائج اور جائزے شامل ہیں۔ private وہ ڈیٹا جو ایجنٹ کے کام کی جگہ میں داخل نہیں ہونا چاہیے، اور سب سے اہم بات، حتمی ہولڈ آؤٹ کے لیے محفوظ ہے۔
load_dotenv(override=True)
for k in ["EODHD_API_KEY", "OPENAI_API_KEY", "LANGSMITH_API_KEY"]:
assert os.environ.get(k), f"missing env var: {k}"
os.environ["EODHD_API_KEY"] = os.environ["EODHD_API_KEY"].strip()
os.environ["LANGSMITH_TRACING"] = "true"
LS_PROJECT = "trading-deep-agent"
os.environ["LANGSMITH_PROJECT"] = LS_PROJECT
ROOT = Path("project").resolve()
RAW = Path("raw_cache").resolve()
WS = ROOT / "workspace"
PRIVATE = ROOT / "private"
for p in [RAW, PRIVATE, WS/"data", WS/"strategies", WS/"results", WS/"reviews"]:
p.mkdir(parents=True, exist_ok=True)
print("workspace:", WS)
یہاں اہم فرق فولڈر کا نام نہیں ہے۔ ایجنٹ سائڈ فائل سسٹم بعد میں روٹ بن جائے گا۔ workspaceتحقیقی عمل مکمل ہونے تک ہولڈ آؤٹ بیرونی رہے گا۔
اگر .env اگر یہ دستیاب نہیں ہے یا آپ کو اپنی اسناد میں سے ایک کو تبدیل کرنے کی ضرورت ہے، تو آپ اس کی بجائے انٹرایکٹو کلید داخل کر سکتے ہیں۔ getpass جب آپ ٹائپ کرتے ہیں تو اسے چھپائیں اور اسے بعد میں عمل درآمد کے لیے محفوظ کریں۔
for k in ["EODHD_API_KEY", "OPENAI_API_KEY", "LANGSMITH_API_KEY"]:
os.environ[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 looks right:", os.environ["OPENAI_API_KEY"].startswith("sk-"),
len(os.environ["OPENAI_API_KEY"]))
کلید خود آؤٹ پٹ میں ظاہر نہیں ہوتی ہے۔
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 1 پروجیکٹ API کلید](https://umang.pk/wp-content/uploads/2026/08/1786768965_333_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
ایک بار جب آپ کا ماحول تیار ہو جائے تو، آپ مارکیٹ ڈیٹاسیٹ بنانا شروع کر سکتے ہیں جس پر آپ کا ریسرچ سسٹم کام کرے گا۔
EODHD مطالعہ ڈیٹا کی تیاری
ایجنٹ کے لیے بامعنی مختص فیصلے کرنے کے لیے اسٹڈی لوپ میں کافی تغیرات ہونے کی ضرورت ہے، لیکن کائنات کو پورے تجربے کے دوران مستقل رہنا چاہیے۔ میں 9 امریکی اسٹاک ای ٹی ایف استعمال کروں گا:
TICKERS = ["SPY","QQQ","IWM","XLE","XLF","XLK","XLV","XLP","XLY"]
START, END = "2004-01-01", "2025-12-31"
SPY، QQQ، اور IWM مارکیٹ کی وسیع نمائش فراہم کرتے ہیں، جبکہ باقی ETFs اسٹاک کے کئی بڑے شعبوں کا احاطہ کرتے ہیں۔
EODHD کے تاریخی EOD اینڈ پوائنٹ سے روزانہ ریکارڈ حاصل کریں۔ اصل ترقی کا دورانیہ 2005 میں شروع ہوتا ہے، لیکن ڈاؤن لوڈز 2004 میں شروع ہوتے ہیں۔ اس کی وجہ یہ ہے کہ حکمت عملی کو بعد میں گردشی رفتار اور حجم کے حسابات کو شروع کرنے کے لیے ابتدائی مشاہدات کی ضرورت ہوتی ہے۔
def fetch_eod(symbol, start=START, end=END):
params = {"api_token": os.environ["EODHD_API_KEY"], "from": start, "to": end, "period": "d", "fmt": "json"}
r = requests.get(f"https://eodhd.com/api/eod/{symbol}.US", params=params, timeout=60)
return r.json()
for s in TICKERS:
f = RAW / f"{s}.json"
if not f.exists():
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])
ہر غیر ترمیم شدہ جواب کو تبدیلی سے پہلے محفوظ کیا جاتا ہے۔ اگر خام فائل پہلے سے موجود ہے تو، کوڈ دوبارہ وہی API درخواست کرنے کے بجائے اسے دوبارہ استعمال کرتا ہے۔
ڈاؤن لوڈ تمام نو ETFs میں مساوی کوریج فراہم کرتا ہے۔
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 2 ETF تاریخی ڈیٹا رینج](https://umang.pk/wp-content/uploads/2026/08/1786768965_818_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
اس حکمت عملی کے لیے ہر ریکارڈ سے تین شعبوں کی ضرورت ہوتی ہے۔ adjusted_close یہ رفتار اور پورٹ فولیو کی واپسی کو آگے بڑھائے گا۔ close اور volume ڈالر کی رقم کا حساب لگانے کے لیے انہیں بعد میں یکجا کریں۔
اپنے تحقیقی پینل کو بنانے سے پہلے، آئیے ہر جواب کو تاریخ کے حساب سے ڈیٹا فریم میں تبدیل کریں اور ان مسائل کی جانچ کریں جو خاموشی سے ہمارے بیک ٹیسٹ کو روک سکتے ہیں۔
def to_frame(symbol):
df = pd.DataFrame(json.loads((RAW / f"{symbol}.json").read_text()))
df["date"] = pd.to_datetime(df["date"])
return df.set_index("date").sort_index()[["close","adjusted_close","volume"]].astype(float)
frames, report = {}, []
for s in TICKERS:
d = to_frame(s)
report.append({"symbol": s, "rows": len(d),
"duplicate_dates": int(d.index.duplicated().sum()),
"missing": int(d.isna().sum().sum()),
"nonpositive_price": int((d[["close","adjusted_close"]] <= 0).sum().sum()),
"zero_volume_days": int((d["volume"] <= 0).sum())})
frames[s] = d[~d.index.duplicated(keep="last")]
pd.DataFrame(report)
چیک میں ڈپلیکیٹ تجارتی دن، غائب مشاہدات، غلط قیمتیں، اور غیر مثبت والیوم شامل ہیں۔
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 3 تاریخی ڈیٹا کی تصدیق](https://umang.pk/wp-content/uploads/2026/08/1786768965_495_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
تمام نو بیانات ہمارے معائنہ کو پاس کرتے ہیں، لہذا ہم لین دین کی تاریخ کے مطابق ترتیب دے سکتے ہیں اور مطالعہ کے تین ادوار بنا سکتے ہیں۔
def panel(field):
return pd.concat({s: frames[s][field] for s in TICKERS}, axis=1)[TICKERS]
adj_close = panel("adjusted_close").dropna()
close = panel("close").loc[adj_close.index]
volume = panel("volume").loc[adj_close.index]
returns = adj_close.pct_change().fillna(0.0)
SPLITS = {"dev": ("2005-01-01","2017-12-31"), "val": ("2018-01-01","2021-12-31"),
"holdout": ("2022-01-01","2025-12-31")}
WARMUP = 250
def make_split(name):
lo, hi = SPLITS[name]; idx = adj_close.index
first = idx[max(0, idx.searchsorted(pd.Timestamp(lo)) - WARMUP)]
keep = (idx >= first) & (idx <= pd.Timestamp(hi))
return {"adj_close": adj_close[keep], "close": close[keep], "volume": volume[keep],
"returns": returns[keep], "eval_start": pd.Timestamp(lo)}
DATA = {name: make_split(name) for name in SPLITS}
for name in ["dev", "val"]:
for field in ["adj_close","close","volume"]:
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 = False
if DELETE_RAW_CACHE:
shutil.rmtree(RAW, ignore_errors=True)
print("holdout files on disk:", list(ROOT.rglob("holdout*")) or "NONE")
pd.DataFrame({n: {"rows": len(DATA[n]["adj_close"]), "eval_start": DATA[n]["eval_start"].date(),
"end": DATA[n]["adj_close"].index[-1].date()} for n in SPLITS}).T
تینوں ادوار میں مختلف پیشے ہیں۔ ترقی وہ جگہ ہے جہاں حکمت عملی بنائی اور نظر ثانی کی جا سکتی ہے۔ توثیق وہ مرحلہ ہے جہاں پروموشن کے لیے مختلف ورژن مقابلہ کرتے ہیں۔ چیمپیئن کو پہلے ہی پن کرنے کے بعد ہولڈ آؤٹ ایک حتمی تشخیص کے لیے محفوظ ہیں۔
ہر اسپلٹ میں اسٹیجنگ ریکارڈ کے طور پر 250 پچھلے تجارتی سیشنز بھی شامل ہیں۔ یہ قطاریں تشخیص کی مدت کے آغاز سے ہی رولنگ اشارے موجود رہنے دیتی ہیں، لیکن eval_start یہ بیکٹیسٹر کو بتاتا ہے کہ کارکردگی کی پیمائش اصل میں کب شروع ہونی چاہیے۔
نتیجے میں تقسیم یہ ہے:
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 4 تاریخی ڈیٹا کی تقسیم](https://umang.pk/wp-content/uploads/2026/08/1786768966_43_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
یہاں اہم لائن ہے holdout files on disk: NONE. اگرچہ تحقیقی کام کی جگہ میں ترقی اور توثیق ریکارڈ کی گئی ہے، لیکن 2022-2025 ہولڈ آؤٹ اب بھی صرف چلانے کے عمل کے لیے موجود ہے۔ لہذا، مستقبل کے ایجنٹ صرف فائل سسٹم کو براؤز کرکے اسے دریافت نہیں کرسکتے ہیں۔
مطالعہ شروع ہونے سے پہلے، ہم پچھلے رنز سے بچ جانے والی حکمت عملی، نتائج، جائزے، یا فیصلے کے نمونے بھی صاف کر دیں گے۔
for d in [WS/"strategies", WS/"results", WS/"reviews", PRIVATE]:
shutil.rmtree(d, ignore_errors=True)
d.mkdir(parents=True, exist_ok=True)
for f in [WS/"registry.csv", WS/"decisions.jsonl", WS/"report.md", WS/"frozen.json",
WS/"strategies"/"frozen.json"]:
f.unlink(missing_ok=True)
for f in WS.glob("data/holdout_*.parquet"):
f.unlink()
print("private:", list(PRIVATE.iterdir()) or "empty")
print("holdout on disk:", list(ROOT.rglob('holdout*')) or "NONE")
print("workspace reset")
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 5 ورک اسپیس کو ری سیٹ کریں۔](https://umang.pk/wp-content/uploads/2026/08/1786768966_28_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
ہمارے پاس اب ایک صاف تحقیقی حالت، منسلک EODHD ڈیٹا، اور ہولڈ آؤٹ باؤنڈریز ہیں جو ایجنٹوں کو ہدایات کے بجائے سسٹم میں موجود ہیں۔
ایک تعییناتی حکمت عملی کی تشخیص کے درجہ بندی کی تعمیر
ایجنٹ بالآخر حکمت عملی کی منطق کو کنٹرول کرتے ہیں، لیکن انہیں اس بات پر قابو نہیں رکھنا چاہیے کہ حکمت عملی کو کیسے عمل میں لایا جاتا ہے یا اسکور کیا جاتا ہے۔ اگر ہر نظر ثانی اپنے منافع، ٹرن اوور، یا تیز تناسب کا حساب لگانے کے لیے آزاد تھی، تو ورژنوں کا موازنہ کرنا مزید معنی خیز نہیں ہوگا۔
لہذا، ایجنٹوں کی ایک ٹیم بنانے سے پہلے، ہم ایک تشخیصی راستہ بنائیں گے جو پورے تجربے کے دوران طے رہے گا۔ تمام حکمت عملی پورٹ فولیو وزن واپس کرتی ہے، اور وہی پائتھون انجن عملدرآمد کے وقت، پورٹ فولیو اکاؤنٹنگ، لین دین کے اخراجات، اور کارکردگی کے میٹرکس کو ہینڈل کرتا ہے۔
1. ایک مشترکہ بیک ٹیسٹنگ انجن بنائیں
مشترکہ انجن اس پر واقع ہے: engine.py. دونوں براہ راست حکمت عملی کی تشخیص اور الگ تھلگ عمل درآمد کا راستہ جو ہم بناتے ہیں بعد میں اسی فائل کو درآمد کرتے ہیں، لہذا صرف ایک اکاؤنٹنگ منطق کو لاگو کیا جاتا ہے۔
ENGINE = '''
"""Fixed backtest engine and standard metrics. Imported by the notebook AND by the
isolated runner, so both compute identical numbers from identical code."""
import json
import numpy as np, pandas as pd
from pathlib import Path
PERIODS, RF_ANNUAL, MAR_ANNUAL = 252, 0.0, 0.0
def backtest(weights, returns, cost_bps=10.0):
scheduled = pd.Series(returns.index.isin(weights.index), index=returns.index, dtype=bool)
w = weights.reindex(returns.index).ffill().shift(1).fillna(0.0)
is_rebal = scheduled.shift(1, fill_value=False)
held = pd.Series(0.0, index=returns.columns)
rows = []
for d in returns.index:
target = w.loc[d] if is_rebal.loc[d] else held
traded = float((target - held).abs().sum())
cost = traded * cost_bps / 1e4
r = returns.loc[d]
gross = float((target * r).sum())
net = gross - cost
rows.append((net, traded, cost, float(1.0 - target.sum())))
denominator = 1.0 + gross
if denominator <= 0:
raise RuntimeError(f"Gross portfolio value became non-positive on {d}: gross return={gross}")
held = (target * (1.0 + r)) / denominator
return pd.DataFrame(rows, index=returns.index, columns=["ret", "turnover", "cost", "cash"],)
def metrics(bt, benchmark=None, rf_annual=RF_ANNUAL, mar_annual=MAR_ANNUAL):
r = bt["ret"]
rf_d = (1 + rf_annual) ** (1/PERIODS) - 1
mar_d = (1 + mar_annual) ** (1/PERIODS) - 1
ex = r - rf_d
eq = (1 + r).cumprod(); yrs = len(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/yrs) - 1,
"ann_ret": r.mean() * PERIODS,
"vol": r.std(ddof=1) * np.sqrt(PERIODS),
"sharpe": (ex.mean()/sd) * np.sqrt(PERIODS) if sd > 0 else 0.0,
"sortino": (r.mean()*PERIODS - mar_annual)/dd if dd > 0 else 0.0,
"max_dd": (eq/eq.cummax() - 1).min(),
"ann_turnover": bt["turnover"].sum()/yrs,
"ann_cost": bt["cost"].sum()/yrs,
"avg_cash": bt["cash"].mean()}
if benchmark is not None:
m["bench_cagr"] = (1+benchmark).cumprod().iloc[-1] ** (1/yrs) - 1
return {k: round(float(v), 4) for k, v in m.items()}
def load_split(data_dir, split):
p = Path(data_dir)
d = {f: pd.read_parquet(p/f"{split}_{f}.parquet") for f in ["adj_close","close","volume"]}
d["returns"] = d["adj_close"].pct_change().fillna(0.0)
d["eval_start"] = pd.Timestamp(json.load(open(p/"splits.json"))[split])
return d
'''
(ROOT/"engine.py").write_text(ENGINE)
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
import engine
importlib.reload(engine)
from engine import backtest, metrics
print("engine.py written")
engine.py written
اب، ہر حکمت عملی کی ذمہ داری بہت کم ہے۔ آپ کو صرف ٹارگٹ پورٹ فولیو وزن بنانے کی ضرورت ہے۔ engine.py جب وہ وزن تشخیصی پرت تک پہنچ جاتے ہیں، تو انہیں تبدیل کر دیا جاتا ہے۔
ایک تفصیل یہاں خاص طور پر اہم ہے۔ ہدف کے وزن کو ایک تجارتی سیشن میں منتقل کیا جاتا ہے اس سے پہلے کہ وہ منافع کو متاثر کریں۔ اگر حکمت عملی دن کی اختتامی قیمت کا استعمال کرتی ہے۔ t آپ کو سگنل کا حساب لگانے کے لیے ایک دن بھی نہیں مل سکتا۔ t وہ معلومات واپس آ جاتی ہیں۔
انجن موجودہ پورٹ فولیو کے وزن اور آنے والے ری بیلنسنگ کے درمیان بھی فرق کرتا ہے۔ ری بیلنسنگ کے درمیان، آپ کی ہولڈنگز قدرتی طور پر اثاثہ جات کی واپسی کی بنیاد پر بڑھ جاتی ہیں، بجائے اس کے کہ ہر روز اپنی ٹارگٹ ویلیو کو دوبارہ ترتیب دیں۔ جب اگلا توازن ہوتا ہے، فروخت کا حساب اس وقت کے اصل ذخائر سے نئے ہدف تک لگایا جاتا ہے۔
یہ آمدنی، لین دین کے اخراجات، ٹرن اوور، کیش ایکسپوژر، شارپ، سورٹینو، اور بعد کے تمام تجربات میں نقصان کے لیے ایک جیسی تعریفیں فراہم کرتا ہے۔
2. پورٹ فولیو اکاؤنٹنگ چیک کریں۔
ایجنٹ کے ذریعہ تیار کردہ درجنوں تجربات پر حسابات پر انحصار کرنے سے پہلے، آپ ایک سادہ کیس کی جانچ کر سکتے ہیں جہاں متوقع جواب واضح ہو۔
فرض کریں کہ پورٹ فولیو مندرجہ ذیل وزن کے ساتھ ایک اثاثہ خریدتا ہے: 1.0 دوبارہ کبھی ایڈجسٹ نہ کریں۔ لین دین کی کل تصوراتی رقم بالکل ہونی چاہیے: 1.0: ابتدائی خریداری ایک بار ہوتی ہے اور کوئی فالو اپ لین دین نہیں ہوتا۔
w = pd.DataFrame(0.0, index=[DATA["dev"]["adj_close"].index[0]], columns=TICKERS)
w.iloc[0, 0] = 1.0
assert round(backtest(w, DATA["dev"]["returns"]).turnover.sum(), 4) == 1.0
print("turnover check ok")
turnover check ok
اس چھوٹے سے دعوے کے اہم ہونے کی وجہ یہ ہے کہ یہاں اکاؤنٹنگ کی باریک خرابی بعد کے تمام موازنہوں کو متاثر کرتی ہے۔ مثال کے طور پر، اگر عام پورٹ فولیو ڈرفٹ کو ہر روز ایک نئے لین دین کے طور پر شمار کیا جاتا ہے، تو ایجنٹوں کے تحقیق شروع کرنے سے پہلے ٹرن اوور اور لین دین کے اخراجات دونوں کو بڑھا چڑھا کر پیش کیا جائے گا۔
3. ایک مقررہ بینچ مارک سیٹ کریں۔
چیلنجرز کو حکمت عملی کے فوری طور پر پچھلے ورژن سے مقابلہ کرنے کے لیے کچھ زیادہ معنی خیز بھی درکار ہے۔
ہم چار حوالہ جات کی حکمت عملی قائم کریں گے: SPY Buy and Hold، Equal Weight Buy and Hold for 9 ETFs، جنرل کراس سیکشن مومنٹم، ڈالر کے سائز کے اہلیت کے فلٹر کا استعمال کرتے ہوئے وہی رفتار حکمت عملی جو ابتدائی تحقیقی حکمت عملی میں ظاہر ہوگی۔
def bh_weights(data, tickers):
w = pd.DataFrame(0.0, index=[data["adj_close"].index[0]], columns=data["adj_close"].columns)
w.loc[w.index[0], tickers] = 1.0/len(tickers)
return w
def plain_momentum(data, mom_window=126, top_n=3):
adj = data["adj_close"]; mom = adj.pct_change(mom_window)
dates = pd.DatetimeIndex(adj.index.to_series().resample("ME").last().dropna())
w = pd.DataFrame(0.0, index=dates, columns=adj.columns)
for dt in dates:
picks = mom.loc[dt][mom.loc[dt] > 0].dropna().nlargest(top_n).index
if len(picks): w.loc[dt, picks] = 1.0/len(picks)
return w
def volume_momentum(data, mom_window=126, top_n=3, vol_short=20, vol_long=120, vol_ratio_min=1.0):
adj, cls, vol = data["adj_close"], data["close"], data["volume"]
mom = adj.pct_change(mom_window); dv = cls*vol
ratio = dv.rolling(vol_short).mean()/dv.rolling(vol_long).mean()
ok = (mom > 0) & (ratio > vol_ratio_min)
dates = pd.DatetimeIndex(adj.index.to_series().resample("ME").last().dropna())
w = pd.DataFrame(0.0, index=dates, columns=adj.columns)
for dt in dates:
picks = mom.loc[dt][ok.loc[dt]].dropna().nlargest(top_n).index
if len(picks): w.loc[dt, picks] = 1.0/len(picks)
return w
BENCHMARKS = {"spy_bh": lambda d: bh_weights(d, ["SPY"]),
"ew_bh": lambda d: bh_weights(d, TICKERS),
"plain_mom": plain_momentum, "volume_mom": volume_momentum}
def benchmark_table(split):
d = DATA[split]; rows = {}
for name, fn in BENCHMARKS.items():
bt = backtest(fn(d), d["returns"])
rows[name] = metrics(bt.loc[d["eval_start"]:], d["returns"]["SPY"].loc[d["eval_start"]:])
return pd.DataFrame(rows).T
COLS_B = ["cagr","sharpe","sortino","max_dd","ann_turnover"]
BENCH = {s: benchmark_table(s) for s in ["dev","val"]}
BENCH_TEXT = ("DEVELOPMENTn" + BENCH["dev"][COLS_B].to_string() +
"nnVALIDATIONn" + BENCH["val"][COLS_B].to_string())
(WS/"BENCHMARKS.md").write_text("# Fixed benchmarksnn```n" + BENCH_TEXT + "n```n")
ab = BENCH["dev"].loc["volume_mom"] - BENCH["dev"].loc["plain_mom"]
print(BENCH["dev"][COLS_B])
print(f"nvolume filter effect on dev: sharpe {ab['sharpe']:+.4f}, "
f"cagr {ab['cagr']:+.4f}, turnover {ab['ann_turnover']:+.2f}")
پیش رفت کا موازنہ ایک ابتدائی حقیقت کی جانچ فراہم کرتا ہے۔
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 6 بینچ مارک موازنہ](https://umang.pk/wp-content/uploads/2026/08/1786768966_176_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
حجم کے فلٹرز معمول کی رفتار کے مقابلے میں زیادہ سے زیادہ کمی کو قدرے بہتر بناتے ہیں، لیکن تجارت خاص طور پر پرکشش نہیں ہے۔ ترقی کی رفتار میں کمی 0.0976CAGR میں تقریباً 2 فیصد پوائنٹس کی کمی ہوگی اور سالانہ فروخت میں تقریباً 2 فیصد پوائنٹس کی کمی ہوگی۔ 4.38.
یہ ایجنٹوں کے لیے مفید معلومات ہے کہ وہ بہتری کی تجویز پیش کرنے سے پہلے قائم کریں۔ ابتدائی حکمت عملی ان کے سامنے ایک مضبوط بینچ مارک کے طور پر پیش نہیں کی جاتی جس میں صرف کچھ تطہیر کی ضرورت ہوتی ہے۔ پہلے ہی واضح کمزوریاں ہیں جن کا انہیں سامنا کرنا ہوگا۔
بینچ مارکس کے ایک ہی سیٹ کو توثیق کے لیے شمار کیا جاتا ہے اور ترقی کے نتائج کے ساتھ تیار کیا جاتا ہے۔ BENCHMARKS.md. اس سے آنے والے ایجنٹوں کو اپنی تبدیلیوں کا موازنہ ایک مقررہ حوالہ جاتی حکمت عملی سے کرنے کی اجازت دیتا ہے، بجائے اس کے کہ کامیابی کا فیصلہ صرف اس ورژن کے خلاف کیا جائے جو موجودہ چیمپئن ہے۔
4. تمام حکمت عملیوں کو الگ تھلگ ذیلی عمل میں چلائیں۔
مشترکہ انجن اس میں ترمیم کرتا ہے کہ کارکردگی کا حساب کیسے لگایا جاتا ہے، لیکن تیار کردہ حکمت عملی کوڈ کو ابھی بھی کہیں چلنا ہے۔
اس کوڈ کو براہ راست مرکزی تحقیقی عمل کے اندر چلانے سے آپ کو ہر اس چیز تک رسائی ملتی ہے جو پہلے سے بھری ہوئی ہے، بشمول API اسناد اور ہولڈ آؤٹ ڈیٹا سیٹس جنہیں آپ جان بوجھ کر تحقیقی لوپ سے دور رکھتے ہیں۔ اس کے بجائے، ہر تجربہ صرف اس مخصوص تشخیص کے لیے درکار فائلوں کا استعمال کرتے ہوئے اپنے ایڈہاک عمل میں چلتا ہے۔
سب سے پہلے، ہم ایک ایگزیکیٹر بناتے ہیں جو اس عمل کے اندر چلتا ہے۔
RUNNER = '''
"""Isolated strategy runner. Own process, temp sandbox, scrubbed environment."""
import sys, json, importlib.util, traceback
def main():
strat, params_json, data_dir, split, cost_bps = sys.argv[1:6]
import engine
d = engine.load_split(data_dir, split)
spec = importlib.util.spec_from_file_location("strategy", strat)
mod = importlib.util.module_from_spec(spec); spec.loader.exec_module(mod)
w = mod.target_weights(d, **json.loads(params_json))
bt = engine.backtest(w, d["returns"], cost_bps=float(cost_bps))
ev = bt.loc[d["eval_start"]:]
bench = d["returns"]["SPY"].loc[d["eval_start"]:] if "SPY" in d["returns"] else None
print(json.dumps({"ok": True, "metrics": engine.metrics(ev, bench),
"equity": [round(float(x), 6) for x in (1+ev["ret"]).cumprod().tolist()],
"dates": [str(x.date()) for x in ev.index]}))
if __name__ == "__main__":
try: main()
except Exception: print(json.dumps({"ok": False, "error": traceback.format_exc(limit=3)}))
'''
(ROOT/"runner.py").write_text(RUNNER)
def isolated_environment(sandbox):
required = ["PATH","SYSTEMROOT","WINDIR","COMSPEC","PATHEXT","VIRTUAL_ENV","CONDA_PREFIX","CONDA_DEFAULT_ENV","LD_LIBRARY_PATH",
"DYLD_LIBRARY_PATH","LANG","LC_ALL"]
env = {name: os.environ[name] for name in required if name in os.environ}
env.update({
"HOME": str(sandbox),
"USERPROFILE": str(sandbox),
"TEMP": str(sandbox),
"TMP": str(sandbox),
"TMPDIR": str(sandbox),
"PYTHONHASHSEED": "1",
"PYTHONUTF8": "1",
})
return env
def run_isolated(strategy_path, params, split, cost_bps=10.0, timeout=600):
sandbox = Path(tempfile.mkdtemp(prefix="strat_"))
(sandbox/"data").mkdir()
for f in ["adj_close","close","volume"]:
shutil.copy(WS/"data"/f"{split}_{f}.parquet", sandbox/"data")
shutil.copy(WS/"data"/"splits.json", sandbox/"data")
shutil.copy(ROOT/"engine.py", sandbox); shutil.copy(ROOT/"runner.py", sandbox)
shutil.copy(strategy_path, sandbox/"strategy.py")
try:
p = subprocess.run([sys.executable, "runner.py", "strategy.py", json.dumps(params),
"data", split, str(cost_bps)],
capture_output=True, text=True, cwd=sandbox, timeout=timeout,
env=isolated_environment(sandbox))
if not p.stdout.strip():
return {"ok": False, "error": (p.stderr or "no output")[-400:]}
return json.loads(p.stdout)
except subprocess.TimeoutExpired:
return {"ok": False, "error": f"timeout after {timeout}s"}
finally:
shutil.rmtree(sandbox, ignore_errors=True)
ہر رن کے لیے، run_isolated() ایک عارضی ڈائرکٹری بنائیں اور صرف مطلوبہ ڈیولپمنٹ یا توثیق کی فائلیں تیار کریں۔ engine.py، runner.pyاور حکمت عملی کا جائزہ لیا۔ مزید برآں، والدین کے عمل کے ماحول کو مکمل طور پر نقل کرنے کے بجائے، یہ بچے کے عمل کے لیے بہت چھوٹا ماحول بناتا ہے۔
اس لیے تیار کردہ حکمت عملی پورٹ فولیو وزن پیدا کرنے کے لیے درکار معلومات حاصل کرتی ہے، لیکن EODHD، OpenAI، LangSmith، یا ہولڈ آؤٹ ڈیٹا تک رسائی کی ضرورت نہیں ہے۔
یہ آپریٹنگ سسٹم سیکیورٹی سینڈ باکس کے بجائے جان بوجھ کر تحقیقی عمل کی تنہائی کی حد ہے۔ تیار کردہ کوڈ اب بھی ایک عام Python عمل ہے جو موجودہ صارف اکاؤنٹ کے تحت چل رہا ہے۔ یہاں مقصد دشمنی کوڈ سے تحفظ کا دعوی کرنا نہیں ہے، بلکہ حکمت عملی کے نفاذ کے راستے میں اسناد اور غیر مرتب شدہ تحقیقی ڈیٹا تک حادثاتی رسائی کو روکنا ہے۔
5. عمل درآمد کی برابری اور ڈیٹا کی حدود کو چیک کریں۔
پھانسی کے اس راستے کو استعمال کرنے سے پہلے جانچ کے قابل دو چیزیں ہیں:
سب سے پہلے، ایک الگ تھلگ عمل کے اندر جانچ کی جانے والی حکمت عملیوں کو بالکل وہی نتائج حاصل کرنے چاہئیں جس طرح اسی منطق کا براہ راست جائزہ لیا جاتا ہے۔ engine.py. ورنہ ہم نے پیمائش کے دو مختلف نظام متعارف کرائے ہوتے۔
ہم برابری کو چیک کرنے کے لیے والیوم مومینٹم بینچ مارک استعمال کریں گے۔
دوسرا، ہم جان بوجھ کر تحقیقات چلاتے ہیں جو اسناد جیسے ماحولیاتی متغیرات اور ہولڈ آؤٹس یا ذاتی فائلوں کو تلاش کرتے ہیں۔
(WS/"strategies"/"parity_check.py").write_text('''import pandas as pd
def target_weights(data, mom_window=126, top_n=3, vol_short=20, vol_long=120, vol_ratio_min=1.0):
adj, cls, vol = data["adj_close"], data["close"], data["volume"]
mom = adj.pct_change(mom_window); dv = cls*vol
ratio = dv.rolling(vol_short).mean()/dv.rolling(vol_long).mean()
ok = (mom>0)&(ratio>vol_ratio_min)
dates = pd.DatetimeIndex(adj.index.to_series().resample("ME").last().dropna())
w = pd.DataFrame(0.0, index=dates, columns=adj.columns)
for d in dates:
picks = mom.loc[d][ok.loc[d]].dropna().nlargest(top_n).index
if len(picks): w.loc[d,picks]=1.0/len(picks)
return w
''')
iso = run_isolated(WS/"strategies"/"parity_check.py", {"mom_window":126,"top_n":3}, "dev")
d = DATA["dev"]
inp = metrics(backtest(volume_momentum(d, 126, 3), d["returns"]).loc[d["eval_start"]:],
d["returns"]["SPY"].loc[d["eval_start"]:])
assert iso["metrics"]["sharpe"] == inp["sharpe"], "isolated and in-process disagree"
print("parity ok:", iso["metrics"]["sharpe"])
PROBE = f'''import os, glob
def target_weights(data, **k):
keys = [x for x in os.environ if any(t in x for t in ("KEY","TOKEN","SECRET"))]
files = glob.glob(r"{PRIVATE}/*") + glob.glob(r"{WS}/data/holdout_*")
raise RuntimeError(f"KEYS={{keys}} REACHABLE_SENSITIVE_FILES={{len(files)}}")
'''
(WS/"strategies"/"probe.py").write_text(PROBE)
msg = run_isolated(WS/"strategies"/"probe.py", {}, "dev")["error"].strip().split("n")[-1]
print("probe:", msg)
assert "KEYS=[]" in msg, "credentials reachable from the sandbox"
assert "REACHABLE_SENSITIVE_FILES=0" in msg, "holdout or private files reachable from the sandbox"
معائنہ گزر چکا ہے۔
parity ok: 0.4387
probe: RuntimeError: KEYS=[] REACHABLE_SENSITIVE_FILES=0
الگ تھلگ راستہ اور سیدھا راستہ دونوں برابر ہیں۔ 0.4387 چونکہ یہ ایک ڈویلپمنٹ شارپ ہے، میں حکمت عملی کے نتائج سے متفق ہوں۔ مزید برآں، تحقیقات کو ذیلی ماحول میں اسنادی متغیرات نہیں ملتے ہیں، اور نہ ہی اس میں اسٹیجڈ پرائیویٹ یا ہولڈ آؤٹ فائلیں ملتی ہیں۔
تجربہ اور فیصلہ کی تہیں بنائیں
بیک ٹیسٹنگ انجن اب تمام حکمت عملیوں کے لیے ایک ہی تشخیصی راستہ فراہم کرتا ہے۔ لیکن ہمیں بار بار تجربات کے ذریعے کیا ہوتا ہے اس پر قابو پانے کی ضرورت ہے۔
اگر ایجنٹ غیر معینہ مدت تک نئی کنفیگریشنز کی جانچ کرنا جاری رکھ سکتے ہیں، ناکام عمل درآمد کو نظر انداز کر سکتے ہیں، یا پچھلے ایک کا جائزہ لینے سے پہلے کسی حکمت عملی کے نئے ورژن پر منتقل ہو سکتے ہیں، تو تحقیقی عمل اب بھی اس نتائج کی طرف بڑھ سکتا ہے جو بہترین معلوم ہوتا ہے۔ اس لیے، اگلی پرت تمام تجربات کو ٹریک کرتی ہے، ایک مقررہ تحقیقی بجٹ کو نافذ کرتی ہے، اور اگلا تجربہ شروع ہونے سے پہلے ہر ورژن کو ایک ہی ترتیب سے گزرنے کی ضرورت ہوتی ہے۔
1. ایک تجرباتی رجسٹری بنائیں
آئیے رجسٹری کے ساتھ شروع کریں، جو سسٹم پر جانچ کی گئی تمام کنفیگریشنز کو ریکارڈ کرتی ہے۔
REGISTRY = WS / "registry.csv"
DECISIONS = WS / "decisions.jsonl"
MAX_CONFIGS = 12
COLS = ["version","run","status","params","note","dev_cagr","dev_sharpe","dev_sortino",
"dev_max_dd","dev_turnover","val_cagr","val_sharpe","val_max_dd","dev_cagr_20bps","error"]
def _used(version):
if not REGISTRY.exists(): return 0
return int((pd.read_csv(REGISTRY)["version"] == version).sum())
def _decisions():
if not DECISIONS.exists(): return []
return [json.loads(l) for l in DECISIONS.read_text().splitlines() if l.strip()]
def _stage_ok(version):
"""vN cannot begin until v(N-1) is swept, reviewed and decided."""
if not (version.startswith("v") and version[1:].isdigit()): return True, ""
n = int(version[1:])
if n <= 1: return True, ""
prev = f"v{n-1}"
if not REGISTRY.exists() or _used(prev) == 0:
return False, f"stage gate: {prev} has no recorded runs. Complete {prev} first."
reg = pd.read_csv(REGISTRY)
if reg[(reg.version == prev) & (reg.status == "ok")].empty:
return False, f"stage gate: {prev} has no successful runs."
if not (WS/"reviews"/f"{prev}.md").exists():
return False, f"stage gate: /reviews/{prev}.md does not exist. Get a critic review first."
if not any(d["version"] == prev for d in _decisions()):
return False, f"stage gate: no decision recorded for {prev}. Call record_decision first."
return True, ""
MAX_CONFIGS = 12 ہم کنفیگریشنز کی تعداد پر سخت حدیں لگاتے ہیں جن کا تجربہ کسی بھی حکمت عملی ورژن میں کیا جا سکتا ہے۔ یہ ضروری ہے کیونکہ تصدیقی ڈیٹا کا زیادہ استعمال ہو سکتا ہے۔ جیسا کہ ایجنٹ کو پیرامیٹرز کے مختلف مجموعوں کو تلاش کرنے کے لامحدود مواقع ملتے ہیں اور وہ توثیق میں بہترین کارکردگی کا مظاہرہ کرنے والے امتزاج کو منتخب کرتا رہتا ہے، توثیق کا سیٹ آہستہ آہستہ ایک اور اصلاح کے تابع ہو جاتا ہے۔
اسٹیج گیٹس دوسرے مسائل کو کنٹرول کرتے ہیں۔ آپ نیا ورژن شروع نہیں کر سکتے کیونکہ آپ کے ایجنٹ مختلف سوچتے ہیں۔ پہلے v2 ٹیسٹ کیا جا سکتا ہے، v1 پہلے سے ہی کم از کم ایک کامیاب دوڑ، تنقیدی جائزے، اور ریکارڈ شدہ فیصلے ہونے چاہئیں۔ وہی حکم پہلے کی طرح لاگو ہوتا ہے۔ v3.
تو ورژن کا بہاؤ یہ ہے:
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 7 ورژن بہاؤ](https://umang.pk/wp-content/uploads/2026/08/1786768966_882_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
یہ آپ کو عمل کو یاد رکھنے کے لیے کوآرڈینیٹر پر انحصار کرنے کے بجائے اپنے کوڈ میں اسٹڈی آرڈر کو نافذ کرنے کی اجازت دیتا ہے۔
2. تحقیقی ٹولز بنائیں
ایجنٹ تین LangChain ٹولز کے ذریعے اس پرت کے ساتھ تعامل کرتے ہیں:
سب سے اہم بات یہ ہے۔ sweep(). ایجنٹوں کے لیے سرکاری بیک ٹیسٹ کے نتائج حاصل کرنے کا یہ واحد راستہ ہے۔
from langchain.tools import tool
@tool
def sweep(version: str, grid_json: str, note: str = "") -> str:
"""Backtest strategies/.py over several parameter sets in ONE call.
version : file stem, e.g. "v1" for strategies/v1.py
grid_json : JSON list of parameter objects, e.g. [{"top_n":3},{"top_n":4}]
note : short reason for this sweep
Runs each configuration in an isolated subprocess. Returns a CSV table sorted by
validation Sharpe. Max 12 configurations per version, cumulative. Every row is
written to registry.csv, including failures. vN is blocked until v(N-1) is swept,
reviewed and decided.
"""
ok, why = _stage_ok(version)
if not ok: return f"error: {why}"
used = _used(version)
try:
grid = json.loads(grid_json)
if isinstance(grid, dict): grid = [grid]
except Exception as e:
return f"error: grid_json is not valid JSON ({e})"
if used + len(grid) > MAX_CONFIGS:
return f"error: budget. {used}/{MAX_CONFIGS} used on {version}, you asked for {len(grid)} more."
path = WS/"strategies"/f"{version}.py"
if not path.exists():
return f"error: {path.name} does not exist. Write it first."
rows = []
for i, params in enumerate(grid, start=used + 1):
row = {"version": version, "run": i, "note": note,
"params": json.dumps(params, separators=(",", ":"))}
dev = run_isolated(path, params, "dev")
if not dev["ok"]:
row.update(status="error", error=dev["error"].strip().split("n")[-1][:150])
rows.append(row); continue
val = run_isolated(path, params, "val")
c20 = run_isolated(path, params, "dev", cost_bps=20.0)
dm, vm = dev["metrics"], val["metrics"]
row.update(status="ok", dev_cagr=dm["cagr"], dev_sharpe=dm["sharpe"],
dev_sortino=dm["sortino"], dev_max_dd=dm["max_dd"],
dev_turnover=dm["ann_turnover"], val_cagr=vm["cagr"],
val_sharpe=vm["sharpe"], val_max_dd=vm["max_dd"],
dev_cagr_20bps=c20["metrics"]["cagr"] if c20["ok"] else None)
tag = f"{version}_run{i}"
(WS/"results"/f"{tag}.json").write_text(json.dumps({"params": params, "dev": dm, "val": vm}, indent=2))
eq = pd.Series(dev["equity"], index=pd.to_datetime(dev["dates"]))
plt.figure(figsize=(8,3)); plt.plot(eq); plt.yscale("log"); plt.title(tag)
plt.tight_layout(); plt.savefig(WS/"results"/f"{tag}.png", dpi=90); plt.close("all")
rows.append(row)
df = pd.DataFrame(rows).reindex(columns=COLS)
df.to_csv(REGISTRY, mode="a", header=not REGISTRY.exists(), index=False)
out = df.drop(columns=["version","note"]).round(3).dropna(axis=1, how="all")
if "val_sharpe" in out:
out = out.sort_values("val_sharpe", ascending=False, na_position="last")
return out.to_csv(index=False)
@tool
def read_registry(version: str = "") -> str:
"""Every run recorded so far as CSV, accepted and rejected. Pass a version to filter."""
if not REGISTRY.exists(): return "empty"
r = pd.read_csv(REGISTRY)
if version: r = r[r["version"] == version]
return r[["version","run","status","params","dev_sharpe","dev_sortino",
"dev_max_dd","val_sharpe","val_max_dd","error"]].to_csv(index=False)
@tool
def record_decision(version: str, champion: str, rationale: str, params_json: str) -> str:
"""Record the approved outcome of a version. REQUIRED before the next version can be swept.
version : the version just reviewed, e.g. "v2"
champion : which version is champion after applying the selection rule
rationale : cite the selection rule and the specific numbers that decided it
params_json: the champion's parameters as JSON
"""
if any(d["version"] == version for d in _decisions()):
return f"error: a decision for {version} already exists and cannot be overwritten."
rec = {"version": version, "champion": champion, "rationale": rationale,
"params": json.loads(params_json), "ts": time.time()}
with DECISIONS.open("a") as f:
f.write(json.dumps(rec) + "n")
return f"recorded. champion is now {champion}"
تمام کنفیگریشنز کے لیے sweep() ترقی اور توثیق کو اس الگ تھلگ تشخیصی راستے کے ذریعے چلائیں جو آپ نے ابھی بنایا ہے۔ ہم لین دین کی لاگت کے 20bp پر پیشرفت کو بھی دوبارہ چلاتے ہیں، ناقدین کو یہ جانچنے کی اجازت دیتے ہیں کہ آیا نتائج خاص طور پر بنیادی 10bp مفروضے کے لیے حساس ہیں۔
ایک کامیاب رن اشارے، ایک JSON نتائج فائل، اور ایک اثاثہ وکر پیدا کرتا ہے۔ ناکام رنز درج ہوتے رہیں گے۔ registry.csv تحقیقی ریکارڈ سے غائب ہونے کے بجائے۔ اس کا مطلب یہ ہے کہ اسٹریٹجک انجینئرز خاموشی سے متعدد ٹوٹے ہوئے کنفیگریشنز کی مرمت نہیں کر سکتے اور صرف حتمی کامیاب کنفیگریشن کے ساتھ آ سکتے ہیں۔
دوسرے دو ٹولز جان بوجھ کر آسان ہیں۔ read_registry() ایجنٹوں کو ریکارڈ شدہ شواہد کا معائنہ کرنے کی اجازت دیں؛ record_decision() ہر ورژن کے لیے سرکاری نتائج پیش کرتا ہے۔ ایک بار فیصلہ ہو جانے کے بعد، اسی ورژن کے لیے ٹول کو دوبارہ کال کر کے اسے اوور رائٹ نہیں کیا جا سکتا۔
3. حکمت عملی کے انتخاب کے قواعد میں ترمیم کریں۔
رجسٹری آپ کو بتاتی ہے کہ کیا ہوا، لیکن اسے اس بات کی وضاحت کرنے کی ضرورت ہے کہ بہتری کے طور پر کیا شمار ہوتا ہے۔
نتائج کو چیک کرنے کے بعد یہ تعین کرنے کے لیے کہ کون سے میٹرکس اہم ہیں، انتخاب کا معیار خود اصلاح کا حصہ ہو سکتا ہے۔ تو آئیے ایجنٹ کے تیار کردہ ورژن کے چلنے سے پہلے پروموشن کے اصولوں میں ترمیم کریں۔
SELECTION_RULE = """
# Version selection rule (fixed before any version was run)
A challenger replaces the incumbent champion only if it passes ALL THREE gates:
1. Validation Sharpe is not worse than the incumbent's
2. Validation max drawdown is within 2 percentage points of the incumbent's
3. Development annual turnover is no more than 20% above the incumbent's
Ties go to the incumbent. A newer version does not automatically replace an older one.
A higher development Sharpe is not sufficient and is not one of the gates.
"""
(WS/"SELECTION_RULE.md").write_text(SELECTION_RULE)
def select_champion(challenger, incumbent, name_c, name_i):
if incumbent is None: return name_c, "no incumbent"
checks = [("validation Sharpe not worse",
challenger["val_sharpe"] >= incumbent["val_sharpe"]),
("validation drawdown within 2pp",
challenger["val_max_dd"] >= incumbent["val_max_dd"] - 0.02),
("turnover within +20%",
challenger["dev_turnover"] <= incumbent["dev_turnover"] * 1.20)]
failed = [n for n, ok in checks if not ok]
if failed:
return name_i, "incumbent retained; challenger failed: " + "; ".join(failed)
return name_c, "challenger passed all three gates"
def best_of(version):
reg = pd.read_csv(REGISTRY)
rows = reg[(reg.version == version) & (reg.status == "ok")]
return None if rows.empty else rows.sort_values("val_sharpe", ascending=False).iloc[0]
print(SELECTION_RULE)
ایجنٹ کے حکمت عملی کے نتائج دیکھنے سے پہلے اب اصول میں ترمیم کی گئی ہے۔
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 8 انتخاب کے قوانین](https://umang.pk/wp-content/uploads/2026/08/1786768966_859_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
یہاں انتخاب کے دو درجے ہیں۔
best_of() سب سے پہلے، ہم سب سے زیادہ طاقتور اور کامیاب ترتیب تلاش کرتے ہیں. ورژن کے اندر توثیق تیز استعمال کریں۔ تاہم، اندرونی جھاڑو جیتنا خود بخود اس حکمت عملی کو نیا چیمپئن نہیں بناتا۔ select_champion() اس کے بعد ان امیدواروں کا موازنہ تینوں دروازوں پر آنے والے امیدواروں سے کیا جاتا ہے۔
ڈویلپمنٹ شارپ جان بوجھ کر اس دروازے پر نہیں ہے۔ ایجنٹ یہ سمجھنے کے لیے ترقیاتی کارکردگی کا استعمال کر سکتے ہیں کہ آیا تبدیلیاں توقع کے مطابق ہو رہی ہیں، لیکن بڑے پیمانے پر ترقیاتی بہتری کمزور توثیق کے ثبوت کی تلافی نہیں کر سکتی۔
یہ فرق اس وقت اہم ہو جاتا ہے جب ایجنٹ اپنی حکمت عملیوں میں ترمیم کرنا شروع کر دیتے ہیں۔ ترقی کے دوران ایک نیا ورژن بہت بہتر نظر آ سکتا ہے، لیکن اسے پھر بھی مسترد کیا جا سکتا ہے۔
دستی بیس لائن سیٹ اپ
ڈیپ ایجنٹوں کو تحقیقی ٹولز فراہم کرنے سے پہلے، ہم ابتدائی حکمت عملی کو اسی تشخیصی پرت کے ذریعے دستی طور پر چلاتے ہیں۔ یہ ایک معروف حوالہ نقطہ فراہم کرتا ہے اور اس بات کو یقینی بناتا ہے کہ ایجنٹ کی حکمت عملی میں ترمیم شروع کرنے سے پہلے ڈیٹا، حکمت عملی کی منطق، بیک ٹیسٹنگ انجن، اور بینچ مارک کیلکولیشنز سبھی میچ کرتے ہیں۔
بیس لائن ڈالر والیوم فلٹر کے ساتھ 126 دن کی ایڈجسٹ شدہ اختتامی رفتار کا استعمال کرتی ہے۔ ہر مہینے کے آخر میں، ETF صرف اس وقت اہل ہوتا ہے جب اس کی رفتار مثبت ہو اور اس کا 20 دن کا اوسط ڈالر کا حجم اس کی 120 دن کی اوسط سے زیادہ ہو۔ یہ حکمت عملی رفتار کے لحاظ سے اہل ETFs کی درجہ بندی کرتی ہے، سب سے اوپر تین ETFs کے برابر وزن کو برقرار رکھتی ہے، اور جب کوئی اہل ETFs دستیاب نہیں ہوتے ہیں تو اس میں نقد رقم ہوتی ہے۔
def manual_baseline(data, mom_window=126, vol_short=20, vol_long=120,
vol_ratio_min=1.0, top_n=3):
adj, cls, vol = data["adj_close"], data["close"], data["volume"]
mom = adj.pct_change(mom_window)
dv = cls * vol
ratio = dv.rolling(vol_short).mean() / dv.rolling(vol_long).mean()
ok = (mom > 0) & (ratio > vol_ratio_min)
dates = pd.DatetimeIndex(adj.index.to_series().resample("ME").last().dropna())
w = pd.DataFrame(0.0, index=dates, columns=adj.columns)
for d in dates:
picks = mom.loc[d][ok.loc[d]].dropna().nlargest(top_n).index
if len(picks):
w.loc[d, picks] = 1.0 / len(picks)
return w
d = DATA["dev"]
bt = backtest(manual_baseline(d), d["returns"])
ev = bt.loc[d["eval_start"]:]
spy = d["returns"]["SPY"].loc[d["eval_start"]:]
print(metrics(ev, spy))
fig, ax = plt.subplots(2, 1, figsize=(9, 5), sharex=True, height_ratios=[2, 1])
eq = (1 + ev["ret"]).cumprod()
ax[0].plot(eq, label="strategy"); ax[0].plot((1 + spy).cumprod(), label="SPY")
ax[0].set_yscale("log"); ax[0].legend(); ax[0].set_title("Development 2005-2017")
ax[1].fill_between(eq.index, (eq / eq.cummax() - 1), 0, alpha=.4)
ax[1].set_ylabel("drawdown")
plt.tight_layout()
plt.show()
ایک ترقی کی دوڑ واپسی:
{'cagr': 0.0549, 'ann_ret': 0.0642, 'vol': 0.1463, 'sharpe': 0.4387, 'sortino': 0.6047, 'max_dd': -0.2606, 'ann_turnover': 11.6605, 'ann_cost': 0.0117, 'avg_cash': 0.2109, 'bench_cagr': 0.0847}
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 9 دستی حوالہ اثاثہ وکر](https://umang.pk/wp-content/uploads/2026/08/1786768966_548_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
حوالہ مرکبات ہیں: 5.49% ہر سال ترقی کی مدت کے دوران 0.4387 تیز اور زیادہ سے زیادہ کمی -26.06%. SPY کمپاؤنڈ 8.47% اسی مدت میں ایجنٹوں کے لیے پہلے سے بہتر نتائج فراہم کرنے کے بجائے، ہم جان بوجھ کر ایک کمزور ریونیو پروفائل کے ساتھ حکمت عملی کے ساتھ شروعات کر رہے ہیں۔
اسٹاک وکر کچھ سیاق و سباق کا اضافہ کرتا ہے۔ اس حکمت عملی نے بڑی حد تک 2008 میں SPY کے خاتمے سے گریز کیا اور اس مدت کے کچھ حصے کے لیے اسے تقریباً فلیٹ رکھا، لیکن بحالی کے دوران اس کا زیادہ تر فائدہ چھوڑ دیا۔ لہٰذا، کم ڈرا ڈاون کی شرح بامعنی واپسی کی تجارت پیدا کرتی ہے۔
تجارتی سرگرمی ایک اور کمزوری ہے۔ سالانہ فروخت تک پہنچ گئی۔ 11.6605اس کا تقریباً یوں ترجمہ ہوتا ہے: 1.17% سالانہ لین دین کے اخراجات 10 بیسس پوائنٹس کے ساتھ۔ یہ حکمت عملی بھی 21.09% پورٹ فولیو میں اوسط نقد۔
سب سے اہم بات یہ ہے کہ یہ نتائج اس کے ساتھ مطابقت رکھتے ہیں: volume_mom یہ ایک بینچ مارک ہے جس کا ہم نے پہلے درست حساب لگایا ہے۔ اس سے ظاہر ہوتا ہے کہ دستی طور پر لکھی گئی حکمت عملی اور مشترکہ تشخیصی انجن مستقل طور پر کام کر رہے ہیں۔
گہری ایجنٹوں کی تحقیقی ٹیم کی تشکیل
تعییناتی تحقیق کی تہہ اب مکمل ہو چکی ہے۔ حکمت عملیوں کی جانچ صرف فکسڈ انجن کے ذریعے کی جا سکتی ہے، تمام تجربات ریکارڈ کیے جاتے ہیں، اور انتخاب کے اصول پہلے سے ہی اس بات کی وضاحت کرتے ہیں کہ چیلنجر کو موجودہ چیمپئن کو تبدیل کرنے کے لیے کیا کرنا چاہیے۔
اب آپ ایجنٹ کی پرتیں شامل کر سکتے ہیں۔
میں تحقیقی عمل کو تین کرداروں میں تقسیم کروں گا:
-
کوئی راستہ نہیں اسٹریٹجک انجینئر ایک کمپنی جو آئیڈیاز کو نافذ اور جانچتی ہے۔
-
کوئی راستہ نہیں تحقیقی نقاد نتیجے کے ثبوت کو چیلنج کرنا
-
کوئی راستہ نہیں کوآرڈینیٹر یہ آرڈر کا انتظام کرنے اور انتخاب کے قواعد کو نافذ کرنے کا ذمہ دار ہے۔
بریک اپ جان بوجھ کر ہوا تھا۔ ایک ہی ایجنٹ کو حکمت عملی تجویز کرنے، اپنے کام کا جائزہ لینے اور پھر فیصلہ کرنے کے قابل نہیں ہونا چاہیے کہ آیا وہ حکمت عملی کو فروغ دینے کے قابل ہے۔
1. ایجنٹ کے کردار اور حدود طے کریں۔
سب سے پہلے، اپنی ٹیم کے ذریعہ استعمال کردہ ماڈل کو شروع کریں۔
load_dotenv(override=True)
from deepagents import create_deep_agent, FilesystemPermission
from deepagents.backends import FilesystemBackend
from langchain.chat_models import init_chat_model
from langgraph.checkpoint.memory import InMemorySaver
MODEL_ID = "openai:gpt-5.6-terra"
WORKER = init_chat_model(MODEL_ID, reasoning={"effort": "low"})
MANAGER = init_chat_model(MODEL_ID, reasoning={"effort": "medium"})
چونکہ انجینئرز کی ملازمتیں بنیادی طور پر لاگو ہوتی ہیں، اس لیے انہیں کم تخمینہ کی ترتیبات ملتی ہیں۔ رابطہ کار اور نقاد اعلیٰ ترتیبات کا استعمال کرتے ہیں کیونکہ انہیں ثبوتوں کا موازنہ کرنا، نتائج کو چیلنج کرنا، اور تحقیقی فیصلے کرنا چاہیے۔
ایجنٹوں کو ایک عام تعریف کی بھی ضرورت ہوتی ہے کہ ایک درست حکمت عملی کیسی دکھتی ہے۔ ہر ورژن کو اس کا اپنا انٹرفیس بنانے پر مجبور کرنے کے بجائے، ہم وہی اسٹریٹجک معاہدے فراہم کرتے ہیں جن کی تعییناتی انجن توقع کرتا ہے۔
CONTRACT = """
Every strategy file defines exactly one function:
def target_weights(data, **params) -> pd.DataFrame
index : rebalance dates, all of which must exist in data["adj_close"].index
columns : the nine tickers
values : target weights, each row summing to <= 1.0 (remainder is cash)
data keys: adj_close, close, volume, returns (DataFrames, dates x tickers)
Use adj_close for momentum and returns. Use close * volume for dollar volume.
A row dated t is a decision made on t's close; the engine applies it on t+1.
Guard against empty selections: if nothing qualifies, leave the row at zero.
Your code runs in an isolated subprocess with no network, no credentials and no
holdout data. Import only pandas and numpy.
Working skeleton:
import pandas as pd
def target_weights(data, mom_window=126, top_n=3):
adj = data["adj_close"]
mom = adj.pct_change(mom_window)
dates = pd.DatetimeIndex(adj.index.to_series().resample("ME").last().dropna())
w = pd.DataFrame(0.0, index=dates, columns=adj.columns)
for d in dates:
picks = mom.loc[d].dropna().nlargest(top_n).index
if len(picks):
w.loc[d, picks] = 1.0 / len(picks)
return w
"""
یہ اس بات کو یقینی بناتا ہے کہ تمام نظرثانی ایک ہی تشخیصی درجے کے ساتھ ہم آہنگ رہیں۔ انجینئرز یہ تبدیل کرنے کے لیے آزاد ہیں کہ ہدف کے وزن کیسے بنائے جاتے ہیں، لیکن وہ ان پٹ ڈیٹا کنٹریکٹ کو تبدیل نہیں کر سکتے یا انجن کو نظرانداز نہیں کر سکتے جو بالآخر ان وزنوں کو اسکور کرتا ہے۔
اگلا، ہم پچھلے حصے سے تفتیشی کنٹرول براہ راست ایجنٹ پرامپٹ پر لاتے ہیں۔
RULES = f"""
Layout: /strategies/vN.py, /results/, /reviews/, /registry.csv, /decisions.jsonl
Stage gates, enforced by the sweep tool:
vN cannot be swept until v(N-1) has successful runs, a review at /reviews/v(N-1).md,
and a decision recorded via record_decision. There is no way around this.
Hard limits: three versions; at most 12 configurations per version; one major
structural change per revision. Engine, universe, splits, benchmark and cost
convention are fixed. The holdout does not exist for you; never ask for it.
{SELECTION_RULE}
Fixed benchmarks, computed before any version was written:
{BENCH_TEXT}
Do not call ls, glob, grep or read_file unless told a specific file exists and you
need its contents.
"""
اہم بات یہ ہے کہ یہ ایجنٹوں کے لیے بنائے گئے نئے اصول نہیں ہیں۔ یہ وہی حدود کو بے نقاب کرتا ہے جو ازگر پہلے سے نافذ کرتا ہے: تین ورژن، باؤنڈڈ سرچز، فکسڈ بینچ مارکس، فکسڈ لاگت، کوئی سٹیپ گیٹس، اور کوئی ہولڈ آؤٹ رسائی نہیں۔
اب آپ دو ماہر کردار بنا سکتے ہیں:
اسٹریٹجک انجینئر کو اسٹریٹجک معاہدہ ملتا ہے، sweep() سامان:
engineer = {
"name": "strategy-engineer",
"description": "Writes strategy files and sweeps them through the fixed backtester in one batched call. Use for anything that creates code or produces metrics.",
"system_prompt": f"""You implement strategies. You do not decide what to implement.
{RULES}{CONTRACT}
Procedure:
1. Write the strategy file with write_file.
2. Call sweep ONCE with the entire parameter grid as a JSON list. Never per configuration.
3. If a run errors, read the message, fix the file, call sweep again. Errors count
against the budget.
4. Report back in under 200 words: filename, the returned table verbatim, and the one
configuration you recommend with a one-line reason. Never paste code back.""",
"tools": [sweep],
"model": WORKER,
}
اس کا اختیار جان بوجھ کر تنگ ہے۔ انجینئرز حکمت عملی بنا سکتے ہیں اور ثبوت تیار کر سکتے ہیں: sweep()تاہم، یہ اس بات کا تعین نہیں کرتا کہ اگلا تحقیقی مفروضہ کیا ہوگا یا اس کی اپنی حکمت عملی چیمپئن کی جگہ لے گی۔
تحقیقی نقاد دوسری طرف کام کرتے ہیں۔
critic = {
"name": "research-critic",
"description": "Reads a results table and returns exactly one evidence-backed weakness with one proposed structural change. Use after every version is swept.",
"system_prompt": f"""You review results. You never write or edit strategy code.
{RULES}
The results table is given to you in the task description. Do not go looking for it.
Call read_registry only to compare against an earlier version.
Write your review to /reviews/vN.md under exactly these five headings:
Weakness one sentence
Evidence specific numbers from the table, compared against the fixed benchmarks
Change one structural change, not a parameter nudge
Expected what it should do to which metric, and why
Overfit risk how this could be curve-fitting, and what would disconfirm it
A higher Sharpe alone is not evidence. Compare against equal-weight buy-and-hold and
plain momentum, not just SPY. Check the 20bps column against the 10bps one, whether
the dev result survives validation, and whether neighbouring parameters behave
similarly. If dev and val disagree, that disagreement is the finding.""",
"tools": [read_registry],
"model": MANAGER,
"permissions": [
FilesystemPermission(operations=["write"], paths=["/strategies/**"], mode="deny"),
FilesystemPermission(operations=["read","write"], paths=["/**"], mode="allow"),
],
}
ناقدین صرف یہ نہیں پوچھ رہے ہیں کہ آیا کوئی حکمت عملی "اچھی لگ رہی ہے"۔ جائزے میں ایک کمزوری کی نشاندہی کرنی چاہیے، ثبوت کے ساتھ اس کمزوری کی تائید کرنی چاہیے، اور زیادہ فٹنگ کے واضح خطرے کے ساتھ ایک ساختی تبدیلی کی تجویز پیش کرنی چاہیے۔
زیادہ اہم بات یہ ہے کہ علیحدگی کو اشارہ کرنے کے بعد نافذ کیا جاتا ہے۔ نقاد کو واضح طور پر لکھنے تک رسائی سے انکار کر دیا گیا ہے: /strategies/**. آپ تحقیقی شواہد کی جانچ کر سکتے ہیں اور جائزے لکھ سکتے ہیں، لیکن آپ خاموشی سے ان حکمت عملیوں کو تبدیل نہیں کر سکتے جن کا جائزہ لینے کی ضرورت ہے۔
2. کوآرڈینیٹر بنائیں
کوآرڈینیٹر انجینئرز اور ناقدین کو پوری ریسرچ لوپ سے جوڑتے ہیں۔
COORDINATOR = f"""You run a quantitative research process and are judged on the honesty
of the process, not on the returns.
{RULES}
Your loop for each version N:
1. plan with write_todos
2. delegate implementation and sweeping to strategy-engineer
3. pass the engineer's table verbatim into the task description for research-critic
4. apply the selection rule yourself and state which gates passed or failed
5. call record_decision with the resulting champion and your rationale
Step 5 is mandatory. The next version is blocked until it is done.
Reject proposals that are parameter tuning dressed up as structure. The champion does
not change just because a newer version exists. Never overwrite an earlier version."""
agent = create_deep_agent(
model=MANAGER,
tools=[sweep, read_registry, record_decision],
system_prompt=COORDINATOR,
subagents=[engineer, critic],
backend=FilesystemBackend(root_dir=str(WS), virtual_mode=True),
checkpointer=InMemorySaver(),
name="coordinator",
)
کوآرڈینیٹر اس عمل کو منظم کرتا ہے، لیکن پھر بھی ہم نے پہلے ہی قائم کر دیے ہوئے تعییناتی کنٹرول کے اوپر بیٹھا ہے۔ آپ انجینئر کی طرف سے رپورٹ کردہ شارپ ریشوز بنائے بغیر، تجرباتی رجسٹریوں کو نظرانداز کیے، یا سخت وائرڈ قوانین کو نافذ کیے بغیر حکمت عملی پر عمل نہیں کر سکتے۔
فائل سسٹم بیک اینڈ ٹیموں کو حکمت عملی کی فائلوں، نتائج، جائزوں اور فیصلوں کے لیے مشترکہ تحقیقی کام کی جگہ فراہم کرتا ہے۔ virtual_mode=True ہم اس کام کی جگہ کو مندرجہ ذیل ایجنٹ سائیڈ راستوں سے بے نقاب کرتے ہیں: /strategies/v1.pyپسدید اس کا نقشہ نیچے دی گئی اصل تحقیقی ڈائرکٹری میں کرتا ہے۔
ہم بھی پورا رکھیں گے۔ v1 -> v2 -> v3 ہم ایک چیک پوائنٹ تھریڈ کے اندر ترتیب کو انجام دینے کے لیے ایک چھوٹا مددگار استعمال کرتے ہیں اور کوآرڈینیٹر کو کال کرتے ہیں۔
def run(prompt):
out = agent.invoke({"messages": [{"role":"user","content":prompt}]}, THREAD)
c = out["messages"][-1].content
print(c if isinstance(c, str) else
"n".join(b.get("text","") for b in c if b.get("type") == "text"))
return out
print("subagent models:", engineer["model"].model_name, critic["model"].model_name)
print(WORKER.invoke("reply with the single word: ok").content)
ایک حتمی جانچ اس بات کی تصدیق کرتی ہے کہ ماہر ماڈل کو کامیابی کے ساتھ شروع کیا گیا ہے۔
subagent models: gpt-5.6-terra gpt-5.6-terra
[{'type': 'text', 'text': 'ok', 'annotations': [], 'id': 'msg_09ea14bfb753e624006a72189dbf84819eac295e52e7d7ccd0', 'phase': 'final_answer'}]
اس وقت، تحقیقی ٹیم کے پاس وہ سب کچھ ہے جس کی انہیں ضرورت ہے۔ انجینئرز حکمت عملیوں کو نافذ اور جانچ سکتے ہیں، نقاد کوڈ کو تبدیل کیے بغیر ثبوت کو چیلنج کر سکتے ہیں، اور کوآرڈینیٹرز ہر ورژن کی جانچ اور جائزہ لینے اور باقاعدہ فیصلہ کرنے کے بعد ہی اپنی تحقیق کو آگے بڑھا سکتے ہیں۔
مینوئل بیس لائن v1 میں دوبارہ تیار کی گئی۔
پہلے ایجنٹ کے چکر میں کوئی نیا اسٹریٹجک آئیڈیا متعارف نہیں ہونا چاہیے۔ چونکہ ہمارے پاس پہلے سے ہی دستی طور پر تصدیق شدہ بیس لائن ہے، v1 یہ اس بات کو یقینی بنانے کا ایک کنٹرول شدہ طریقہ فراہم کرتا ہے کہ ایک نیا ایجنٹ ورک فلو اس حکمت عملی کو دوبارہ پیش کر سکتا ہے، پہلے سے طے شدہ تجربات چلا سکتا ہے، آزاد تنقیدی جائزے حاصل کر سکتا ہے، اور حقیقی نظرثانی شروع ہونے سے پہلے فیصلے ریکارڈ کر سکتا ہے۔
بنیادی منطق کو کام میں مکمل طور پر بیان کیا گیا ہے۔ واحد تلاش تین مومینٹم ونڈوز اور تین پورٹ فولیو سائزز میں نو پری رجسٹرڈ کنفیگریشنز کا ایک گرڈ ہے، جو انجینئرز کو پہلے نتائج دیکھنے کے بعد پیرامیٹر کی تلاش کو بڑھانے سے روکتی ہے۔
V1_BRIEF = """Build Version 1, the baseline.
Delegate to strategy-engineer. /strategies/v1.py: 126-day momentum from adjusted close;
20-day over 120-day average dollar volume from raw close x raw volume; eligible if
momentum > 0 and volume ratio > 1.0; rank eligible by momentum, hold top 3 equal weight,
rebalance monthly, cash otherwise. Parameters: mom_window, vol_short, vol_long,
vol_ratio_min, top_n.
Sweep exactly these nine in one call: mom_window in (63, 126, 189) crossed with
top_n in (2, 3, 4), everything else at default.
Pass the table to research-critic for a review of v1, telling it to compare against the
fixed benchmarks. Then apply the selection rule (v1 has no incumbent, so it becomes the
champion by default) and call record_decision for v1.
Finally report: the chosen configuration, how it compares to equal-weight buy-and-hold
and plain momentum, and the critic's proposal with your decision."""
_ = run(V1_BRIEF)
ایک مکمل ایجنٹ سائیکل واپس آتا ہے:
## Version 1 baseline completed
**Champion:** v1 (initial version; no incumbent, so selected by default)
**Chosen configuration:**
```json
{
"mom_window": 126,
"vol_short": 20,
"vol_long": 120,
"vol_ratio_min": 1.0,
"top_n": 2
}
```
This was selected because it produced the highest validation Sharpe of the nine predefined configurations: **0.542**.
### Selected-result comparison
| Metric | V1 selected | Equal-weight buy & hold | Plain momentum |
|---|---:|---:|---:|
| **Development CAGR** | 0.0550 | 0.0904 | 0.0750 |
| **Development Sharpe** | 0.4240 | 0.5532 | 0.5363 |
| **Development max drawdown** | -0.2760 | -0.5203 | -0.2817 |
| **Development annual turnover** | 11.5890 | 0.0000 | 7.2798 |
| **Validation CAGR** | 0.1000 | 0.1769 | 0.2051 |
| **Validation Sharpe** | 0.5420 | 0.8697 | 0.9279 |
| **Validation max drawdown** | -0.2950 | -0.3371 | -0.2901 |
V1 has lower development drawdown than both benchmarks, but it underperforms equal-weight buy-and-hold and plain momentum on both development and validation CAGR and Sharpe. It also trades substantially more than plain momentum (development turnover **11.589** vs. **7.280**).
### Selection-rule application
V1 has **no incumbent**, so it becomes champion by default.
- Gate 1 — validation Sharpe: **not applicable**
- Gate 2 — validation max drawdown: **not applicable**
- Gate 3 — development turnover: **not applicable**
The decision was recorded with v1 as champion.
### Critic review and decision
**Critic’s evidence-backed weakness:** the always-invested selection strategy did not achieve benchmark-level risk-adjusted performance despite materially higher turnover. The longer 189-day specification had the strongest development result, but that relative advantage did not persist in validation. The 126-day configurations were more consistent, but still remained well below both fixed benchmarks in validation Sharpe.
**Critic’s proposed structural change:** add a **dual-momentum market-regime rule**: hold the existing relative-momentum portfolio only when broad-market absolute momentum is positive, otherwise move to cash.
**Decision:** retain v1 as the baseline champion. The proposal is a valid single structural change—not parameter tuning—and is appropriate to test as the next version, subject to the fixed version-selection gates.
انجینئرز تمام نو رنز مکمل کرتے ہیں اور سب سے ثابت شدہ Sharpe کنفیگریشن کو منتخب کرتے ہیں۔
{
"mom_window": 126,
"vol_short": 20,
"vol_long": 120,
"vol_ratio_min": 1.0,
"top_n": 2
}
وہ تصدیق تیز 0.542. یہ v1 سویپ کے اندر سب سے طاقتور کنفیگریشن ہے، لیکن فکسڈ بینچ مارک "مضبوط حکمت عملی" کے ساتھ "اس تلاش میں بہترین" کو الجھانے سے گریز کرتا ہے۔
V1 اب بھی ترقی اور توثیق CAGR اور Sharpe دونوں میں مساوی وزن کی خرید اور ہولڈ اور عمومی رفتار کی پیروی کر رہا ہے۔ یہ باقاعدہ رفتار سے بہت زیادہ تجارت بھی کرتا ہے۔ اس حکمت عملی کے ترقیاتی نقصانات کم ہیں، لیکن صرف یہ فائدہ مجموعی نتیجہ کو پرکشش بنانے کے لیے کافی نہیں ہے۔
چونکہ ابھی تک کوئی ذمہ دار نہیں ہے، تینوں پروموشن گیٹ ویز لاگو نہیں ہوتے ہیں۔ v1 یہ پہلا چیمپیئن بن جاتا ہے جسے بعد کے تمام ورژنز کو ہرانا ضروری ہے۔
پھر نقاد جیتنے والی صف سے آگے نظر آتا ہے۔ 189 دن کے مختلف قسم کے مضبوط ترقیاتی نتائج تھے، لیکن توثیق میں اس کے فوائد ختم ہو گئے تھے۔ 126 دن کا ویرینٹ مختلف پورٹ فولیو سائزز میں زیادہ مطابقت رکھتا تھا، لیکن شارپس کی توثیق اب بھی سادہ بینچ مارک سے بہت نیچے تھی۔
ایک مختلف رفتار ونڈو تجویز کرنے کے بجائے: top_n قدر کے ناقدین ساختی تبدیلیوں کا مشورہ دیتے ہیں۔ یعنی، ایک وسیع مارکیٹ مطلق مومینٹم فلٹر شامل کرنا۔ روایتی یک طرفہ مومینٹم پورٹ فولیو اس وقت فعال رہتا ہے جب SPY کی رفتار مثبت ہوتی ہے اور جب مارکیٹ کے نظام منفی ہوتے ہیں تو نقد رقم میں منتقل ہوتے ہیں۔
اس سے پہلے کہ ہم آگے بڑھیں، ہم اس بات کی تصدیق کر سکتے ہیں کہ پورے v1 سائیکل نے درحقیقت اسٹیج گیٹ کے لیے درکار تین نمونے پیچھے چھوڑ دیے ہیں: ایک کامیاب تجربہ، ایک تنقیدی جائزہ، اور ایک ریکارڈ شدہ فیصلہ۔
print(pd.read_csv(REGISTRY).groupby(["version","status"]).size())
print("decisions:", [d["version"] for d in _decisions()])
assert (WS/"reviews"/"v1.md").exists(), "v1 review missing"
assert any(d["version"] == "v1" for d in _decisions()), "v1 decision missing"
print("v1 cycle complete")
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 10 V1 تصدیق](https://umang.pk/wp-content/uploads/2026/08/1786768966_876_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
پہلا مرحلہ مکمل ہو گیا ہے۔ v1 لہذا اب آپ موجودہ چیمپئن ہیں، ناقدین نے کچھ کمزوریوں کی نشاندہی کی ہے، اور اگلے ورژن میں جانچنے کے لیے ایک واضح ساختی مفروضہ ہے۔
ایجنٹوں کو اپنی حکمت عملیوں کو ایڈجسٹ کرنے دیں۔
کے ساتھ v1 ایک بار پرائمری چیمپئن کے طور پر قائم ہونے کے بعد، ریسرچ لوپ آخر کار تولید سے آگے بڑھ سکتا ہے۔ اس مقام سے، تمام نئے ورژن پچھلے تنقیدی جائزوں میں نشاندہی کی گئی کمزوریوں سے آنے چاہئیں، اور چیلنج کرنے والے صرف موجودہ ورژنز کی جگہ لے لیں گے اگر وہ تینوں فکسڈ سلیکشن گیٹس کو پاس کر لیں۔
v2 میں مارکیٹ رجیم فلٹرز کی جانچ کرنا
v1 ناقدین نے ایک ساختی تبدیلی کا مشورہ دیا: دوسرے لفظوں میں، اپنی موجودہ یک طرفہ رفتار کی حکمت عملی کو برقرار رکھیں، لیکن جب بھی SPY کی مطلق رفتار مثبت نہ ہو تو پورٹ فولیو کو نقد رقم میں منتقل کریں۔
پیرامیٹر تلاش کو فوری طور پر دوبارہ کھولنے کے بجائے، ہم اپنی موجودہ v1 چیمپئن کنفیگریشن کا استعمال کرتے ہوئے اس تبدیلی کی جانچ کریں گے۔ یہ پیرامیٹر ٹیوننگ کے دوسرے دور کے بجائے بنیادی طور پر رجیم فلٹر کے بارے میں پہلا v2 موازنہ کرتا ہے۔
V2_BRIEF = """Review the critic's v1 proposal in /reviews/v1.md. If you approve it, have
strategy-engineer implement it as /strategies/v2.py. Do not modify v1.py.
Sweep at most 12 configurations in one call. Pass the table to research-critic for a
review written to /reviews/v2.md. Then apply the selection rule between v2 and the
current champion, state which of the three gates passed and which failed, and call
record_decision for v2. Do not proceed past that."""
_ = run(V2_BRIEF)
ایجنٹ ٹیم کی واپسی:
Approved the v1 critic proposal as a single structural change: a dual-momentum regime filter that moves the portfolio to cash when SPY’s adjusted-close momentum over the existing `mom_window` is non-positive.
- Implemented as `/strategies/v2.py`
- `/strategies/v1.py` was not modified.
- Swept one configuration using the current v1 champion parameters:
```json
{
"mom_window": 126,
"vol_short": 20,
"vol_long": 120,
"vol_ratio_min": 1.0,
"top_n": 2
}
```
### V2 result
| Metric | V1 champion | V2 |
|---|---:|---:|
| Development Sharpe | 0.424 | 0.611 |
| Development max drawdown | -0.276 | -0.190 |
| Development turnover | 11.589 | 9.814 |
| Validation Sharpe | 0.542 | 0.321 |
| Validation max drawdown | -0.295 | -0.295 |
The critic review was written to `/reviews/v2.md`.
### Selection rule: v2 vs. v1
1. **Validation Sharpe — failed**
V2: **0.321** vs. V1: **0.542**.
2. **Validation maximum drawdown — passed**
V2: **-0.295** vs. V1: **-0.295**; difference is 0.0 percentage points, within the 2-point limit.
3. **Development annual turnover — passed**
V2: **9.814** vs. V1: **11.589**; V2 is below V1 and below the allowed 20%-higher limit of **13.907**.
Because v2 failed the validation-Sharpe gate, it does **not** replace the incumbent. The decision was recorded: **v1 remains champion**.
پہلی نظر میں، v2 ایک بہت بڑی بہتری معلوم ہوتی ہے۔ ترقی تیز چھلانگ سے: 0.4235 کو 0.6110زیادہ سے زیادہ کمی ہے۔ -27.57% کو -18.99%سالانہ فروخت 11.5888 کو 9.8139.
صرف ترقی کی مدت کو دیکھیں تو ایسا لگتا ہے کہ Regime Filter نے ایک ساتھ کئی مسائل حل کیے ہیں۔
تصدیق ایک بہت مختلف کہانی بتاتی ہے۔ سے تیز گرتا ہے: 0.5424 v1 کے لیے 0.3207 v2 کے لیے، زیادہ سے زیادہ کمی عملی طور پر کوئی تبدیلی نہیں ہے۔ لہذا، ترقی میں بہتری درحقیقت اس وقت تک نہیں رہتی جو اس بات کا تعین کرتی ہے کہ حکمت عملی کو آگے بڑھانا ہے یا نہیں۔
یہ وہ جگہ ہے جہاں انتخاب کے قوانین کام آتے ہیں۔ V2 ڈیکلائن گیٹ اور ریونیو گیٹ کو آسانی سے پاس کرتا ہے، لیکن پہلی ضرورت میں ناکام ہو جاتا ہے۔ تصدیق شارپ قائم کمپنیوں سے بدتر نہیں ہو سکتا.
لہذا بہت زیادہ مضبوط ترقیاتی نتائج کے باوجود، v1 اب بھی چیمپئن ہے۔
ناقدین کو ثبوت میں ایک اور کمزوری بھی ملی۔ V2 کا تجربہ صرف ایک کنفیگریشن میں کیا گیا۔ اس کا مطلب یہ ہے کہ بڑے پیمانے پر ترقی کی بہتری میں کوئی ملحقہ پیرامیٹر سپورٹ نہیں ہے۔ حکومتی قوانین کو خود کو ایڈجسٹ کرنے کے بجائے، ناقدین نے ایک اور ساختی اصلاحات کی تجویز پیش کی۔ اس کا مطلب ہے بائنری ڈالر کے حجم کے اہلیت کے فلٹر کو منتخب مومینٹم اثاثوں میں اتار چڑھاؤ کے ساتھ ایڈجسٹ شدہ وزن کے ساتھ تبدیل کرنا۔
ہم اس خیال کو جانچنے سے پہلے اس بات کو یقینی بنائیں گے کہ تمام v2 تجربات، جائزے اور فیصلے برقرار ہیں۔
print(pd.read_csv(REGISTRY).groupby(["version","status"]).size())
print("decisions:", [d["version"] for d in _decisions()])
assert (WS/"reviews"/"v2.md").exists(), "v2 review missing"
assert any(d["version"] == "v2" for d in _decisions()), "v2 decision missing"
print("v2 cycle complete")
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 11 V2 تصدیق](https://umang.pk/wp-content/uploads/2026/08/1786768966_365_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
لہذا، V2 بغیر پروموشن کے بھی مفید ثبوت فراہم کرتا ہے۔
v3 میں حتمی نظرثانی چل رہا ہے۔
v2 جائزہ لینے والوں کی تجاویز حتمی نظرثانی بن جاتی ہیں۔ V3 v2 میں متعارف کرائے گئے وسیع مارکیٹ رجیم فلٹرز کو برقرار رکھتا ہے، بائنری ڈالر کے حجم کی اہلیت کے اصولوں کو ہٹاتا ہے، اور مومینٹم اثاثوں کو ان کی حال ہی میں محسوس کی گئی اتار چڑھاؤ کے الٹا متناسب وزن کرتا ہے۔
اس بار، انجینئر تین ملحقہ پورٹ فولیو سائز کی جانچ کرتے ہیں۔ top_n پر سیٹ کریں 2، 3اور 4. حتمی تنقیدی جائزہ اور انتخاب کے فیصلے کے بعد، کوآرڈینیٹر کو فوری طور پر ان حکمت عملیوں کو منجمد کرنا چاہیے جو اب بھی چیمپئنز کے طور پر اہل ہیں۔
V3_BRIEF = """Implement the final approved revision as /strategies/v3.py. Do not modify
v1 or v2. Sweep at most 12 configurations in one call, get a critic review at
/reviews/v3.md, apply the selection rule, and call record_decision for v3.
Then write /strategies/frozen.json containing exactly:
{"version": "", "params": {...}, "rationale": "..."}
where the version is whichever the selection rule says is champion, which may be v1 or
v2 rather than v3. After writing that file, stop."""
_ = run(V3_BRIEF)
display(Markdown("### Decision log"))
for dd_ in _decisions():
print(f"{dd_['version']} -> champion {dd_['champion']}: {dd_['rationale'][:160]}")
print("nfrozen:", (WS/"strategies"/"frozen.json").read_text())
مکمل آؤٹ پٹ ہے:
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 12 V3 نتائج](https://umang.pk/wp-content/uploads/2026/08/1786768966_384_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
سب سے طاقتور v3 کنفیگریشن ہے۔ top_n=3 شارپ کی تصدیق ہو چکی ہے۔ 0.5377. v1 سے بہت ملتا جلتا ہے۔ 0.5424. V3 بھی -0.2954 کو -0.2884 ترقی کی فروخت میں کمی آئی۔ 11.5888 کو 7.0480.
تو تین میں سے دو دروازے اندر سے گزرتے ہیں۔
شارپ کی توثیق میں باقی فرق مندرجہ ذیل ہیں: 0.0047یہ پورے تجربے کے سب سے اہم فیصلوں میں سے ایک ہے۔ یہ دعوی کرنا آسان ہوگا کہ نمبرز مؤثر طریقے سے ایک جیسے ہیں اور v3 کو فروغ دیں گے کیونکہ اس میں بہتر توجہ اور ٹرن اوور ہے۔
لیکن اس کا مطلب ہے نتائج کو دیکھنا اور معیارات کو تبدیل کرنا۔
v3 کے وجود سے پہلے اس اصول میں ترمیم کی گئی تھی، اور ہمیں یہ یقینی بنانا ہوگا کہ Sharpe پرانے اصول سے بدتر نہیں ہے۔ V3 آسانی سے اس ضرورت کو یاد کرتا ہے۔
لہذا، V1 حتمی چیمپئن رہتا ہے۔
کوآرڈینیٹر نتائج کو درج ذیل جگہ پر ریکارڈ کرتا ہے: frozen.jsonبالکل ایسے پیرامیٹرز پر مشتمل ہے جو پورے اسٹڈی لوپ میں محفوظ رہے۔ اس وقت حکمت عملی کے انتخاب کا مرحلہ ختم ہو چکا ہے۔ اس کے بعد آنے والا کوئی بھی ورژن ہولڈ آؤٹ تک پہنچنے والے ورژن کو تبدیل نہیں کر سکتا۔
چیمپئنز کو منجمد کریں اور ہول آؤٹ کو غیر مقفل کریں۔
ریسرچ لوپ مکمل ہو گیا ہے، لیکن ہولڈ آؤٹ ابھی تک سامنے نہیں آئے ہیں۔ لانچ سے پہلے، ہم اس بات کو یقینی بنائیں گے کہ حکمت عملی کے تینوں چکر مکمل ہو چکے ہیں اور آیا چیمپئنز پہلے ہی منجمد ہو چکے ہیں۔
یہ توثیق مرکزی تحقیقی عمل کی ایجنٹ پرت سے باہر کی جاتی ہے۔ یہ فرق اہم ہے۔ اگر ایجنٹ خود فیصلہ کر سکتے ہیں کہ کب ہولڈ آؤٹ کو بے نقاب کرنا ہے، تو حدود ارد گرد کے نظام کی بجائے ایجنٹ کے رویے پر منحصر ہوتی ہیں۔
frozen = json.loads((WS/"strategies"/"frozen.json").read_text())
print("frozen:", frozen)
assert len(_decisions()) == 3, f"expected 3 decisions, found {len(_decisions())}"
for v in ["v1","v2","v3"]:
assert (WS/"reviews"/f"{v}.md").exists(), f"missing review for {v}"
assert not pd.read_csv(REGISTRY).query(f"version=='{v}' and status=='ok'").empty, f"no runs for {v}"
print("all three cycles complete")
for field in ["adj_close","close","volume"]:
DATA["holdout"][field].to_parquet(WS/"data"/f"holdout_{field}.parquet")
final = {}
for split in ["dev","val","holdout"]:
res = run_isolated(WS/"strategies"/f"{frozen['version']}.py", frozen["params"], split)
assert res["ok"], res["error"]
final[split] = res["metrics"]
plt.plot(pd.Series(res["equity"], index=pd.to_datetime(res["dates"])), label=split)
plt.yscale("log"); plt.legend(); plt.title(f"frozen {frozen['version']} across all periods"); plt.show()
(WS/"results"/"holdout.json").write_text(json.dumps(final, indent=2))
BENCH_HOLD = benchmark_table("holdout")
comparison = pd.concat([pd.DataFrame(final).T.assign(source="strategy"),
BENCH_HOLD.assign(source="benchmark_holdout")])
comparison[["cagr","sharpe","sortino","max_dd","ann_turnover","source"]]
چیک کے ذریعے اسی کی تصدیق کریں۔ v1 ہولڈ آؤٹ سے پہلے منتخب کردہ کنفیگریشن ابھی بھی طے شدہ ہے:
frozen: {
'version': 'v1',
'params': {
'mom_window': 126,
'vol_short': 20,
'vol_long': 120,
'vol_ratio_min': 1.0,
'top_n': 2
},
'rationale': "V1 remains champion after v3 failed the required validation-Sharpe gate (0.538 versus v1's 0.542), although v3 passed the validation-drawdown and development-turnover gates."
}
all three cycles complete
ان چیکس کے پاس ہونے کے بعد ہی ہولڈ آؤٹ ڈیٹا ورک فلو میں دستیاب ہوتا ہے اور منجمد حکمت عملی کا جائزہ لیا جاتا ہے۔
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 13 V1 تمام ادوار میں جم جاتا ہے۔](https://umang.pk/wp-content/uploads/2026/08/1786768966_83_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
حصص کا خاکہ ترقی، توثیق، اور ہولڈ آؤٹ میں ایک ہی طے شدہ v1 کنفیگریشن کو ظاہر کرتا ہے۔
ہر پیریڈ کا الگ سے جائزہ لیا جاتا ہے، اس لیے تین لائنوں کو ایک مسلسل جامع پورٹ فولیو کے طور پر نہیں پڑھنا چاہیے۔ یہاں اہم بات یہ ہے کہ تینوں ادوار میں حکمت عملی کی منطق اور پیرامیٹرز میں کوئی تبدیلی نہیں آئی۔
یہاں حتمی موازنہ ہے:
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 14 حتمی نتائج کا موازنہ کریں۔](https://umang.pk/wp-content/uploads/2026/08/1786768966_985_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
ایک پوشیدہ ہولڈ آؤٹ پر منجمد v1 پیداوار 13.98% سی اے جی آر اور 0.7962 تیز دونوں اسی مدت کے دوران SPY بائے اینڈ ہولڈ، ایکویل ویٹ بائی اینڈ ہولڈ، جنرل مومنٹم اور والیوم مومینٹم بینچ مارکس سے زیادہ ہیں۔
زیادہ سے زیادہ کمی ہے۔ -23.04% اگرچہ SPY اور ریگولر مومینٹم سے قدرے چھوٹا ہے، لیکن مساوی وزن خریدنا اور ہولڈ کرنا اب بھی منفی پہلو سے بہتر ہے۔ -18.23%.
یہ ایک سازگار نتیجہ ہے، لیکن اس سے وہ تبدیلی نہیں آتی جو ہولڈ آؤٹ سے پہلے سیکھا گیا تھا۔ V1 میں اب بھی ایک سادہ بینچ مارک کے مقابلے میں بہت کمزور شارپ توثیق تھی، اور اس طرح کے نمبروں کے موجود ہونے سے پہلے اسے منجمد کر دیا گیا تھا۔
ہولڈ آؤٹ پہلے سے طے شدہ حکمت عملیوں کا ایک پوشیدہ جائزہ فراہم کرتے ہیں۔ آپ کو یہ فیصلہ کرنے کا دوسرا موقع نہیں دیا جاتا ہے کہ کس حکمت عملی کی جانچ کرنی ہے۔
مکمل مطالعہ سے باخبر رہنے کا آڈٹ
تجربہ ختم کرنے سے پہلے کوآرڈینیٹر کو ایک حتمی کام دیں۔ خیال یہ ہے کہ سب کچھ پہلے ہی منجمد ہونے کے بعد پورے ٹریس کا جائزہ لیا جائے۔
اس وقت نتائج حکمت عملی کو تبدیل نہیں کر سکتے۔ کوآرڈینیٹر کو ایک مقررہ ترتیب، تینوں ادوار سے میٹرکس، ہولڈ آؤٹ بینچ مارکس، تجربہ کی رجسٹری، فیصلے کی تاریخ، اور تنقیدی جائزے موصول ہوتے ہیں۔ میں آپ کو واضح طور پر بتاتا ہوں کہ نتائج کا دفاع نہ کریں۔
REPORT_BRIEF = f"""The holdout has been run once and the strategy is frozen. Nothing can change now.
Frozen: {json.dumps(frozen)}
Metrics by period: {json.dumps(final)}
Holdout benchmarks: {BENCH_HOLD[COLS_B].to_json()}
Call read_registry once with no argument, read /decisions.jsonl and every file in
/reviews/, then write /report.md covering:
1. What changed at each version and what evidence drove it
2. How the selection rule decided each champion, including gates that failed
3. Whether the revisions improved the research case, separately from returns
4. How the frozen strategy compares to SPY buy-and-hold, equal-weight buy-and-hold,
and plain momentum on the holdout
5. Whether the volume filter earned its turnover
6. Where you made weak decisions, accepted thin evidence, or got lucky
Cite run numbers from the registry. Do not defend the result."""
_ = run(REPORT_BRIEF)
![لینگ چین ڈیپ ایجنٹس کا استعمال کرتے ہوئے ملٹی ایجنٹ ٹرانزیکشن انویسٹی گیشن سسٹم کیسے بنایا جائے۔ [Full Handbook] 15 جوابی رپورٹ](https://umang.pk/wp-content/uploads/2026/08/1786768966_606_لینگ-چین-ڈیپ-ایجنٹس-کا-استعمال-کرتے-ہوئے-ملٹی-ایجنٹ.png)
آئیے اس رپورٹ کو مکمل تجربہ رجسٹری کے ساتھ پیش کریں اور اس بات کو یقینی بنائیں کہ تمام ورژنز میں اب بھی ان کے رنز، فیصلے اور تنقیدی جائزے موجود ہیں۔
display(Markdown("## Agent report"))
display(Markdown((WS / "report.md").read_text(encoding="utf-8")))
display(Markdown("## Experiment registry"))
reg = pd.read_csv(REGISTRY)
display(reg[["version","run","status","params","dev_sharpe","dev_sortino",
"dev_max_dd","dev_turnover","val_sharpe","val_max_dd","dev_cagr_20bps"]])
print("versions with runs:", sorted(reg["version"].unique()))
print("decisions recorded:", [d["version"] for d in _decisions()])
print("reviews on disk: ", sorted(p.stem for p in (WS/"reviews").glob("*.md")))
ایک آڈٹ اس بات کا جائزہ لینے کے لیے زیادہ کارآمد ہوتا ہے کہ کارکردگی کا ایک اور موازنہ کرنے کے بجائے مطالعہ کیسے کیا گیا۔
تین واضح کمزوریاں سامنے آتی ہیں۔ چونکہ V2 نے صرف ایک کنفیگریشن میں اہم رجیم تبدیلیوں کا تجربہ کیا، اس لیے ترقی میں بہتری کے لیے بہت کم مضبوطی کے ثبوت موجود تھے۔ V3 نے پھر حقیقی چیمپئن v1 کے مقابلے میں بہت سے اختلافات جمع کیے، جس سے رویے کی وجہ کو الگ کرنا مشکل ہو گیا۔
زیادہ اہم بات یہ ہے کہ آڈٹ نقاد کی اپنی غلطیوں سے پردہ اٹھاتا ہے۔ v3 جائزہ بائنری والیوم ریشو فلٹر کو اتار چڑھاؤ کی پیمائش کے ساتھ تبدیل کرنے کی سفارش کرتا ہے، حالانکہ v3 نے پہلے ہی اس فلٹر کو ہٹا دیا ہے اور الٹا اتار چڑھاؤ کے وزن کو نافذ کیا ہے۔ اگرچہ وضاحت معقول لگ رہی تھی، لیکن اس نے زیر غور حکمت عملی کو درست طریقے سے بیان نہیں کیا۔
شاید یہ سب سے طاقتور سبق ہے جو میں نے شکر گزاری سے سیکھا ہے۔ ایجنٹوں کو کردار کے لحاظ سے الگ کرنا مفید ہے، لیکن یہ اس بات کی ضمانت نہیں دیتا کہ وہ ایجنٹ اس نمونے کو سمجھتے ہیں جس کا وہ جائزہ لے رہے ہیں۔ حکمت عملی کے کوڈز، تجرباتی رجسٹریوں، جائزوں اور فیصلوں کو برقرار رکھنا ایک آزاد ریکارڈ فراہم کرتا ہے جس کے خلاف قیاس آرائیوں کی تصدیق کی جا سکتی ہے۔
نتیجہ
تعمیر آخر کار ختم ہو گئی ہے۔
ہم نے خام سے شروع کیا۔ EODHD مارکیٹ ڈیٹا ہم نے مقررہ ڈیٹا باؤنڈریز، ڈیٹرمنسٹک بیکٹیسٹرز، بینچ مارکس، تجرباتی ٹریکنگ، تین ایجنٹ کے کردار، تین حکمت عملی ورژن، فکسڈ چیمپئنز، ایک ہولڈ آؤٹ ٹیسٹ، اور جو کچھ بھی ہوا اس کا حتمی آڈٹ کے ساتھ ایک کنٹرول شدہ ملٹی ایجنٹ ریسرچ سسٹم کے ساتھ اختتام کیا۔
اور سفر اتنا صاف ستھرا نہیں تھا جتنا "AI نے اپنی حکمت عملی کو بہتر کرنا جاری رکھا۔" V2 ترقی کے دوران بہت بہتر نظر آیا لیکن توثیق میں ناکام رہا۔ V3 چھوٹ گیا v1۔ 0.0047 تیز ناقدین نے اس حکمت عملی کو بھی غلط سمجھا جس کا وہ جائزہ لے رہے تھے۔
عجیب بات یہ ہے کہ وہ گندا حصہ تھا جس نے تجربہ کرنے کے قابل بنا دیا۔ انہوں نے بالکل ظاہر کیا کہ ایجنٹوں پر کنٹرول کیوں ضروری ہے۔
مضبوط مضبوطی کی جانچ اور کلین سنگل چینج پراپرٹیز سے لے کر آزاد ناقدین اور پیرامیٹر کے استحکام کے ٹیسٹ تک بہتری کے لیے ابھی بھی کافی گنجائش ہے۔
لیکن بات سادہ ہے۔ ایجنٹ تحقیقی خیالات پیدا کرنے اور چیلنج کرنے کے لیے واقعی مفید ثابت ہو سکتے ہیں۔ انہیں ان شواہد پر قابو نہیں رکھنا چاہیے جو یہ طے کرتے ہیں کہ آیا خیال زندہ رہتا ہے۔