feat: add autonomous paper-trading and calibration pipeline

This commit is contained in:
ImBenji
2026-08-03 14:03:27 +01:00
parent 5a9a2e4c6d
commit c4028cc394
46 changed files with 2246 additions and 115 deletions
+7
View File
@@ -15,6 +15,13 @@ OPEN_ROUTER_API_KEY=
OPEN_ROUTER_LLM_MODEL=qwen/qwen3-235b-a22b-2507 OPEN_ROUTER_LLM_MODEL=qwen/qwen3-235b-a22b-2507
OPEN_ROUTER_EMBED_MODEL=qwen/qwen3-embedding-8b OPEN_ROUTER_EMBED_MODEL=qwen/qwen3-embedding-8b
# Paper execution is disabled unless AUTONOMY_EXECUTION_MODE=paper.
# These credentials are accepted only by the hard-coded Alpaca paper endpoint.
ALPACA_PAPER_KEY_ID=
ALPACA_PAPER_SECRET_KEY=
AUTONOMY_EXECUTION_MODE=shadow
AUTONOMY_DEFAULT_NOTIONAL=100
GDELT_BQ_PROJECT= GDELT_BQ_PROJECT=
GDELT_BQ_KEY_FILE=./gdelt-credentials.json GDELT_BQ_KEY_FILE=./gdelt-credentials.json
+4
View File
@@ -16,6 +16,10 @@ Node.js Fastify server that ingests news articles from RSS, GDELT, SEC EDGAR 8-K
The server listens on the host and port defined in `config.json`. The server listens on the host and port defined in `config.json`.
The bounded autonomy runtime and paper-trading contracts are documented in
[`docs/autonomy.md`](docs/autonomy.md). It is opt-in and does not start with
the API-only Compose service.
## How the data pipeline works ## How the data pipeline works
On startup the server: On startup the server:
+26
View File
@@ -214,6 +214,32 @@ def main():
print(f" 20-day: {a20:.1f}% (n={n20})") print(f" 20-day: {a20:.1f}% (n={n20})")
print() print()
# baselines — what would naive strategies have scored on the same set?
# this is the most important context for interpreting the model accuracy above
eval_df = df[df["correct_10d"].notna()].copy()
if len(eval_df) > 0:
# 1. always-positive baseline — predict every event as bullish
eval_df["always_pos_correct"] = eval_df["10d_return"].apply(lambda r: r > 0 if r is not None else None)
always_pos = eval_df["always_pos_correct"].mean() * 100
# 2. random baseline — flip a coin for each prediction (analytic expectation = 50%)
# we report the empirical positive rate of the underlying market over the test window
# since random would converge to that for a balanced dataset
market_up_rate = (eval_df["10d_return"] > 0).mean() * 100
# 3. always-negative baseline
always_neg = ((eval_df["10d_return"] < 0).sum() / len(eval_df)) * 100
print("BASELINES (10-day, same evaluation set)")
print(f" Always-positive: {always_pos:.1f}% (this is the bar to beat in a bull market)")
print(f" Always-negative: {always_neg:.1f}%")
print(f" Random (coin): 50.0% (analytic)")
print(f" Market up rate: {market_up_rate:.1f}% (% of events where stock rose 10d later)")
edge = a10 - always_pos
print(f" MODEL EDGE vs always-positive: {edge:+.1f} percentage points")
print()
# by magnitude # by magnitude
print("BY MAGNITUDE (10-day accuracy)") print("BY MAGNITUDE (10-day accuracy)")
for mag in sorted(df["magnitude"].dropna().unique()): for mag in sorted(df["magnitude"].dropna().unique()):
+2
View File
@@ -260,8 +260,10 @@ def main():
print() print()
sample = df[df["correct_10d"].notna()].head(30) sample = df[df["correct_10d"].notna()].head(30)
print("SAMPLE (30 most recent predictions)") print("SAMPLE (30 most recent predictions)")
print(f"{'Ticker':<12} {'Date':<12} {'Dir':<10} {'Mag':<8} {'5d%':>7} {'10d%':>7} {'20d%':>7} @10d") print(f"{'Ticker':<12} {'Date':<12} {'Dir':<10} {'Mag':<8} {'5d%':>7} {'10d%':>7} {'20d%':>7} @10d")
print("-" * 72) print("-" * 72)
for _, row in sample.iterrows(): for _, row in sample.iterrows():
r5s = f"{row['5d_return']:+.2f}" if row['5d_return'] is not None else "N/A" r5s = f"{row['5d_return']:+.2f}" if row['5d_return'] is not None else "N/A"
+88 -88
View File
@@ -92,8 +92,8 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
1240,HF,Hugging Face,2025-10-03,negative,medium,medium,OpenAI's valuation surge to $500 billion highlights its dominant market position and ability to attr,20.9692,20.8305,21.0089,20.9791,-0.6615,0.189,0.0472,True,False,False 1240,HF,Hugging Face,2025-10-03,negative,medium,medium,OpenAI's valuation surge to $500 billion highlights its dominant market position and ability to attr,20.9692,20.8305,21.0089,20.9791,-0.6615,0.189,0.0472,True,False,False
1304,META,Meta,2025-10-02,positive,medium,medium,"By using AI interaction data to improve recommendation relevance, Meta can increase user engagement ",725.8361,732.2853,710.8811,665.3572,0.8885,-2.0604,-8.3323,True,False,False 1304,META,Meta,2025-10-02,positive,medium,medium,"By using AI interaction data to improve recommendation relevance, Meta can increase user engagement ",725.8361,732.2853,710.8811,665.3572,0.8885,-2.0604,-8.3323,True,False,False
1305,META,Meta,2025-10-02,positive,medium,medium,Enhanced personalization using deeper AI signals strengthens Meta's competitive edge in social media,725.8361,732.2853,710.8811,665.3572,0.8885,-2.0604,-8.3323,True,False,False 1305,META,Meta,2025-10-02,positive,medium,medium,Enhanced personalization using deeper AI signals strengthens Meta's competitive edge in social media,725.8361,732.2853,710.8811,665.3572,0.8885,-2.0604,-8.3323,True,False,False
935,META,Meta,2025-10-01,positive,medium,short,AI-driven ad personalization strengthens Meta's competitive edge in digital advertising by improving,716.1423,716.6415,716.3519,750.4149,0.0697,0.0293,4.7857,True,True,True 935,META,Meta,2025-10-01,positive,medium,short,AI-driven ad personalization strengthens Meta's competitive edge in digital advertising by improving,716.1423,716.6415,716.3519,750.415,0.0697,0.0293,4.7857,True,True,True
937,META,Meta,2025-10-01,positive,medium,medium,"Enhanced ad targeting using AI interactions could increase advertiser ROI, driving higher ad spend s",716.1423,716.6415,716.3519,750.4149,0.0697,0.0293,4.7857,True,True,True 937,META,Meta,2025-10-01,positive,medium,medium,"Enhanced ad targeting using AI interactions could increase advertiser ROI, driving higher ad spend s",716.1423,716.6415,716.3519,750.415,0.0697,0.0293,4.7857,True,True,True
1302,SPOT,Spotify,2025-09-27,positive,medium,medium,"By adopting DDEX standards for AI transparency, Spotify positions itself as a responsible leader in ",728.47,680.5,685.29,645.78,-6.585,-5.9275,-11.3512,False,False,False 1302,SPOT,Spotify,2025-09-27,positive,medium,medium,"By adopting DDEX standards for AI transparency, Spotify positions itself as a responsible leader in ",728.47,680.5,685.29,645.78,-6.585,-5.9275,-11.3512,False,False,False
926,META,Meta,2025-09-18,positive,medium,medium,Launch of consumer-ready smartglasses with differentiated AI features may increase Meta's presence i,778.4218,747.6595,725.8361,710.8811,-3.9519,-6.7554,-8.6766,False,False,False 926,META,Meta,2025-09-18,positive,medium,medium,Launch of consumer-ready smartglasses with differentiated AI features may increase Meta's presence i,778.4218,747.6595,725.8361,710.8811,-3.9519,-6.7554,-8.6766,False,False,False
927,META,Meta,2025-09-18,positive,medium,short,Introduction of AI-integrated smartglasses with partnerships in fitness tech strengthens Meta's posi,778.4218,747.6595,725.8361,710.8811,-3.9519,-6.7554,-8.6766,False,False,False 927,META,Meta,2025-09-18,positive,medium,short,Introduction of AI-integrated smartglasses with partnerships in fitness tech strengthens Meta's posi,778.4218,747.6595,725.8361,710.8811,-3.9519,-6.7554,-8.6766,False,False,False
@@ -110,11 +110,11 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
637,AZN,AstraZeneca,2025-09-13,negative,medium,short,"Pausing a major investment may signal reduced confidence in the UK market, potentially affecting inv",154.4894,150.9859,145.9979,167.3157,-2.2678,-5.4965,8.3024,True,True,False 637,AZN,AstraZeneca,2025-09-13,negative,medium,short,"Pausing a major investment may signal reduced confidence in the UK market, potentially affecting inv",154.4894,150.9859,145.9979,167.3157,-2.2678,-5.4965,8.3024,True,True,False
638,AZN,AstraZeneca,2025-09-13,negative,medium,medium,Delaying expansion in a key life sciences hub like Cambridge could slow innovation and talent acquis,154.4894,150.9859,145.9979,167.3157,-2.2678,-5.4965,8.3024,True,True,False 638,AZN,AstraZeneca,2025-09-13,negative,medium,medium,Delaying expansion in a key life sciences hub like Cambridge could slow innovation and talent acquis,154.4894,150.9859,145.9979,167.3157,-2.2678,-5.4965,8.3024,True,True,False
628,ORCL,Oracle,2025-09-12,positive,medium,short,Bullish options activity suggests increased investor confidence in Oracle's near-term stock performa,289.8924,306.2434,281.2406,291.1707,5.6404,-2.9845,0.441,True,False,True 628,ORCL,Oracle,2025-09-12,positive,medium,short,Bullish options activity suggests increased investor confidence in Oracle's near-term stock performa,289.8924,306.2434,281.2406,291.1707,5.6404,-2.9845,0.441,True,False,True
988,AAPL,Apple,2025-09-12,positive,medium,short,"Strong buy-side investor sentiment, particularly from Indian retail investors, combined with histori",233.6247,245.033,254.974,244.8034,4.8832,9.1383,4.7849,True,True,True 988,AAPL,Apple,2025-09-12,positive,medium,short,"Strong buy-side investor sentiment, particularly from Indian retail investors, combined with histori",233.6247,245.033,254.974,244.8034,4.8831,9.1383,4.7849,True,True,True
627,ORCL,Oracle,2025-09-11,negative,medium,short,"Shares retreated 6-7% after a record high due to concerns about overreliance on OpenAI for growth, d",305.4496,294.2976,289.049,295.1463,-3.651,-5.3693,-3.3732,True,True,True 627,ORCL,Oracle,2025-09-11,negative,medium,short,"Shares retreated 6-7% after a record high due to concerns about overreliance on OpenAI for growth, d",305.4496,294.2976,289.049,295.1462,-3.651,-5.3693,-3.3732,True,True,True
1409,ORCL,Oracle,2025-09-11,positive,high,short,Oracle's stock surged 35.98% following strong cloud revenue forecasts and major AI-related contracts,305.4496,294.2976,289.049,295.1463,-3.651,-5.3693,-3.3732,False,False,False 1409,ORCL,Oracle,2025-09-11,positive,high,short,Oracle's stock surged 35.98% following strong cloud revenue forecasts and major AI-related contracts,305.4496,294.2976,289.049,295.1462,-3.651,-5.3693,-3.3732,False,False,False
1410,ORCL,Oracle,2025-09-11,positive,medium,medium,"With a cloud services backlog nearing $500 billion and major contracts in AI infrastructure, Oracle ",305.4496,294.2976,289.049,295.1463,-3.651,-5.3693,-3.3732,False,False,False 1410,ORCL,Oracle,2025-09-11,positive,medium,medium,"With a cloud services backlog nearing $500 billion and major contracts in AI infrastructure, Oracle ",305.4496,294.2976,289.049,295.1462,-3.651,-5.3693,-3.3732,False,False,False
1411,ORCL,Oracle,2025-09-11,positive,high,medium,Oracle's strategic positioning as a key AI cloud infrastructure provider through partnerships with l,305.4496,294.2976,289.049,295.1463,-3.651,-5.3693,-3.3732,False,False,False 1411,ORCL,Oracle,2025-09-11,positive,high,medium,Oracle's strategic positioning as a key AI cloud infrastructure provider through partnerships with l,305.4496,294.2976,289.049,295.1462,-3.651,-5.3693,-3.3732,False,False,False
611,INTC,Intel,2025-08-28,positive,medium,short,"Direct government investment signals confidence and improves public perception, consistent with prio",24.93,24.61,24.61,33.99,-1.2836,-1.2836,36.3418,False,False,True 611,INTC,Intel,2025-08-28,positive,medium,short,"Direct government investment signals confidence and improves public perception, consistent with prio",24.93,24.61,24.61,33.99,-1.2836,-1.2836,36.3418,False,False,True
612,INTC,Intel,2025-08-28,positive,medium,medium,"Government funding and stake may enhance capital investment in manufacturing, supporting domestic pr",24.93,24.61,24.61,33.99,-1.2836,-1.2836,36.3418,False,False,True 612,INTC,Intel,2025-08-28,positive,medium,medium,"Government funding and stake may enhance capital investment in manufacturing, supporting domestic pr",24.93,24.61,24.61,33.99,-1.2836,-1.2836,36.3418,False,False,True
608,NVDA,NVIDIA,2025-08-28,positive,high,short,"Extraordinary demand and full-speed ramp-up of Blackwell Ultra platform indicate strong adoption, re",180.1401,171.6315,177.1506,177.6705,-4.7233,-1.6595,-1.3709,False,False,False 608,NVDA,NVIDIA,2025-08-28,positive,high,short,"Extraordinary demand and full-speed ramp-up of Blackwell Ultra platform indicate strong adoption, re",180.1401,171.6315,177.1506,177.6705,-4.7233,-1.6595,-1.3709,False,False,False
@@ -135,24 +135,24 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
857,PLTR,Palantir,2025-08-10,positive,medium,medium,Recognition as 'the best story in all of software' and leadership in AI-driven government and enterp,182.68,177.17,158.74,153.11,-3.0162,-13.1049,-16.1868,False,False,False 857,PLTR,Palantir,2025-08-10,positive,medium,medium,Recognition as 'the best story in all of software' and leadership in AI-driven government and enterp,182.68,177.17,158.74,153.11,-3.0162,-13.1049,-16.1868,False,False,False
1208,INTC,Intel,2025-08-08,negative,medium,short,Trump's public demand for CEO resignation and allegations of conflict due to ties with Chinese firms,19.95,24.56,24.8,24.49,23.1078,24.3108,22.7569,False,False,False 1208,INTC,Intel,2025-08-08,negative,medium,short,Trump's public demand for CEO resignation and allegations of conflict due to ties with Chinese firms,19.95,24.56,24.8,24.49,23.1078,24.3108,22.7569,False,False,False
1209,INTC,Intel,2025-08-08,negative,low,short,"Leadership instability and political scrutiny may delay turnaround plans, giving competitors like Nv",19.95,24.56,24.8,24.49,23.1078,24.3108,22.7569,False,False,False 1209,INTC,Intel,2025-08-08,negative,low,short,"Leadership instability and political scrutiny may delay turnaround plans, giving competitors like Nv",19.95,24.56,24.8,24.49,23.1078,24.3108,22.7569,False,False,False
1210,META,Meta,2025-08-08,positive,high,medium,"The $29 billion financing enables accelerated AI infrastructure development, strengthening Meta's ca",767.4975,783.3901,753.0215,750.687,2.0707,-1.8861,-2.1903,True,False,False 1210,META,Meta,2025-08-08,positive,high,medium,"The $29 billion financing enables accelerated AI infrastructure development, strengthening Meta's ca",767.4976,783.3902,753.0215,750.6871,2.0707,-1.8861,-2.1903,True,False,False
1289,TSM,TSMC,2025-08-08,negative,medium,short,"The leak of trade secrets, even if not directly TSMCs fault, could undermine confidence in its IP p",239.7449,236.8203,230.9811,241.3113,-1.2199,-3.6555,0.6534,True,True,False 1289,TSM,TSMC,2025-08-08,negative,medium,short,"The leak of trade secrets, even if not directly TSMCs fault, could undermine confidence in its IP p",239.7449,236.8203,230.9811,241.3112,-1.2199,-3.6555,0.6533,True,True,False
1290,TSM,TSMC,2025-08-08,negative,low,short,"While the incident does not directly implicate TSMC in wrongdoing, associated supply chain instabili",239.7449,236.8203,230.9811,241.3113,-1.2199,-3.6555,0.6534,True,True,False 1290,TSM,TSMC,2025-08-08,negative,low,short,"While the incident does not directly implicate TSMC in wrongdoing, associated supply chain instabili",239.7449,236.8203,230.9811,241.3112,-1.2199,-3.6555,0.6533,True,True,False
1218,META,Meta,2025-08-08,positive,high,long,"The $29 billion financing enables large-scale AI data center development, strengthening Meta's infra",767.4975,783.3901,753.0215,750.687,2.0707,-1.8861,-2.1903,True,False,False 1218,META,Meta,2025-08-08,positive,high,long,"The $29 billion financing enables large-scale AI data center development, strengthening Meta's infra",767.4976,783.3902,753.0215,750.6871,2.0707,-1.8861,-2.1903,True,False,False
1511,SPOT,Spotify,2025-08-07,positive,medium,short,"The introduction of AI DJ, which provides personalized, context-rich music recommendations using gen",686.74,698.5,689.47,703.85,1.7124,0.3975,2.4915,True,True,True 1511,SPOT,Spotify,2025-08-07,positive,medium,short,"The introduction of AI DJ, which provides personalized, context-rich music recommendations using gen",686.74,698.5,689.47,703.85,1.7124,0.3975,2.4915,True,True,True
1513,SPOT,Spotify,2025-08-07,positive,medium,medium,Investment in advanced AI features like AI DJ strengthens Spotifys differentiation from competitors,686.74,698.5,689.47,703.85,1.7124,0.3975,2.4915,True,True,True 1513,SPOT,Spotify,2025-08-07,positive,medium,medium,Investment in advanced AI features like AI DJ strengthens Spotifys differentiation from competitors,686.74,698.5,689.47,703.85,1.7124,0.3975,2.4915,True,True,True
851,PLTR,Palantir,2025-08-07,negative,medium,medium,"CEO's remarks may deepen skepticism among educated public and academia, contributing to declining pu",182.2,181.02,156.18,156.14,-0.6476,-14.281,-14.303,True,True,True 851,PLTR,Palantir,2025-08-07,negative,medium,medium,"CEO's remarks may deepen skepticism among educated public and academia, contributing to declining pu",182.2,181.02,156.18,156.14,-0.6476,-14.281,-14.303,True,True,True
852,PLTR,Palantir,2025-08-07,positive,medium,long,Positioning Palantir as a meritocratic alternative to elite education could strengthen employer bran,182.2,181.02,156.18,156.14,-0.6476,-14.281,-14.303,False,False,False 852,PLTR,Palantir,2025-08-07,positive,medium,long,Positioning Palantir as a meritocratic alternative to elite education could strengthen employer bran,182.2,181.02,156.18,156.14,-0.6476,-14.281,-14.303,False,False,False
1288,TSM,TSMC,2025-08-07,negative,medium,short,Increased geopolitical risk and costly overseas expansion could weigh on investor sentiment in the n,240.5281,238.922,225.3699,233.182,-0.6677,-6.302,-3.0541,True,True,True 1288,TSM,TSMC,2025-08-07,negative,medium,short,Increased geopolitical risk and costly overseas expansion could weigh on investor sentiment in the n,240.5281,238.922,225.3699,233.182,-0.6677,-6.302,-3.0542,True,True,True
1509,TSM,TSMC,2025-08-07,positive,medium,short,Tariff exemption strengthens TSMC's competitive position relative to non-U.S.-based semiconductor ma,240.5281,238.922,225.3699,233.182,-0.6677,-6.302,-3.0541,False,False,False 1509,TSM,TSMC,2025-08-07,positive,medium,short,Tariff exemption strengthens TSMC's competitive position relative to non-U.S.-based semiconductor ma,240.5281,238.922,225.3699,233.182,-0.6677,-6.302,-3.0542,False,False,False
1510,TSM,TSMC,2025-08-07,positive,low,short,"Exemption from high tariffs provides operational certainty and reduces near-term geopolitical risk, ",240.5281,238.922,225.3699,233.182,-0.6677,-6.302,-3.0541,False,False,False 1510,TSM,TSMC,2025-08-07,positive,low,short,"Exemption from high tariffs provides operational certainty and reduces near-term geopolitical risk, ",240.5281,238.922,225.3699,233.182,-0.6677,-6.302,-3.0542,False,False,False
873,PLTR,Palantir,2025-08-05,positive,high,short,"Palantir's strong earnings, revenue growth of nearly 50%, net income up 144%, raised guidance, and i",173.27,186.97,157.75,157.09,7.9067,-8.9571,-9.338,True,False,False 873,PLTR,Palantir,2025-08-05,positive,high,short,"Palantir's strong earnings, revenue growth of nearly 50%, net income up 144%, raised guidance, and i",173.27,186.97,157.75,157.09,7.9067,-8.9571,-9.338,True,False,False
874,PLTR,Palantir,2025-08-05,positive,medium,medium,Investor confidence in Palantir's AI-powered efficiency and scalability may accelerate adoption in g,173.27,186.97,157.75,157.09,7.9067,-8.9571,-9.338,True,False,False 874,PLTR,Palantir,2025-08-05,positive,medium,medium,Investor confidence in Palantir's AI-powered efficiency and scalability may accelerate adoption in g,173.27,186.97,157.75,157.09,7.9067,-8.9571,-9.338,True,False,False
875,PLTR,Palantir,2025-08-05,positive,medium,short,Palantir's demonstrated ability to grow revenue while reducing workforce through AI gives it a perce,173.27,186.97,157.75,157.09,7.9067,-8.9571,-9.338,True,False,False 875,PLTR,Palantir,2025-08-05,positive,medium,short,Palantir's demonstrated ability to grow revenue while reducing workforce through AI gives it a perce,173.27,186.97,157.75,157.09,7.9067,-8.9571,-9.338,True,False,False
1463,META,Meta,2025-08-01,positive,high,short,Meta shares jump after strong third-quarter sales forecast and better-than-expected financial perfor,748.2527,767.4975,783.3901,736.9692,2.572,4.6959,-1.508,True,True,False 1463,META,Meta,2025-08-01,positive,high,short,Meta shares jump after strong third-quarter sales forecast and better-than-expected financial perfor,748.2527,767.4976,783.3902,736.9692,2.572,4.6959,-1.508,True,True,False
1307,MSFT,Microsoft,2025-08-01,positive,high,short,"Microsoft's stock rose 3.9% on July 31, 2025, following record valuation and strong quarterly result",521.0829,519.0249,517.1657,504.5917,-0.395,-0.7517,-3.1648,False,False,False 1307,MSFT,Microsoft,2025-08-01,positive,high,short,"Microsoft's stock rose 3.9% on July 31, 2025, following record valuation and strong quarterly result",521.0829,519.025,517.1657,504.5917,-0.3949,-0.7517,-3.1648,False,False,False
1308,MSFT,Microsoft,2025-08-01,positive,medium,medium,Azure's 39% growth and increasing AI-driven cloud revenue suggest Microsoft is gaining cloud market ,521.0829,519.0249,517.1657,504.5917,-0.395,-0.7517,-3.1648,False,False,False 1308,MSFT,Microsoft,2025-08-01,positive,medium,medium,Azure's 39% growth and increasing AI-driven cloud revenue suggest Microsoft is gaining cloud market ,521.0829,519.025,517.1657,504.5917,-0.3949,-0.7517,-3.1648,False,False,False
1309,MSFT,Microsoft,2025-08-01,positive,high,long,"Surpassing four trillion dollars in market cap, second only to Nvidia, reinforces Microsoft's elite ",521.0829,519.0249,517.1657,504.5917,-0.395,-0.7517,-3.1648,False,False,False 1309,MSFT,Microsoft,2025-08-01,positive,high,long,"Surpassing four trillion dollars in market cap, second only to Nvidia, reinforces Microsoft's elite ",521.0829,519.025,517.1657,504.5917,-0.3949,-0.7517,-3.1648,False,False,False
1400,ARM,Arm Holdings,2025-07-31,negative,high,short,Arm's shares dropped nearly 13% following disappointing guidance and a strategic shift that risks cu,141.375,135.57,140.55,142.55,-4.1061,-0.5836,0.8311,True,True,False 1400,ARM,Arm Holdings,2025-07-31,negative,high,short,Arm's shares dropped nearly 13% following disappointing guidance and a strategic shift that risks cu,141.375,135.57,140.55,142.55,-4.1061,-0.5836,0.8311,True,True,False
1401,ARM,Arm Holdings,2025-07-31,negative,medium,medium,Developing full chip solutions may lead to conflicts of interest with key customers like Nvidia and ,141.375,135.57,140.55,142.55,-4.1061,-0.5836,0.8311,True,True,False 1401,ARM,Arm Holdings,2025-07-31,negative,medium,medium,Developing full chip solutions may lead to conflicts of interest with key customers like Nvidia and ,141.375,135.57,140.55,142.55,-4.1061,-0.5836,0.8311,True,True,False
1402,ARM,Arm Holdings,2025-07-31,negative,low,long,Long-term market share could be affected if customers reduce reliance on Arm's IP due to competitive,141.375,135.57,140.55,142.55,-4.1061,-0.5836,0.8311,True,True,False 1402,ARM,Arm Holdings,2025-07-31,negative,low,long,Long-term market share could be affected if customers reduce reliance on Arm's IP due to competitive,141.375,135.57,140.55,142.55,-4.1061,-0.5836,0.8311,True,True,False
@@ -163,10 +163,10 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
1222,META,Meta,2025-07-31,positive,medium,medium,"Aggressive investment in AI talent and infrastructure positions Meta to better compete with OpenAI, ",771.6278,760.045,780.2974,749.3502,-1.5011,1.1235,-2.8871,False,True,False 1222,META,Meta,2025-07-31,positive,medium,medium,"Aggressive investment in AI talent and infrastructure positions Meta to better compete with OpenAI, ",771.6278,760.045,780.2974,749.3502,-1.5011,1.1235,-2.8871,False,True,False
1223,META,Meta,2025-07-31,positive,medium,medium,Strong ad revenue growth and AI-driven product enhancements may increase user engagement and ad mark,771.6278,760.045,780.2974,749.3502,-1.5011,1.1235,-2.8871,False,True,False 1223,META,Meta,2025-07-31,positive,medium,medium,Strong ad revenue growth and AI-driven product enhancements may increase user engagement and ad mark,771.6278,760.045,780.2974,749.3502,-1.5011,1.1235,-2.8871,False,True,False
1279,UBS,UBS,2025-07-30,negative,medium,medium,Proposed capital requirements could impair competitiveness if implemented; CEO warns 42 billion doll,36.9761,37.0834,38.6529,39.15,0.29,4.5347,5.8793,False,False,False 1279,UBS,UBS,2025-07-30,negative,medium,medium,Proposed capital requirements could impair competitiveness if implemented; CEO warns 42 billion doll,36.9761,37.0834,38.6529,39.15,0.29,4.5347,5.8793,False,False,False
893,META,Meta,2025-07-26,positive,high,medium,Hiring a foundational OpenAI researcher and formalizing leadership under a strong AI executive team ,715.9486,748.2527,767.4975,753.0215,4.5121,7.2001,5.1781,True,True,True 893,META,Meta,2025-07-26,positive,high,medium,Hiring a foundational OpenAI researcher and formalizing leadership under a strong AI executive team ,715.9486,748.2527,767.4976,753.0215,4.5121,7.2001,5.1781,True,True,True
894,META,Meta,2025-07-26,positive,medium,long,"Strengthening AI talent base supports future AI product development, potentially increasing market s",715.9486,748.2527,767.4975,753.0215,4.5121,7.2001,5.1781,True,True,True 894,META,Meta,2025-07-26,positive,medium,long,"Strengthening AI talent base supports future AI product development, potentially increasing market s",715.9486,748.2527,767.4976,753.0215,4.5121,7.2001,5.1781,True,True,True
1558,VZ,Verizon,2025-07-24,negative,low,short,"The $175 million penalty represents a one-time cost that may slightly pressure earnings, but given V",41.0128,40.7082,40.8891,42.8693,-0.7428,-0.3018,4.5264,True,True,False 1558,VZ,Verizon,2025-07-24,negative,low,short,"The $175 million penalty represents a one-time cost that may slightly pressure earnings, but given V",41.0128,40.7082,40.8891,42.8693,-0.7428,-0.3018,4.5265,True,True,False
1559,VZ,Verizon,2025-07-24,negative,medium,short,Increased legal risk from patent litigation could affect investor sentiment and raise concerns about,41.0128,40.7082,40.8891,42.8693,-0.7428,-0.3018,4.5264,True,True,False 1559,VZ,Verizon,2025-07-24,negative,medium,short,Increased legal risk from patent litigation could affect investor sentiment and raise concerns about,41.0128,40.7082,40.8891,42.8693,-0.7428,-0.3018,4.5265,True,True,False
799,META,Meta,2025-07-17,negative,medium,short,Public perception may be negatively influenced by the association of top executives with privacy vio,699.7665,713.1252,771.6278,780.2974,1.909,10.2693,11.5083,False,False,False 799,META,Meta,2025-07-17,negative,medium,short,Public perception may be negatively influenced by the association of top executives with privacy vio,699.7665,713.1252,771.6278,780.2974,1.909,10.2693,11.5083,False,False,False
1109,NVDA,NVIDIA,2025-07-10,positive,high,short,Nvidia's stock has surged 69% since early April and analysts project an additional 17% rise to $190 ,164.0727,172.9713,173.7111,180.74,5.4235,5.8745,10.1584,True,True,True 1109,NVDA,NVIDIA,2025-07-10,positive,high,short,Nvidia's stock has surged 69% since early April and analysts project an additional 17% rise to $190 ,164.0727,172.9713,173.7111,180.74,5.4235,5.8745,10.1584,True,True,True
1110,NVDA,NVIDIA,2025-07-10,positive,medium,medium,Ongoing demand from big tech and AI innovators for high-performance computing chips reinforces Nvidi,164.0727,172.9713,173.7111,180.74,5.4235,5.8745,10.1584,True,True,True 1110,NVDA,NVIDIA,2025-07-10,positive,medium,medium,Ongoing demand from big tech and AI innovators for high-performance computing chips reinforces Nvidi,164.0727,172.9713,173.7111,180.74,5.4235,5.8745,10.1584,True,True,True
@@ -182,8 +182,8 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
1084,MU,Micron,2025-07-03,positive,low,long,Sustained revenue growth from rising HBM demand and expanded production capacity could support long-,121.998,122.9316,113.0959,108.9819,0.7653,-7.2969,-10.6691,True,False,False 1084,MU,Micron,2025-07-03,positive,low,long,Sustained revenue growth from rising HBM demand and expanded production capacity could support long-,121.998,122.9316,113.0959,108.9819,0.7653,-7.2969,-10.6691,True,False,False
1506,BP,BP,2025-07-02,positive,medium,short,"Takeover speculation and activist involvement typically create short-term stock price momentum, even",30.038,30.0093,30.633,30.9497,-0.0958,1.9808,3.0351,False,True,True 1506,BP,BP,2025-07-02,positive,medium,short,"Takeover speculation and activist involvement typically create short-term stock price momentum, even",30.038,30.0093,30.633,30.9497,-0.0958,1.9808,3.0351,False,True,True
1507,BP,BP,2025-07-02,negative,medium,medium,Persistent speculation that BP could be acquired may weaken its strategic autonomy and bargaining po,30.038,30.0093,30.633,30.9497,-0.0958,1.9808,3.0351,True,False,False 1507,BP,BP,2025-07-02,negative,medium,medium,Persistent speculation that BP could be acquired may weaken its strategic autonomy and bargaining po,30.038,30.0093,30.633,30.9497,-0.0958,1.9808,3.0351,True,False,False
902,META,Meta,2025-06-13,positive,high,medium,Acquiring key AI talent and investing heavily in AI infrastructure through Scale AI strengthens Meta,680.7462,680.7512,731.9111,715.8289,0.0007,7.516,5.1536,True,True,True 902,META,Meta,2025-06-13,positive,high,medium,Acquiring key AI talent and investing heavily in AI infrastructure through Scale AI strengthens Meta,680.7463,680.7512,731.9111,715.8289,0.0007,7.516,5.1535,True,True,True
903,META,Meta,2025-06-13,positive,medium,short,Major strategic investment in AI and high-profile talent acquisition may be viewed favorably by inve,680.7462,680.7512,731.9111,715.8289,0.0007,7.516,5.1536,True,True,True 903,META,Meta,2025-06-13,positive,medium,short,Major strategic investment in AI and high-profile talent acquisition may be viewed favorably by inve,680.7463,680.7512,731.9111,715.8289,0.0007,7.516,5.1535,True,True,True
1476,NVS,Novartis,2025-06-13,positive,medium,short,"Novo Nordisk's leadership turmoil and stock decline may weaken its market positioning, creating oppo",115.9217,112.3504,116.4652,117.4453,-3.0808,0.4688,1.3144,False,True,True 1476,NVS,Novartis,2025-06-13,positive,medium,short,"Novo Nordisk's leadership turmoil and stock decline may weaken its market positioning, creating oppo",115.9217,112.3504,116.4652,117.4453,-3.0808,0.4688,1.3144,False,True,True
1477,NVS,Novartis,2025-06-13,positive,low,short,"While Novartis is not directly affected by Novo Nordisk's CEO dismissal, reduced competitive pressur",115.9217,112.3504,116.4652,117.4453,-3.0808,0.4688,1.3144,False,True,True 1477,NVS,Novartis,2025-06-13,positive,low,short,"While Novartis is not directly affected by Novo Nordisk's CEO dismissal, reduced competitive pressur",115.9217,112.3504,116.4652,117.4453,-3.0808,0.4688,1.3144,False,True,True
1085,AMD,AMD,2025-06-13,positive,high,medium,AMDs launch of the Helios server and partnership with OpenAI strengthen its position in the AI chip,116.16,128.24,143.81,146.42,10.3995,23.8034,26.0503,True,True,True 1085,AMD,AMD,2025-06-13,positive,high,medium,AMDs launch of the Helios server and partnership with OpenAI strengthen its position in the AI chip,116.16,128.24,143.81,146.42,10.3995,23.8034,26.0503,True,True,True
@@ -195,32 +195,32 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
1397,UBS,UBS,2025-06-08,positive,high,medium,"The new draft law significantly increases regulatory obligations, including capitalization of foreig",32.1019,31.1758,29.655,33.3107,-2.8849,-7.6222,3.7656,False,False,True 1397,UBS,UBS,2025-06-08,positive,high,medium,"The new draft law significantly increases regulatory obligations, including capitalization of foreig",32.1019,31.1758,29.655,33.3107,-2.8849,-7.6222,3.7656,False,False,True
1556,UBS,UBS,2025-06-06,negative,medium,short,"Stricter capital requirements may constrain UBS's ability to deploy capital efficiently, increasing ",32.7745,31.1758,29.655,33.3107,-4.878,-9.5181,1.6359,True,True,False 1556,UBS,UBS,2025-06-06,negative,medium,short,"Stricter capital requirements may constrain UBS's ability to deploy capital efficiently, increasing ",32.7745,31.1758,29.655,33.3107,-4.878,-9.5181,1.6359,True,True,False
1557,UBS,UBS,2025-06-06,negative,low,short,"Announcement of higher capital requirements could lead to margin compression concerns, negatively im",32.7745,31.1758,29.655,33.3107,-4.878,-9.5181,1.6359,True,True,False 1557,UBS,UBS,2025-06-06,negative,low,short,"Announcement of higher capital requirements could lead to margin compression concerns, negatively im",32.7745,31.1758,29.655,33.3107,-4.878,-9.5181,1.6359,True,True,False
1393,AVGO,Broadcom,2025-06-06,negative,medium,short,"Broadcom's stock fell 2% in extended trading after the forecast missed the loftiest expectations, de",244.9453,246.7011,248.5644,272.6165,0.7168,1.4775,11.2969,False,False,False 1393,AVGO,Broadcom,2025-06-06,negative,medium,short,"Broadcom's stock fell 2% in extended trading after the forecast missed the loftiest expectations, de",244.9453,246.7011,248.5644,272.6164,0.7168,1.4775,11.2969,False,False,False
913,META,Meta,2025-06-04,positive,medium,long,"Securing long-term, stable nuclear power enhances Meta's ability to scale AI infrastructure, improvi",685.8104,691.9812,694.1398,711.8981,0.8998,1.2145,3.8039,True,True,True 913,META,Meta,2025-06-04,positive,medium,long,"Securing long-term, stable nuclear power enhances Meta's ability to scale AI infrastructure, improvi",685.8105,691.9812,694.1398,711.8981,0.8998,1.2145,3.8039,True,True,True
914,META,Meta,2025-06-04,positive,high,long,The 20-year power purchase agreement with Constellation Energy directly supports Meta's growing AI w,685.8104,691.9812,694.1398,711.8981,0.8998,1.2145,3.8039,True,True,True 914,META,Meta,2025-06-04,positive,high,long,The 20-year power purchase agreement with Constellation Energy directly supports Meta's growing AI w,685.8105,691.9812,694.1398,711.8981,0.8998,1.2145,3.8039,True,True,True
1106,AVGO,Broadcom,2025-06-02,negative,medium,short,"Dissatisfied partners may drive customers toward competing private cloud solutions, increasing migra",246.711,242.3166,250.0738,274.0781,-1.7812,1.363,11.0927,True,False,False 1106,AVGO,Broadcom,2025-06-02,negative,medium,short,"Dissatisfied partners may drive customers toward competing private cloud solutions, increasing migra",246.711,242.3166,250.0738,274.0781,-1.7812,1.363,11.0928,True,False,False
1107,AVGO,Broadcom,2025-06-02,negative,medium,medium,"Reducing the number of channel partners, especially long-standing ones, could erode VMware's market ",246.711,242.3166,250.0738,274.0781,-1.7812,1.363,11.0927,True,False,False 1107,AVGO,Broadcom,2025-06-02,negative,medium,medium,"Reducing the number of channel partners, especially long-standing ones, could erode VMware's market ",246.711,242.3166,250.0738,274.0781,-1.7812,1.363,11.0928,True,False,False
1196,NVDA,NVIDIA,2025-05-29,positive,high,short,Nvidia's revenue surpassing $44bn despite China sales restrictions indicates robust global demand fo,139.1572,139.957,144.9759,154.9942,0.5748,4.1814,11.3807,True,True,True 1196,NVDA,NVIDIA,2025-05-29,positive,high,short,Nvidia's revenue surpassing $44bn despite China sales restrictions indicates robust global demand fo,139.1572,139.957,144.9759,154.9942,0.5748,4.1814,11.3807,True,True,True
1197,NVDA,NVIDIA,2025-05-29,positive,medium,medium,Ability to achieve record revenue under geopolitical constraints reinforces Nvidia's competitive adv,139.1572,139.957,144.9759,154.9942,0.5748,4.1814,11.3807,True,True,True 1197,NVDA,NVIDIA,2025-05-29,positive,medium,medium,Ability to achieve record revenue under geopolitical constraints reinforces Nvidia's competitive adv,139.1572,139.957,144.9759,154.9942,0.5748,4.1814,11.3807,True,True,True
1198,NVDA,NVIDIA,2025-05-29,positive,medium,short,Strong revenue performance despite headwinds aligns with analyst sentiment supporting stock valuatio,139.1572,139.957,144.9759,154.9942,0.5748,4.1814,11.3807,True,True,True 1198,NVDA,NVIDIA,2025-05-29,positive,medium,short,Strong revenue performance despite headwinds aligns with analyst sentiment supporting stock valuatio,139.1572,139.957,144.9759,154.9942,0.5748,4.1814,11.3807,True,True,True
1203,LHX,L3Harris Technologies,2025-05-29,positive,medium,short,Technical breakout above $232 resistance and inclusion in a model portfolio suggest near-term upward,239.3204,239.1635,247.3939,243.8468,-0.0655,3.3735,1.8914,False,True,True 1203,LHX,L3Harris Technologies,2025-05-29,positive,medium,short,Technical breakout above $232 resistance and inclusion in a model portfolio suggest near-term upward,239.3204,239.1635,247.3939,243.8468,-0.0655,3.3735,1.8914,False,True,True
1503,META,Meta,2025-05-29,positive,medium,medium,"One billion monthly users of Meta AI strengthens Meta's position in the generative AI race, though i",643.0439,682.4907,691.2036,724.3888,6.1344,7.4893,12.65,True,True,True 1503,META,Meta,2025-05-29,positive,medium,medium,"One billion monthly users of Meta AI strengthens Meta's position in the generative AI race, though i",643.0439,682.4907,691.2036,724.3887,6.1344,7.4893,12.65,True,True,True
1504,META,Meta,2025-05-29,positive,low,short,"High user engagement with Meta AI may lead to incremental gains in AI assistant market share, but Go",643.0439,682.4907,691.2036,724.3888,6.1344,7.4893,12.65,True,True,True 1504,META,Meta,2025-05-29,positive,low,short,"High user engagement with Meta AI may lead to incremental gains in AI assistant market share, but Go",643.0439,682.4907,691.2036,724.3887,6.1344,7.4893,12.65,True,True,True
1271,NVS,Novartis,2025-05-29,positive,medium,short,"As a competitor in the metabolic and pharmaceutical space, Novartis may benefit from Novo Nordisk's ",109.2546,114.3108,117.2027,116.766,4.6278,7.2748,6.8751,True,True,True 1271,NVS,Novartis,2025-05-29,positive,medium,short,"As a competitor in the metabolic and pharmaceutical space, Novartis may benefit from Novo Nordisk's ",109.2546,114.3108,117.2027,116.766,4.6278,7.2748,6.8751,True,True,True
1272,NVS,Novartis,2025-05-29,positive,low,short,"While not directly mentioned, the known positive impact of production investment and divestment on N",109.2546,114.3108,117.2027,116.766,4.6278,7.2748,6.8751,True,True,True 1272,NVS,Novartis,2025-05-29,positive,low,short,"While not directly mentioned, the known positive impact of production investment and divestment on N",109.2546,114.3108,117.2027,116.766,4.6278,7.2748,6.8751,True,True,True
1273,META,Meta,2025-05-29,positive,medium,medium,"Increased AI integration in advertising and user content, combined with high advertiser adoption, po",643.0439,682.4907,691.2036,724.3888,6.1344,7.4893,12.65,True,True,True 1273,META,Meta,2025-05-29,positive,medium,medium,"Increased AI integration in advertising and user content, combined with high advertiser adoption, po",643.0439,682.4907,691.2036,724.3887,6.1344,7.4893,12.65,True,True,True
1274,META,Meta,2025-05-29,positive,high,medium,"Meta's massive AI investment, global user base, and early lead in AI-powered advertising tools stren",643.0439,682.4907,691.2036,724.3888,6.1344,7.4893,12.65,True,True,True 1274,META,Meta,2025-05-29,positive,high,medium,"Meta's massive AI investment, global user base, and early lead in AI-powered advertising tools stren",643.0439,682.4907,691.2036,724.3887,6.1344,7.4893,12.65,True,True,True
1199,META,Meta,2025-05-25,positive,medium,medium,"Expanding AI training with user data may improve Meta AI and Llama models, enhancing competitiveness",640.3224,645.4763,695.5401,680.7512,0.8049,8.6234,6.3138,True,True,True 1199,META,Meta,2025-05-25,positive,medium,medium,"Expanding AI training with user data may improve Meta AI and Llama models, enhancing competitiveness",640.3223,645.4763,695.5401,680.7512,0.8049,8.6234,6.3138,True,True,True
1200,META,Meta,2025-05-25,negative,high,short,"Noyb's challenge and opt-out model may lead to GDPR enforcement actions, increasing regulatory and l",640.3224,645.4763,695.5401,680.7512,0.8049,8.6234,6.3138,False,False,False 1200,META,Meta,2025-05-25,negative,high,short,"Noyb's challenge and opt-out model may lead to GDPR enforcement actions, increasing regulatory and l",640.3223,645.4763,695.5401,680.7512,0.8049,8.6234,6.3138,False,False,False
1201,META,Meta,2025-05-25,negative,medium,short,"Public backlash over data usage for AI without explicit consent could harm user trust, especially in",640.3224,645.4763,695.5401,680.7512,0.8049,8.6234,6.3138,False,False,False 1201,META,Meta,2025-05-25,negative,medium,short,"Public backlash over data usage for AI without explicit consent could harm user trust, especially in",640.3223,645.4763,695.5401,680.7512,0.8049,8.6234,6.3138,False,False,False
1202,META,Meta,2025-05-25,negative,low,short,Short-term investor concerns may arise from increased regulatory scrutiny and reputational risk tied,640.3224,645.4763,695.5401,680.7512,0.8049,8.6234,6.3138,False,False,False 1202,META,Meta,2025-05-25,negative,low,short,Short-term investor concerns may arise from increased regulatory scrutiny and reputational risk tied,640.3223,645.4763,695.5401,680.7512,0.8049,8.6234,6.3138,False,False,False
1259,TSLA,Tesla,2025-05-23,negative,medium,short,Being outsold in Europe suggests Tesla is losing market share to a strong competitor in a key region,339.34,346.46,295.14,322.16,2.0982,-13.0253,-5.0628,False,True,True 1259,TSLA,Tesla,2025-05-23,negative,medium,short,Being outsold in Europe suggests Tesla is losing market share to a strong competitor in a key region,339.34,346.46,295.14,322.16,2.0982,-13.0253,-5.0628,False,True,True
1260,TSLA,Tesla,2025-05-23,negative,medium,short,A competitor labeled as a 'Tesla-killer' gaining sales leadership in Europe undermines Tesla's compe,339.34,346.46,295.14,322.16,2.0982,-13.0253,-5.0628,False,True,True 1260,TSLA,Tesla,2025-05-23,negative,medium,short,A competitor labeled as a 'Tesla-killer' gaining sales leadership in Europe undermines Tesla's compe,339.34,346.46,295.14,322.16,2.0982,-13.0253,-5.0628,False,True,True
1261,TSLA,Tesla,2025-05-23,negative,low,short,"Missing sales expectations in a major market can negatively impact investor sentiment, especially am",339.34,346.46,295.14,322.16,2.0982,-13.0253,-5.0628,False,True,True 1261,TSLA,Tesla,2025-05-23,negative,low,short,"Missing sales expectations in a major market can negatively impact investor sentiment, especially am",339.34,346.46,295.14,322.16,2.0982,-13.0253,-5.0628,False,True,True
1464,SHOP,Shopify,2025-05-23,positive,medium,short,"The launch of the AI Store Builder enhances Shopify's product offering, differentiating its platform",101.51,107.22,111.41,106.4,5.6251,9.7527,4.8173,True,True,True 1464,SHOP,Shopify,2025-05-23,positive,medium,short,"The launch of the AI Store Builder enhances Shopify's product offering, differentiating its platform",101.51,107.22,111.41,106.4,5.6251,9.7527,4.8173,True,True,True
1189,WBD,Warner Bros Discovery,2025-05-14,positive,medium,medium,"By refocusing on HBO's premium brand and distinct adult-oriented content, WBD aims to carve out a cl",9.21,8.95,10.02,10.51,-2.823,8.7948,14.1151,False,True,True 1189,WBD,Warner Bros Discovery,2025-05-14,positive,medium,medium,"By refocusing on HBO's premium brand and distinct adult-oriented content, WBD aims to carve out a cl",9.21,8.95,10.02,10.51,-2.823,8.7948,14.1151,False,True,True
1282,META,Meta,2025-05-08,negative,medium,short,Public exposure of widespread scam activity leveraging Meta's platforms may weaken user trust and in,596.1501,641.8775,634.5903,682.4907,7.6704,6.4481,14.483,False,False,False 1282,META,Meta,2025-05-08,negative,medium,short,Public exposure of widespread scam activity leveraging Meta's platforms may weaken user trust and in,596.1502,641.8775,634.5902,682.4907,7.6704,6.448,14.483,False,False,False
1283,META,Meta,2025-05-08,negative,low,short,"While the takedown demonstrates proactive moderation, the underlying prevalence of sophisticated sca",596.1501,641.8775,634.5903,682.4907,7.6704,6.4481,14.483,False,False,False 1283,META,Meta,2025-05-08,negative,low,short,"While the takedown demonstrates proactive moderation, the underlying prevalence of sophisticated sca",596.1502,641.8775,634.5902,682.4907,7.6704,6.448,14.483,False,False,False
1473,V,Visa,2025-05-08,positive,high,long,"By enabling AI agents to use its payment network, Visa positions itself as a foundational player in ",348.6606,360.2059,355.9009,364.6501,3.3113,2.0766,4.586,True,True,True 1473,V,Visa,2025-05-08,positive,high,long,"By enabling AI agents to use its payment network, Visa positions itself as a foundational player in ",348.6606,360.2059,355.9009,364.6501,3.3113,2.0766,4.586,True,True,True
1474,V,Visa,2025-05-08,positive,medium,medium,Opening its network to AI developers and expanding in key markets like Europe by 2025 could increase,348.6606,360.2059,355.9009,364.6501,3.3113,2.0766,4.586,True,True,True 1474,V,Visa,2025-05-08,positive,medium,medium,Opening its network to AI developers and expanding in key markets like Europe by 2025 could increase,348.6606,360.2059,355.9009,364.6501,3.3113,2.0766,4.586,True,True,True
1475,V,Visa,2025-05-08,positive,low,short,"The announcement of a forward-looking strategic initiative may generate investor interest, though im",348.6606,360.2059,355.9009,364.6501,3.3113,2.0766,4.586,True,True,True 1475,V,Visa,2025-05-08,positive,low,short,"The announcement of a forward-looking strategic initiative may generate investor interest, though im",348.6606,360.2059,355.9009,364.6501,3.3113,2.0766,4.586,True,True,True
@@ -235,22 +235,22 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
1022,SPOT,Spotify,2025-05-04,positive,low,long,"While Backstage is gaining traction in the internal developer portal space, its market share impact ",637.65,648.25,656.3,665.14,1.6624,2.9248,4.3111,True,True,True 1022,SPOT,Spotify,2025-05-04,positive,low,long,"While Backstage is gaining traction in the internal developer portal space, its market share impact ",637.65,648.25,656.3,665.14,1.6624,2.9248,4.3111,True,True,True
1067,AMZN,Amazon,2025-05-02,positive,medium,short,"Amazon is positioned to gain market share during tariff-related uncertainty, as it did during the pa",189.98,193.06,205.59,205.01,1.6212,8.2167,7.9114,True,True,True 1067,AMZN,Amazon,2025-05-02,positive,medium,short,"Amazon is positioned to gain market share during tariff-related uncertainty, as it did during the pa",189.98,193.06,205.59,205.01,1.6212,8.2167,7.9114,True,True,True
1068,AMZN,Amazon,2025-05-02,positive,medium,short,"Diverse seller base and proactive inventory management reduce the risk of price increases, strengthe",189.98,193.06,205.59,205.01,1.6212,8.2167,7.9114,True,True,True 1068,AMZN,Amazon,2025-05-02,positive,medium,short,"Diverse seller base and proactive inventory management reduce the risk of price increases, strengthe",189.98,193.06,205.59,205.01,1.6212,8.2167,7.9114,True,True,True
1375,META,Meta,2025-05-02,positive,medium,medium,"Launching a premium AI service positions Meta to compete more effectively with OpenAI, Google, and M",595.1632,590.6473,638.3485,645.4763,-0.7588,7.256,8.4537,False,True,True 1375,META,Meta,2025-05-02,positive,medium,medium,"Launching a premium AI service positions Meta to compete more effectively with OpenAI, Google, and M",595.1632,590.6473,638.3484,645.4763,-0.7588,7.256,8.4537,False,True,True
1376,META,Meta,2025-05-02,positive,medium,medium,With nearly a billion users already on Meta AI and a potential premium tier offering enhanced featur,595.1632,590.6473,638.3485,645.4763,-0.7588,7.256,8.4537,False,True,True 1376,META,Meta,2025-05-02,positive,medium,medium,With nearly a billion users already on Meta AI and a potential premium tier offering enhanced featur,595.1632,590.6473,638.3484,645.4763,-0.7588,7.256,8.4537,False,True,True
1037,META,Meta,2025-04-29,positive,medium,short,Launching a standalone AI app enhances Meta's visibility and positioning in the competitive AI assis,552.7156,585.4835,653.9897,640.3223,5.9285,18.323,15.8502,True,True,True 1037,META,Meta,2025-04-29,positive,medium,short,Launching a standalone AI app enhances Meta's visibility and positioning in the competitive AI assis,552.7156,585.4834,653.9897,640.3223,5.9285,18.323,15.8502,True,True,True
1038,META,Meta,2025-04-29,positive,low,medium,"The app leverages Meta's extensive user data for personalization, which could attract users over tim",552.7156,585.4835,653.9897,640.3223,5.9285,18.323,15.8502,True,True,True 1038,META,Meta,2025-04-29,positive,low,medium,"The app leverages Meta's extensive user data for personalization, which could attract users over tim",552.7156,585.4834,653.9897,640.3223,5.9285,18.323,15.8502,True,True,True
1039,PL,Planet Labs,2025-04-29,negative,medium,medium,"The $20M funding enables Near Space Labs to scale its stratospheric imaging operations, increasing c",3.43,3.5,3.78,3.97,2.0408,10.2041,15.7434,False,False,False 1039,PL,Planet Labs,2025-04-29,negative,medium,medium,"The $20M funding enables Near Space Labs to scale its stratospheric imaging operations, increasing c",3.43,3.5,3.78,3.97,2.0408,10.2041,15.7434,False,False,False
1291,META,Meta,2025-04-26,negative,medium,short,"High-profile public protest by grieving parents increases reputational damage and litigation risk, w",548.0302,595.1632,590.6473,625.1098,8.6004,7.7764,14.0648,False,False,False 1291,META,Meta,2025-04-26,negative,medium,short,"High-profile public protest by grieving parents increases reputational damage and litigation risk, w",548.0302,595.1632,590.6473,625.1097,8.6004,7.7764,14.0648,False,False,False
1292,META,Meta,2025-04-26,negative,medium,medium,Growing civil society and regulatory pressure could force Meta to implement stricter safety measures,548.0302,595.1632,590.6473,625.1098,8.6004,7.7764,14.0648,False,False,False 1292,META,Meta,2025-04-26,negative,medium,medium,Growing civil society and regulatory pressure could force Meta to implement stricter safety measures,548.0302,595.1632,590.6473,625.1097,8.6004,7.7764,14.0648,False,False,False
1293,META,Meta,2025-04-26,positive,high,short,"The protest is a direct indicator of escalating civil society pressure, which is likely to attract f",548.0302,595.1632,590.6473,625.1098,8.6004,7.7764,14.0648,True,True,True 1293,META,Meta,2025-04-26,positive,high,short,"The protest is a direct indicator of escalating civil society pressure, which is likely to attract f",548.0302,595.1632,590.6473,625.1097,8.6004,7.7764,14.0648,True,True,True
1362,GOOGL,Alphabet,2025-04-24,positive,medium,short,Alphabet exceeded earnings expectations and stock jumped over 7% in after-hours trading despite macr,158.7296,160.7426,153.7469,170.2796,1.2682,-3.1391,7.2765,True,False,True 1362,GOOGL,Alphabet,2025-04-24,positive,medium,short,Alphabet exceeded earnings expectations and stock jumped over 7% in after-hours trading despite macr,158.7296,160.7426,153.7469,170.2796,1.2682,-3.1391,7.2765,True,False,True
1047,NFLX,Netflix,2025-04-23,positive,medium,long,"Articulation of a $1 trillion market cap goal by co-CEO suggests strong long-term confidence, which ",104.959,113.172,115.541,119.463,7.825,10.082,13.8187,True,True,True 1047,NFLX,Netflix,2025-04-23,positive,medium,long,"Articulation of a $1 trillion market cap goal by co-CEO suggests strong long-term confidence, which ",104.959,113.172,115.541,119.463,7.825,10.082,13.8187,True,True,True
1048,NFLX,Netflix,2025-04-23,positive,medium,long,Ambitious growth targets and diversification into new ventures like theater and retail may strengthe,104.959,113.172,115.541,119.463,7.825,10.082,13.8187,True,True,True 1048,NFLX,Netflix,2025-04-23,positive,medium,long,Ambitious growth targets and diversification into new ventures like theater and retail may strengthe,104.959,113.172,115.541,119.463,7.825,10.082,13.8187,True,True,True
1052,META,Meta,2025-04-23,positive,medium,medium,"Expanding ads globally increases Threads' competitiveness against X, leveraging high user engagement",518.652,547.2925,594.9539,633.5235,5.5221,14.7116,22.1481,True,True,True 1052,META,Meta,2025-04-23,positive,medium,medium,"Expanding ads globally increases Threads' competitiveness against X, leveraging high user engagement",518.652,547.2925,594.9539,633.5236,5.5221,14.7116,22.1481,True,True,True
1053,META,Meta,2025-04-23,positive,high,short,Opening ad inventory to global advertisers directly expands monetization opportunities across a user,518.652,547.2925,594.9539,633.5235,5.5221,14.7116,22.1481,True,True,True 1053,META,Meta,2025-04-23,positive,high,short,Opening ad inventory to global advertisers directly expands monetization opportunities across a user,518.652,547.2925,594.9539,633.5236,5.5221,14.7116,22.1481,True,True,True
1054,META,Meta,2025-04-23,positive,medium,medium,"Meta positions Threads as more advertiser-friendly than X, using Instagram's network effects to stre",518.652,547.2925,594.9539,633.5235,5.5221,14.7116,22.1481,True,True,True 1054,META,Meta,2025-04-23,positive,medium,medium,"Meta positions Threads as more advertiser-friendly than X, using Instagram's network effects to stre",518.652,547.2925,594.9539,633.5236,5.5221,14.7116,22.1481,True,True,True
1045,META,Meta,2025-04-20,negative,medium,long,Ongoing struggles with Facebook's cultural relevance may weaken Meta's competitive position over tim,483.1527,545.568,595.1632,638.3485,12.9183,23.1833,32.1215,False,False,False 1045,META,Meta,2025-04-20,negative,medium,long,Ongoing struggles with Facebook's cultural relevance may weaken Meta's competitive position over tim,483.1527,545.568,595.1632,638.3484,12.9183,23.1833,32.1215,False,False,False
1046,META,Meta,2025-04-20,negative,medium,long,Declining cultural relevance of Facebook could lead to erosion in user engagement and time spent on ,483.1527,545.568,595.1632,638.3485,12.9183,23.1833,32.1215,False,False,False 1046,META,Meta,2025-04-20,negative,medium,long,Declining cultural relevance of Facebook could lead to erosion in user engagement and time spent on ,483.1527,545.568,595.1632,638.3484,12.9183,23.1833,32.1215,False,False,False
1040,META,Meta,2025-04-17,negative,medium,short,TikTok's continued dominance in short-form video has already caused a dramatic slowdown in Meta's gr,499.9204,531.4919,570.4304,641.8775,6.3153,14.1043,28.3959,False,False,False 1040,META,Meta,2025-04-17,negative,medium,short,TikTok's continued dominance in short-form video has already caused a dramatic slowdown in Meta's gr,499.9204,531.4919,570.4304,641.8775,6.3153,14.1043,28.3959,False,False,False
1041,META,Meta,2025-04-17,negative,medium,short,Zuckerberg's admission that TikTok directly slowed Meta's growth implies a loss of user engagement a,499.9204,531.4919,570.4304,641.8775,6.3153,14.1043,28.3959,False,False,False 1041,META,Meta,2025-04-17,negative,medium,short,Zuckerberg's admission that TikTok directly slowed Meta's growth implies a loss of user engagement a,499.9204,531.4919,570.4304,641.8775,6.3153,14.1043,28.3959,False,False,False
1058,RIVN,Rivian,2025-04-16,positive,medium,medium,"HelloFreshs adoption of 70 Rivian vans marks the first major commercial customer beyond Amazon, sig",11.49,11.8,13.66,14.82,2.698,18.886,28.9817,True,True,True 1058,RIVN,Rivian,2025-04-16,positive,medium,medium,"HelloFreshs adoption of 70 Rivian vans marks the first major commercial customer beyond Amazon, sig",11.49,11.8,13.66,14.82,2.698,18.886,28.9817,True,True,True
@@ -261,61 +261,61 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
1207,NVS,Novartis,2025-04-11,positive,medium,short,The announcement of a major investment in U.S. production facilities led to a 1.6% increase in Novar,104.3441,107.2749,108.8276,105.4892,2.8088,4.2969,1.0975,True,True,True 1207,NVS,Novartis,2025-04-11,positive,medium,short,The announcement of a major investment in U.S. production facilities led to a 1.6% increase in Novar,104.3441,107.2749,108.8276,105.4892,2.8088,4.2969,1.0975,True,True,True
1372,HF,Hugging Face,2025-04-11,positive,medium,medium,Increased public legal conflict between OpenAI and Elon Musk may divert focus and resources from Ope,19.9983,20.0924,19.9884,19.9785,0.4707,-0.0495,-0.0991,True,False,False 1372,HF,Hugging Face,2025-04-11,positive,medium,medium,Increased public legal conflict between OpenAI and Elon Musk may divert focus and resources from Ope,19.9983,20.0924,19.9884,19.9785,0.4707,-0.0495,-0.0991,True,False,False
1108,SHOP,Shopify,2025-04-10,negative,medium,short,"Growing traction of TikTok Shop in social commerce, especially among Gen Z and legacy brands, may er",84.63,83.65,95.12,94.0,-1.158,12.3951,11.0717,True,False,False 1108,SHOP,Shopify,2025-04-10,negative,medium,short,"Growing traction of TikTok Shop in social commerce, especially among Gen Z and legacy brands, may er",84.63,83.65,95.12,94.0,-1.158,12.3951,11.0717,True,False,False
1478,META,Meta,2025-04-10,negative,medium,short,Whistleblower testimony before Congress alleging collusion with the Chinese government on censorship,544.591,499.9204,531.4919,596.1501,-8.2026,-2.4053,9.4675,True,True,False 1478,META,Meta,2025-04-10,negative,medium,short,Whistleblower testimony before Congress alleging collusion with the Chinese government on censorship,544.591,499.9204,531.4919,596.1502,-8.2026,-2.4053,9.4675,True,True,False
1479,META,Meta,2025-04-10,negative,medium,medium,"Allegations of aiding Chinese AI development via Llama could damage partnerships, restrict future AI",544.591,499.9204,531.4919,596.1501,-8.2026,-2.4053,9.4675,True,True,False 1479,META,Meta,2025-04-10,negative,medium,medium,"Allegations of aiding Chinese AI development via Llama could damage partnerships, restrict future AI",544.591,499.9204,531.4919,596.1502,-8.2026,-2.4053,9.4675,True,True,False
1480,META,Meta,2025-04-10,positive,high,short,Senate testimony alleging Metas cooperation with the Chinese Communist Party on censorship and data,544.591,499.9204,531.4919,596.1501,-8.2026,-2.4053,9.4675,False,False,True 1480,META,Meta,2025-04-10,positive,high,short,Senate testimony alleging Metas cooperation with the Chinese Communist Party on censorship and data,544.591,499.9204,531.4919,596.1502,-8.2026,-2.4053,9.4675,False,False,True
1373,META,Meta,2025-04-10,negative,medium,short,"Allegations of collaboration with the Chinese Communist Party on censorship tools, aired during a U.",544.591,499.9204,531.4919,596.1501,-8.2026,-2.4053,9.4675,True,True,False 1373,META,Meta,2025-04-10,negative,medium,short,"Allegations of collaboration with the Chinese Communist Party on censorship tools, aired during a U.",544.591,499.9204,531.4919,596.1502,-8.2026,-2.4053,9.4675,True,True,False
1374,META,Meta,2025-04-10,negative,medium,medium,Increased reputational damage and regulatory scrutiny from U.S. lawmakers may weaken Meta's public t,544.591,499.9204,531.4919,596.1501,-8.2026,-2.4053,9.4675,True,True,False 1374,META,Meta,2025-04-10,negative,medium,medium,Increased reputational damage and regulatory scrutiny from U.S. lawmakers may weaken Meta's public t,544.591,499.9204,531.4919,596.1502,-8.2026,-2.4053,9.4675,True,True,False
1175,ORCL,Oracle,2025-03-31,negative,medium,short,"Public criticism over handling of security incidents, particularly involving sensitive patient data,",137.9258,125.4463,133.3026,138.7479,-9.048,-3.3519,0.5961,True,True,False 1175,ORCL,Oracle,2025-03-31,negative,medium,short,"Public criticism over handling of security incidents, particularly involving sensitive patient data,",137.9258,125.4463,133.3026,138.748,-9.048,-3.3519,0.5961,True,True,False
1176,ORCL,Oracle,2025-03-31,negative,medium,medium,"Security concerns, especially in healthcare and legacy infrastructure, may weaken trust in Oracle's ",137.9258,125.4463,133.3026,138.7479,-9.048,-3.3519,0.5961,True,True,False 1176,ORCL,Oracle,2025-03-31,negative,medium,medium,"Security concerns, especially in healthcare and legacy infrastructure, may weaken trust in Oracle's ",137.9258,125.4463,133.3026,138.748,-9.048,-3.3519,0.5961,True,True,False
1481,TSLA,Tesla,2025-03-27,positive,medium,short,Tesla's 100% US production insulates it from the 25% import tariffs that will burden competitors lik,273.13,267.28,252.4,259.51,-2.1418,-7.5898,-4.9866,False,False,False 1481,TSLA,Tesla,2025-03-27,positive,medium,short,Tesla's 100% US production insulates it from the 25% import tariffs that will burden competitors lik,273.13,267.28,252.4,259.51,-2.1418,-7.5898,-4.9866,False,False,False
1482,TSLA,Tesla,2025-03-27,positive,low,medium,"With competitors facing higher costs due to tariffs, Tesla may gain slight market share in the US, t",273.13,267.28,252.4,259.51,-2.1418,-7.5898,-4.9866,False,False,False 1482,TSLA,Tesla,2025-03-27,positive,low,medium,"With competitors facing higher costs due to tariffs, Tesla may gain slight market share in the US, t",273.13,267.28,252.4,259.51,-2.1418,-7.5898,-4.9866,False,False,False
1554,RIVN,Rivian,2025-03-26,positive,medium,medium,"By expanding into micromobility through Also, Rivian strengthens its technological brand and diversi",12.1,12.49,11.77,11.8,3.2231,-2.7273,-2.4793,True,False,False 1554,RIVN,Rivian,2025-03-26,positive,medium,medium,"By expanding into micromobility through Also, Rivian strengthens its technological brand and diversi",12.1,12.49,11.77,11.8,3.2231,-2.7273,-2.4793,True,False,False
1494,TSM,TSMC,2025-03-25,negative,medium,medium,The substantial capital expenditure with expected margin pressure from U.S. operations may weigh on ,178.6869,166.5769,139.6405,149.5478,-6.7772,-21.8518,-16.3074,True,True,True 1494,TSM,TSMC,2025-03-25,negative,medium,medium,The substantial capital expenditure with expected margin pressure from U.S. operations may weigh on ,178.6869,166.5769,139.6405,149.5478,-6.7772,-21.8519,-16.3073,True,True,True
1181,META,Meta,2025-03-24,negative,medium,short,"Meta's failed acquisition of FuriosaAI, an AI chip startup developing competitive chips for reasonin",616.9253,574.5675,514.6444,483.1527,-6.866,-16.5791,-21.6838,True,True,True 1181,META,Meta,2025-03-24,negative,medium,short,"Meta's failed acquisition of FuriosaAI, an AI chip startup developing competitive chips for reasonin",616.9254,574.5674,514.6444,483.1526,-6.866,-16.5791,-21.6838,True,True,True
1182,META,Meta,2025-03-24,negative,low,medium,"While FuriosaAI remains independent and may expand its partnerships (e.g., with LG AI Research), Met",616.9253,574.5675,514.6444,483.1527,-6.866,-16.5791,-21.6838,True,True,True 1182,META,Meta,2025-03-24,negative,low,medium,"While FuriosaAI remains independent and may expand its partnerships (e.g., with LG AI Research), Met",616.9254,574.5674,514.6444,483.1526,-6.866,-16.5791,-21.6838,True,True,True
1183,FTNT,Fortinet,2025-03-17,negative,medium,short,The public disclosure of active exploitation of Fortinet vulnerabilities by a LockBit-linked group m,96.67,99.79,96.26,96.85,3.2275,-0.4241,0.1862,False,True,False 1183,FTNT,Fortinet,2025-03-17,negative,medium,short,The public disclosure of active exploitation of Fortinet vulnerabilities by a LockBit-linked group m,96.67,99.79,96.26,96.85,3.2275,-0.4241,0.1862,False,True,False
1184,FTNT,Fortinet,2025-03-17,negative,medium,medium,Repeated security breaches linked to Fortinet products could weaken its market standing versus compe,96.67,99.79,96.26,96.85,3.2275,-0.4241,0.1862,False,True,False 1184,FTNT,Fortinet,2025-03-17,negative,medium,medium,Repeated security breaches linked to Fortinet products could weaken its market standing versus compe,96.67,99.79,96.26,96.85,3.2275,-0.4241,0.1862,False,True,False
1359,RIVN,Rivian,2025-03-05,positive,high,long,Providing core software and architecture to a major automaker like Volkswagen enhances Rivians stra,11.42,11.06,11.36,12.49,-3.1524,-0.5254,9.3695,False,False,True 1359,RIVN,Rivian,2025-03-05,positive,high,long,Providing core software and architecture to a major automaker like Volkswagen enhances Rivians stra,11.42,11.06,11.36,12.49,-3.1524,-0.5254,9.3695,False,False,True
1360,RIVN,Rivian,2025-03-05,positive,medium,short,The influx of capital and validation of Rivians technology by Volkswagen may boost investor confide,11.42,11.06,11.36,12.49,-3.1524,-0.5254,9.3695,False,False,True 1360,RIVN,Rivian,2025-03-05,positive,medium,short,The influx of capital and validation of Rivians technology by Volkswagen may boost investor confide,11.42,11.06,11.36,12.49,-3.1524,-0.5254,9.3695,False,False,True
1354,META,Meta,2025-03-05,positive,medium,medium,Expanding facial recognition tools in regulated markets like the UK and EU strengthens Meta's positi,653.8467,617.084,582.2435,582.1139,-5.6225,-10.9511,-10.9709,False,False,False 1354,META,Meta,2025-03-05,positive,medium,medium,Expanding facial recognition tools in regulated markets like the UK and EU strengthens Meta's positi,653.8466,617.0841,582.2435,582.114,-5.6225,-10.9511,-10.9709,False,False,False
1355,META,Meta,2025-03-05,positive,low,medium,"Optional anti-fraud and verification tools may improve user trust and retention, particularly among ",653.8467,617.084,582.2435,582.1139,-5.6225,-10.9511,-10.9709,False,False,False 1355,META,Meta,2025-03-05,positive,low,medium,"Optional anti-fraud and verification tools may improve user trust and retention, particularly among ",653.8466,617.0841,582.2435,582.114,-5.6225,-10.9511,-10.9709,False,False,False
1560,BLK,BlackRock,2025-03-02,positive,medium,short,"Record inflows suggest investor confidence remains strong despite the ESG reversal, potentially supp",941.8132,927.7991,909.947,927.5837,-1.488,-3.3835,-1.5109,False,False,False 1560,BLK,BlackRock,2025-03-02,positive,medium,short,"Record inflows suggest investor confidence remains strong despite the ESG reversal, potentially supp",941.8132,927.7991,909.947,927.5836,-1.488,-3.3835,-1.5109,False,False,False
1562,BLK,BlackRock,2025-03-02,positive,medium,short,"By aligning with conservative political forces and avoiding regulatory scrutiny, BlackRock may gain ",941.8132,927.7991,909.947,927.5837,-1.488,-3.3835,-1.5109,False,False,False 1562,BLK,BlackRock,2025-03-02,positive,medium,short,"By aligning with conservative political forces and avoiding regulatory scrutiny, BlackRock may gain ",941.8132,927.7991,909.947,927.5836,-1.488,-3.3835,-1.5109,False,False,False
1350,META,Meta,2025-02-27,positive,low,short,"Terminating leakers may strengthen internal discipline and protect strategic information, slightly i",655.6096,625.4207,588.2797,600.706,-4.6047,-10.2698,-8.3744,False,False,False 1350,META,Meta,2025-02-27,positive,low,short,"Terminating leakers may strengthen internal discipline and protect strategic information, slightly i",655.6095,625.4207,588.2797,600.706,-4.6047,-10.2698,-8.3744,False,False,False
1351,META,Meta,2025-02-27,negative,medium,short,Public disclosure of internal leaks and subsequent firings may amplify perceptions of internal disse,655.6096,625.4207,588.2797,600.706,-4.6047,-10.2698,-8.3744,True,True,True 1351,META,Meta,2025-02-27,negative,medium,short,Public disclosure of internal leaks and subsequent firings may amplify perceptions of internal disse,655.6095,625.4207,588.2797,600.706,-4.6047,-10.2698,-8.3744,True,True,True
1142,SAP,SAP,2025-02-27,negative,low,short,"The stock is continuing a downward trend, underperforming the Dax, and trading volume has decreased,",272.1395,276.837,252.9034,265.7473,1.7261,-7.0685,-2.3489,False,True,True 1142,SAP,SAP,2025-02-27,negative,low,short,"The stock is continuing a downward trend, underperforming the Dax, and trading volume has decreased,",272.1395,276.837,252.9034,265.7473,1.7261,-7.0685,-2.3489,False,True,True
1114,PLTR,Palantir,2025-02-08,positive,high,short,"Retail investor enthusiasm, dollar-cost averaging, and a significant rise in stock price in 2024 and",116.65,119.16,101.35,84.91,2.1517,-13.1162,-27.2096,True,False,False 1114,PLTR,Palantir,2025-02-08,positive,high,short,"Retail investor enthusiasm, dollar-cost averaging, and a significant rise in stock price in 2024 and",116.65,119.16,101.35,84.91,2.1517,-13.1162,-27.2096,True,False,False
1065,AMD,AMD,2025-02-04,positive,medium,medium,"Powering 100 million game consoles indicates strong market penetration in the gaming segment, likely",119.5,111.1,114.28,100.75,-7.0293,-4.3682,-15.6904,False,False,False 1065,AMD,AMD,2025-02-04,positive,medium,medium,"Powering 100 million game consoles indicates strong market penetration in the gaming segment, likely",119.5,111.1,114.28,100.75,-7.0293,-4.3682,-15.6904,False,False,False
1066,AMD,AMD,2025-02-04,positive,medium,short,Success in securing design wins across major console platforms strengthens AMD's position against co,119.5,111.1,114.28,100.75,-7.0293,-4.3682,-15.6904,False,False,False 1066,AMD,AMD,2025-02-04,positive,medium,short,Success in securing design wins across major console platforms strengthens AMD's position against co,119.5,111.1,114.28,100.75,-7.0293,-4.3682,-15.6904,False,False,False
1125,NVDA,NVIDIA,2025-01-30,negative,medium,short,"Technical indicators suggest further downside toward $110, with momentum shifting negative in the in",124.6092,128.6379,135.2457,120.1106,3.2331,8.5359,-3.6101,False,False,True 1125,NVDA,NVIDIA,2025-01-30,negative,medium,short,"Technical indicators suggest further downside toward $110, with momentum shifting negative in the in",124.6092,128.6378,135.2457,120.1106,3.233,8.5359,-3.6101,False,False,True
1244,NVDA,NVIDIA,2025-01-30,positive,medium,short,"The stock rebounded nearly 9% following a sharp decline, indicating strong investor resilience and c",124.6092,128.6379,135.2457,120.1106,3.2331,8.5359,-3.6101,True,True,False 1244,NVDA,NVIDIA,2025-01-30,positive,medium,short,"The stock rebounded nearly 9% following a sharp decline, indicating strong investor resilience and c",124.6092,128.6378,135.2457,120.1106,3.233,8.5359,-3.6101,True,True,False
1243,MS,Morgan Stanley,2025-01-24,positive,medium,short,"Morgan Stanley is highlighted as one of the top stocks to buy for strong Q4 earnings, with positive ",133.331,134.8122,136.3217,128.2484,1.1109,2.2431,-3.812,True,True,False 1243,MS,Morgan Stanley,2025-01-24,positive,medium,short,"Morgan Stanley is highlighted as one of the top stocks to buy for strong Q4 earnings, with positive ",132.6183,134.0916,135.593,127.5628,1.1109,2.2431,-3.812,True,True,False
1248,STX,Seagate,2025-01-23,positive,medium,short,Solid 2Q25 performance driven by cloud sector recovery and increasing AI storage demand support upwa,106.1709,96.2413,94.5374,100.5108,-9.3525,-10.9574,-5.3311,False,False,False 1248,STX,Seagate,2025-01-23,positive,medium,short,Solid 2Q25 performance driven by cloud sector recovery and increasing AI storage demand support upwa,106.1709,96.2413,94.5374,100.5108,-9.3525,-10.9574,-5.3311,False,False,False
1130,META,Meta,2025-01-21,positive,low,short,"Enhanced cross-platform integration improves user engagement and data sharing across Meta's apps, sl",613.9966,671.6353,701.3759,713.5073,9.3875,14.2312,16.207,True,True,True 1130,META,Meta,2025-01-21,positive,low,short,"Enhanced cross-platform integration improves user engagement and data sharing across Meta's apps, sl",613.9966,671.6353,701.3759,713.5073,9.3875,14.2312,16.2071,True,True,True
1466,TSM,TSMC,2025-01-16,positive,high,short,Strong profit growth driven by high AI chip demand supports a positive short-term stock price moveme,211.3388,221.0109,204.8055,198.5871,4.5766,-3.0914,-6.0338,True,False,False 1466,TSM,TSMC,2025-01-16,positive,high,short,Strong profit growth driven by high AI chip demand supports a positive short-term stock price moveme,211.3388,221.0109,204.8055,198.5871,4.5766,-3.0914,-6.0338,True,False,False
1467,TSM,TSMC,2025-01-16,positive,medium,medium,Continued leadership in advanced semiconductor manufacturing and strong customer relationships reinf,211.3388,221.0109,204.8055,198.5871,4.5766,-3.0914,-6.0338,True,False,False 1467,TSM,TSMC,2025-01-16,positive,medium,medium,Continued leadership in advanced semiconductor manufacturing and strong customer relationships reinf,211.3388,221.0109,204.8055,198.5871,4.5766,-3.0914,-6.0338,True,False,False
1468,TSM,TSMC,2025-01-16,negative,medium,medium,Geopolitical uncertainties and export restrictions may negatively affect future business operations ,211.3388,221.0109,204.8055,198.5871,4.5766,-3.0914,-6.0338,False,True,True 1468,TSM,TSMC,2025-01-16,negative,medium,medium,Geopolitical uncertainties and export restrictions may negatively affect future business operations ,211.3388,221.0109,204.8055,198.5871,4.5766,-3.0914,-6.0338,False,True,True
1312,META,Meta,2025-01-10,negative,high,short,"Widespread condemnation from 71 fact-checking organizations, including a public open letter, signals",613.3989,610.3214,644.9025,711.6646,-0.5017,5.1359,16.0199,True,False,False 1312,META,Meta,2025-01-10,negative,high,short,"Widespread condemnation from 71 fact-checking organizations, including a public open letter, signals",613.3988,610.3212,644.9025,711.6646,-0.5017,5.1359,16.0199,True,False,False
1313,META,Meta,2025-01-10,positive,medium,medium,Strong pushback from civil society groups may prompt increased scrutiny from regulators concerned wi,613.3989,610.3214,644.9025,711.6646,-0.5017,5.1359,16.0199,False,True,True 1313,META,Meta,2025-01-10,positive,medium,medium,Strong pushback from civil society groups may prompt increased scrutiny from regulators concerned wi,613.3988,610.3212,644.9025,711.6646,-0.5017,5.1359,16.0199,False,True,True
1159,NVDA,NVIDIA,2025-01-07,positive,medium,short,Analyst reaffirmation of Nvidia as a top pick following a major executive keynote typically boosts i,140.0941,131.7168,140.7839,118.6111,-5.9797,0.4924,-15.3347,False,True,False 1159,NVDA,NVIDIA,2025-01-07,positive,medium,short,Analyst reaffirmation of Nvidia as a top pick following a major executive keynote typically boosts i,140.0941,131.7168,140.7839,118.6111,-5.9797,0.4924,-15.3347,False,True,False
1160,NVDA,NVIDIA,2025-01-07,positive,low,medium,Positive analyst sentiment following a strategic keynote may reinforce market perception of Nvidia's,140.0941,131.7168,140.7839,118.6111,-5.9797,0.4924,-15.3347,False,True,False 1160,NVDA,NVIDIA,2025-01-07,positive,low,medium,Positive analyst sentiment following a strategic keynote may reinforce market perception of Nvidia's,140.0941,131.7168,140.7839,118.6111,-5.9797,0.4924,-15.3347,False,True,False
1157,RIVN,Rivian,2025-01-03,positive,high,short,"Rivian's stock surged 24.5%, its largest daily increase since going public, after meeting revised pr",16.49,13.85,14.21,12.56,-16.0097,-13.8266,-23.8326,False,False,False 1157,RIVN,Rivian,2025-01-03,positive,high,short,"Rivian's stock surged 24.5%, its largest daily increase since going public, after meeting revised pr",16.49,13.85,14.21,12.56,-16.0097,-13.8266,-23.8326,False,False,False
1158,RIVN,Rivian,2025-01-03,positive,medium,medium,Resolving production constraints and delivering above analyst expectations strengthens Rivian's posi,16.49,13.85,14.21,12.56,-16.0097,-13.8266,-23.8326,False,False,False 1158,RIVN,Rivian,2025-01-03,positive,medium,medium,Resolving production constraints and delivering above analyst expectations strengthens Rivian's posi,16.49,13.85,14.21,12.56,-16.0097,-13.8266,-23.8326,False,False,False
1162,AVGO,Broadcom,2024-12-31,positive,high,short,Broadcom's stock price rose 111% in 2024 due to strong AI-related demand and market outperformance r,229.2828,226.1181,222.2215,205.0728,-1.3803,-3.0797,-10.559,False,False,False 1162,AVGO,Broadcom,2024-12-31,positive,high,short,Broadcom's stock price rose 111% in 2024 due to strong AI-related demand and market outperformance r,229.2828,226.1181,222.2216,205.0728,-1.3803,-3.0797,-10.559,False,False,False
1163,AVGO,Broadcom,2024-12-31,positive,medium,medium,"Broadcom is gaining ground in the AI chip and networking space despite Nvidia's dominance, positioni",229.2828,226.1181,222.2215,205.0728,-1.3803,-3.0797,-10.559,False,False,False 1163,AVGO,Broadcom,2024-12-31,positive,medium,medium,"Broadcom is gaining ground in the AI chip and networking space despite Nvidia's dominance, positioni",229.2828,226.1181,222.2216,205.0728,-1.3803,-3.0797,-10.559,False,False,False
1161,AAPL,Apple,2024-12-26,positive,high,medium,"Apple's stock soars to a record high, and JPMorgan has a positive outlook for the company in 2025, s",257.6127,242.5252,235.5632,222.4449,-5.8567,-8.5592,-13.6515,False,False,False 1161,AAPL,Apple,2024-12-26,positive,high,medium,"Apple's stock soars to a record high, and JPMorgan has a positive outlook for the company in 2025, s",257.6127,242.5252,235.5632,222.4449,-5.8567,-8.5592,-13.6515,False,False,False
1317,LLY,Eli Lilly,2024-12-23,positive,medium,short,Eli Lilly's potential to extend a winning streak over the broad market for 6 years suggests continue,789.0677,766.8309,758.17,735.6262,-2.8181,-3.9157,-6.7727,False,False,False 1317,LLY,Eli Lilly,2024-12-23,positive,medium,short,Eli Lilly's potential to extend a winning streak over the broad market for 6 years suggests continue,789.0677,766.8309,758.1701,735.6262,-2.8181,-3.9157,-6.7727,False,False,False
1427,SMCI,Super Micro Computer,2024-12-16,negative,medium,short,"Removal from Nasdaq 100 triggers passive fund selling, combined with ongoing governance and complian",33.44,32.4,30.68,31.08,-3.11,-8.2536,-7.0574,True,True,True 1427,SMCI,Super Micro Computer,2024-12-16,negative,medium,short,"Removal from Nasdaq 100 triggers passive fund selling, combined with ongoing governance and complian",33.44,32.4,30.68,31.08,-3.11,-8.2536,-7.0574,True,True,True
1428,SMCI,Super Micro Computer,2024-12-16,negative,low,medium,Reduced market visibility and investor confidence may impair access to capital and strategic partner,33.44,32.4,30.68,31.08,-3.11,-8.2536,-7.0574,True,True,True 1428,SMCI,Super Micro Computer,2024-12-16,negative,low,medium,Reduced market visibility and investor confidence may impair access to capital and strategic partner,33.44,32.4,30.68,31.08,-3.11,-8.2536,-7.0574,True,True,True
1254,META,Meta,2024-12-14,positive,medium,medium,"By challenging OpenAIs for-profit transition, Meta aims to constrain a key AI competitors flexibil",621.7454,582.9113,597.4131,613.3989,-6.246,-3.9135,-1.3424,False,False,False 1254,META,Meta,2024-12-14,positive,medium,medium,"By challenging OpenAIs for-profit transition, Meta aims to constrain a key AI competitors flexibil",621.7454,582.9113,597.4131,613.3988,-6.246,-3.9136,-1.3424,False,False,False
1255,META,Meta,2024-12-14,positive,high,short,"Metas public call for regulatory intervention increases scrutiny on OpenAI, amplifying broader regu",621.7454,582.9113,597.4131,613.3989,-6.246,-3.9135,-1.3424,False,False,False 1255,META,Meta,2024-12-14,positive,high,short,"Metas public call for regulatory intervention increases scrutiny on OpenAI, amplifying broader regu",621.7454,582.9113,597.4131,613.3988,-6.246,-3.9136,-1.3424,False,False,False
1424,AAPL,Apple,2024-12-13,positive,medium,medium,"Morgan Stanley naming Apple a top pick for 2025 signals strong institutional confidence, supporting ",246.7819,253.1074,254.2014,235.5632,2.5632,3.0065,-4.546,True,True,False 1424,AAPL,Apple,2024-12-13,positive,medium,medium,"Morgan Stanley naming Apple a top pick for 2025 signals strong institutional confidence, supporting ",246.7819,253.1073,254.2014,235.5632,2.5632,3.0065,-4.546,True,True,False
1441,SPOT,Spotify,2024-12-11,positive,medium,short,Public discussion around faking Spotify Wrapped indicates high user interest and emotional investmen,476.91,448.65,457.98,479.73,-5.9256,-3.9693,0.5913,False,False,True 1441,SPOT,Spotify,2024-12-11,positive,medium,short,Public discussion around faking Spotify Wrapped indicates high user interest and emotional investmen,476.91,448.65,457.98,479.73,-5.9256,-3.9693,0.5913,False,False,True
1439,RIVN,Rivian,2024-12-09,positive,medium,medium,Rivian's superior charging experience and renewable energy partnerships enhance its differentiation ,14.45,15.34,13.75,15.715,6.1592,-4.8443,8.7543,True,False,True 1439,RIVN,Rivian,2024-12-09,positive,medium,medium,Rivian's superior charging experience and renewable energy partnerships enhance its differentiation ,14.45,15.34,13.75,15.715,6.1592,-4.8443,8.7543,True,False,True
1440,RIVN,Rivian,2024-12-09,positive,low,long,Expanded charging infrastructure accessible to all EV users increases Rivian's visibility and brand ,14.45,15.34,13.75,15.715,6.1592,-4.8443,8.7543,True,False,True 1440,RIVN,Rivian,2024-12-09,positive,low,long,Expanded charging infrastructure accessible to all EV users increases Rivian's visibility and brand ,14.45,15.34,13.75,15.715,6.1592,-4.8443,8.7543,True,False,True
1431,CVX,Chevron,2024-12-08,positive,medium,short,"Goldman Sachs reiterated a buy rating with a raised price target, citing strong shareholder returns ",148.6666,145.6285,135.1987,139.9309,-2.0435,-9.0591,-5.876,False,False,False 1431,CVX,Chevron,2024-12-08,positive,medium,short,"Goldman Sachs reiterated a buy rating with a raised price target, citing strong shareholder returns ",148.6666,145.6285,135.1987,139.931,-2.0435,-9.0591,-5.876,False,False,False
1432,CVX,Chevron,2024-12-08,positive,medium,medium,Recognition by top Wall Street analysts as a top dividend stock enhances Chevron's profile among ene,148.6666,145.6285,135.1987,139.9309,-2.0435,-9.0591,-5.876,False,False,False 1432,CVX,Chevron,2024-12-08,positive,medium,medium,Recognition by top Wall Street analysts as a top dividend stock enhances Chevron's profile among ene,148.6666,145.6285,135.1987,139.931,-2.0435,-9.0591,-5.876,False,False,False
1429,SHOP,Shopify,2024-12-06,positive,medium,short,"Analyst upgrade typically leads to improved market sentiment and short-term stock price momentum, es",118.37,114.63,108.95,109.25,-3.1596,-7.9581,-7.7047,False,False,False 1429,SHOP,Shopify,2024-12-06,positive,medium,short,"Analyst upgrade typically leads to improved market sentiment and short-term stock price momentum, es",118.37,114.63,108.95,109.25,-3.1596,-7.9581,-7.7047,False,False,False
1430,SHOP,Shopify,2024-12-06,positive,low,medium,Increased recognition of AI capabilities may enhance Shopify's positioning against competitors over ,118.37,114.63,108.95,109.25,-3.1596,-7.9581,-7.7047,False,False,False 1430,SHOP,Shopify,2024-12-06,positive,low,medium,Increased recognition of AI capabilities may enhance Shopify's positioning against competitors over ,118.37,114.63,108.95,109.25,-3.1596,-7.9581,-7.7047,False,False,False
1437,AMD,AMD,2024-12-04,positive,medium,short,"The article suggests a potential catch-up trade based on technical charts, indicating upward momentu",143.99,130.15,121.41,120.63,-9.6118,-15.6816,-16.2234,False,False,False 1437,AMD,AMD,2024-12-04,positive,medium,short,"The article suggests a potential catch-up trade based on technical charts, indicating upward momentu",143.99,130.15,121.41,120.63,-9.6118,-15.6816,-16.2234,False,False,False
@@ -324,15 +324,15 @@ id,ticker,name,event_date,direction,magnitude,timeframe,rationale,price_0,price_
1433,NOW,ServiceNow,2024-12-01,positive,high,medium,"Analyst upgraded price target due to strong financials, AI tailwinds, and confidence in near- and me",209.686,224.868,224.22,216.292,7.2403,6.9313,3.1504,True,True,True 1433,NOW,ServiceNow,2024-12-01,positive,high,medium,"Analyst upgraded price target due to strong financials, AI tailwinds, and confidence in near- and me",209.686,224.868,224.22,216.292,7.2403,6.9313,3.1504,True,True,True
1434,NOW,ServiceNow,2024-12-01,positive,medium,long,"New Workflow Data Fabric product expected to power new workflows and AI agents, enhancing differenti",209.686,224.868,224.22,216.292,7.2403,6.9313,3.1504,True,True,True 1434,NOW,ServiceNow,2024-12-01,positive,medium,long,"New Workflow Data Fabric product expected to power new workflows and AI agents, enhancing differenti",209.686,224.868,224.22,216.292,7.2403,6.9313,3.1504,True,True,True
1435,NOW,ServiceNow,2024-12-01,positive,high,long,"Product innovation expected to double total addressable market to $500 billion, enabling greater mar",209.686,224.868,224.22,216.292,7.2403,6.9313,3.1504,True,True,True 1435,NOW,ServiceNow,2024-12-01,positive,high,long,"Product innovation expected to double total addressable market to $500 billion, enabling greater mar",209.686,224.868,224.22,216.292,7.2403,6.9313,3.1504,True,True,True
1442,META,Meta,2024-11-29,positive,high,long,"By building a private, globally spanning subsea cable, Meta gains greater control over data transmis",571.5638,620.7766,617.373,597.4131,8.6102,8.0147,4.5226,True,True,True 1442,META,Meta,2024-11-29,positive,high,long,"By building a private, globally spanning subsea cable, Meta gains greater control over data transmis",571.5638,620.7766,617.3729,597.4131,8.6102,8.0147,4.5225,True,True,True
1443,META,Meta,2024-11-29,negative,medium,short,"The $10 billion upfront investment may raise investor concerns about near-term profitability, especi",571.5638,620.7766,617.373,597.4131,8.6102,8.0147,4.5226,False,False,False 1443,META,Meta,2024-11-29,negative,medium,short,"The $10 billion upfront investment may raise investor concerns about near-term profitability, especi",571.5638,620.7766,617.3729,597.4131,8.6102,8.0147,4.5225,False,False,False
1444,META,Meta,2024-11-29,positive,medium,long,Exclusive control over high-capacity global data infrastructure will enable Meta to scale AI-driven ,571.5638,620.7766,617.373,597.4131,8.6102,8.0147,4.5226,True,True,True 1444,META,Meta,2024-11-29,positive,medium,long,Exclusive control over high-capacity global data infrastructure will enable Meta to scale AI-driven ,571.5638,620.7766,617.3729,597.4131,8.6102,8.0147,4.5225,True,True,True
1446,META,Meta,2024-11-21,positive,low,medium,"Proactive measures against scams may improve platform trustworthiness, slightly enhancing Meta's com",560.3878,571.5639,606.0079,593.1899,1.9943,8.1408,5.8535,True,True,True 1446,META,Meta,2024-11-21,positive,low,medium,"Proactive measures against scams may improve platform trustworthiness, slightly enhancing Meta's com",560.3878,571.564,606.0078,593.19,1.9944,8.1408,5.8535,True,True,True
1453,CMCSA,Comcast,2024-11-20,positive,medium,short,"A spin-off of the cable business could unlock shareholder value and streamline operations, potential",37.9328,37.5534,37.5446,33.4063,-1.0002,-1.0235,-11.933,False,False,False 1453,CMCSA,Comcast,2024-11-20,positive,medium,short,"A spin-off of the cable business could unlock shareholder value and streamline operations, potential",37.9328,37.5534,37.5446,33.4063,-1.0002,-1.0235,-11.933,False,False,False
1454,CMCSA,Comcast,2024-11-20,positive,medium,long,Separating the cable business may allow Comcast to focus on growth areas like streaming and broadban,37.9328,37.5534,37.5446,33.4063,-1.0002,-1.0235,-11.933,False,False,False 1454,CMCSA,Comcast,2024-11-20,positive,medium,long,Separating the cable business may allow Comcast to focus on growth areas like streaming and broadban,37.9328,37.5534,37.5446,33.4063,-1.0002,-1.0235,-11.933,False,False,False
1448,META,Meta,2024-11-14,negative,medium,short,The $840 million fine represents a significant financial penalty and reinforces investor concerns ab,574.3903,560.3878,571.5639,627.7628,-2.4378,-0.4921,9.292,True,True,False 1448,META,Meta,2024-11-14,negative,medium,short,The $840 million fine represents a significant financial penalty and reinforces investor concerns ab,574.3902,560.3878,571.564,627.7629,-2.4378,-0.492,9.2921,True,True,False
1449,META,Meta,2024-11-14,negative,medium,medium,"The EU ruling may force Meta to alter how Marketplace is integrated into Facebook, potentially reduc",574.3903,560.3878,571.5639,627.7628,-2.4378,-0.4921,9.292,True,True,False 1449,META,Meta,2024-11-14,negative,medium,medium,"The EU ruling may force Meta to alter how Marketplace is integrated into Facebook, potentially reduc",574.3902,560.3878,571.564,627.7629,-2.4378,-0.492,9.2921,True,True,False
1450,META,Meta,2024-11-14,positive,high,long,"This fine adds to a pattern of EU enforcement actions, signaling sustained and increasing regulatory",574.3903,560.3878,571.5639,627.7628,-2.4378,-0.4921,9.292,False,False,True 1450,META,Meta,2024-11-14,positive,high,long,"This fine adds to a pattern of EU enforcement actions, signaling sustained and increasing regulatory",574.3902,560.3878,571.564,627.7629,-2.4378,-0.492,9.2921,False,False,True
1527,TSLA,Tesla,2024-11-08,positive,high,short,"Tesla's stock surged 29% in one week following Trump's election, driven by investor optimism over re",321.22,320.72,352.56,389.22,-0.1557,9.7566,21.1693,False,True,True 1527,TSLA,Tesla,2024-11-08,positive,high,short,"Tesla's stock surged 29% in one week following Trump's election, driven by investor optimism over re",321.22,320.72,352.56,389.22,-0.1557,9.7566,21.1693,False,True,True
1528,TSLA,Tesla,2024-11-08,positive,medium,medium,Potential higher tariffs on Chinese EVs like BYD could reduce competitive pressure in the U.S. marke,321.22,320.72,352.56,389.22,-0.1557,9.7566,21.1693,False,True,True 1528,TSLA,Tesla,2024-11-08,positive,medium,medium,Potential higher tariffs on Chinese EVs like BYD could reduce competitive pressure in the U.S. marke,321.22,320.72,352.56,389.22,-0.1557,9.7566,21.1693,False,True,True
1552,RIVN,Rivian,2024-10-17,positive,low,short,"The novelty of themed updates may attract media attention and increase short-term consumer interest,",10.12,10.43,10.1,10.31,3.0632,-0.1976,1.8775,True,False,True 1552,RIVN,Rivian,2024-10-17,positive,low,short,"The novelty of themed updates may attract media attention and increase short-term consumer interest,",10.12,10.43,10.1,10.31,3.0632,-0.1976,1.8775,True,False,True
1 id ticker name event_date direction magnitude timeframe rationale price_0 price_5d price_10d price_20d 5d_return 10d_return 20d_return correct_5d correct_10d correct_20d
92 1240 HF Hugging Face 2025-10-03 negative medium medium OpenAI's valuation surge to $500 billion highlights its dominant market position and ability to attr 20.9692 20.8305 21.0089 20.9791 -0.6615 0.189 0.0472 True False False
93 1304 META Meta 2025-10-02 positive medium medium By using AI interaction data to improve recommendation relevance, Meta can increase user engagement 725.8361 732.2853 710.8811 665.3572 0.8885 -2.0604 -8.3323 True False False
94 1305 META Meta 2025-10-02 positive medium medium Enhanced personalization using deeper AI signals strengthens Meta's competitive edge in social media 725.8361 732.2853 710.8811 665.3572 0.8885 -2.0604 -8.3323 True False False
95 935 META Meta 2025-10-01 positive medium short AI-driven ad personalization strengthens Meta's competitive edge in digital advertising by improving 716.1423 716.6415 716.3519 750.4149 750.415 0.0697 0.0293 4.7857 True True True
96 937 META Meta 2025-10-01 positive medium medium Enhanced ad targeting using AI interactions could increase advertiser ROI, driving higher ad spend s 716.1423 716.6415 716.3519 750.4149 750.415 0.0697 0.0293 4.7857 True True True
97 1302 SPOT Spotify 2025-09-27 positive medium medium By adopting DDEX standards for AI transparency, Spotify positions itself as a responsible leader in 728.47 680.5 685.29 645.78 -6.585 -5.9275 -11.3512 False False False
98 926 META Meta 2025-09-18 positive medium medium Launch of consumer-ready smartglasses with differentiated AI features may increase Meta's presence i 778.4218 747.6595 725.8361 710.8811 -3.9519 -6.7554 -8.6766 False False False
99 927 META Meta 2025-09-18 positive medium short Introduction of AI-integrated smartglasses with partnerships in fitness tech strengthens Meta's posi 778.4218 747.6595 725.8361 710.8811 -3.9519 -6.7554 -8.6766 False False False
110 637 AZN AstraZeneca 2025-09-13 negative medium short Pausing a major investment may signal reduced confidence in the UK market, potentially affecting inv 154.4894 150.9859 145.9979 167.3157 -2.2678 -5.4965 8.3024 True True False
111 638 AZN AstraZeneca 2025-09-13 negative medium medium Delaying expansion in a key life sciences hub like Cambridge could slow innovation and talent acquis 154.4894 150.9859 145.9979 167.3157 -2.2678 -5.4965 8.3024 True True False
112 628 ORCL Oracle 2025-09-12 positive medium short Bullish options activity suggests increased investor confidence in Oracle's near-term stock performa 289.8924 306.2434 281.2406 291.1707 5.6404 -2.9845 0.441 True False True
113 988 AAPL Apple 2025-09-12 positive medium short Strong buy-side investor sentiment, particularly from Indian retail investors, combined with histori 233.6247 245.033 254.974 244.8034 4.8832 4.8831 9.1383 4.7849 True True True
114 627 ORCL Oracle 2025-09-11 negative medium short Shares retreated 6-7% after a record high due to concerns about overreliance on OpenAI for growth, d 305.4496 294.2976 289.049 295.1463 295.1462 -3.651 -5.3693 -3.3732 True True True
115 1409 ORCL Oracle 2025-09-11 positive high short Oracle's stock surged 35.98% following strong cloud revenue forecasts and major AI-related contracts 305.4496 294.2976 289.049 295.1463 295.1462 -3.651 -5.3693 -3.3732 False False False
116 1410 ORCL Oracle 2025-09-11 positive medium medium With a cloud services backlog nearing $500 billion and major contracts in AI infrastructure, Oracle 305.4496 294.2976 289.049 295.1463 295.1462 -3.651 -5.3693 -3.3732 False False False
117 1411 ORCL Oracle 2025-09-11 positive high medium Oracle's strategic positioning as a key AI cloud infrastructure provider through partnerships with l 305.4496 294.2976 289.049 295.1463 295.1462 -3.651 -5.3693 -3.3732 False False False
118 611 INTC Intel 2025-08-28 positive medium short Direct government investment signals confidence and improves public perception, consistent with prio 24.93 24.61 24.61 33.99 -1.2836 -1.2836 36.3418 False False True
119 612 INTC Intel 2025-08-28 positive medium medium Government funding and stake may enhance capital investment in manufacturing, supporting domestic pr 24.93 24.61 24.61 33.99 -1.2836 -1.2836 36.3418 False False True
120 608 NVDA NVIDIA 2025-08-28 positive high short Extraordinary demand and full-speed ramp-up of Blackwell Ultra platform indicate strong adoption, re 180.1401 171.6315 177.1506 177.6705 -4.7233 -1.6595 -1.3709 False False False
135 857 PLTR Palantir 2025-08-10 positive medium medium Recognition as 'the best story in all of software' and leadership in AI-driven government and enterp 182.68 177.17 158.74 153.11 -3.0162 -13.1049 -16.1868 False False False
136 1208 INTC Intel 2025-08-08 negative medium short Trump's public demand for CEO resignation and allegations of conflict due to ties with Chinese firms 19.95 24.56 24.8 24.49 23.1078 24.3108 22.7569 False False False
137 1209 INTC Intel 2025-08-08 negative low short Leadership instability and political scrutiny may delay turnaround plans, giving competitors like Nv 19.95 24.56 24.8 24.49 23.1078 24.3108 22.7569 False False False
138 1210 META Meta 2025-08-08 positive high medium The $29 billion financing enables accelerated AI infrastructure development, strengthening Meta's ca 767.4975 767.4976 783.3901 783.3902 753.0215 750.687 750.6871 2.0707 -1.8861 -2.1903 True False False
139 1289 TSM TSMC 2025-08-08 negative medium short The leak of trade secrets, even if not directly TSMC’s fault, could undermine confidence in its IP p 239.7449 236.8203 230.9811 241.3113 241.3112 -1.2199 -3.6555 0.6534 0.6533 True True False
140 1290 TSM TSMC 2025-08-08 negative low short While the incident does not directly implicate TSMC in wrongdoing, associated supply chain instabili 239.7449 236.8203 230.9811 241.3113 241.3112 -1.2199 -3.6555 0.6534 0.6533 True True False
141 1218 META Meta 2025-08-08 positive high long The $29 billion financing enables large-scale AI data center development, strengthening Meta's infra 767.4975 767.4976 783.3901 783.3902 753.0215 750.687 750.6871 2.0707 -1.8861 -2.1903 True False False
142 1511 SPOT Spotify 2025-08-07 positive medium short The introduction of AI DJ, which provides personalized, context-rich music recommendations using gen 686.74 698.5 689.47 703.85 1.7124 0.3975 2.4915 True True True
143 1513 SPOT Spotify 2025-08-07 positive medium medium Investment in advanced AI features like AI DJ strengthens Spotify’s differentiation from competitors 686.74 698.5 689.47 703.85 1.7124 0.3975 2.4915 True True True
144 851 PLTR Palantir 2025-08-07 negative medium medium CEO's remarks may deepen skepticism among educated public and academia, contributing to declining pu 182.2 181.02 156.18 156.14 -0.6476 -14.281 -14.303 True True True
145 852 PLTR Palantir 2025-08-07 positive medium long Positioning Palantir as a meritocratic alternative to elite education could strengthen employer bran 182.2 181.02 156.18 156.14 -0.6476 -14.281 -14.303 False False False
146 1288 TSM TSMC 2025-08-07 negative medium short Increased geopolitical risk and costly overseas expansion could weigh on investor sentiment in the n 240.5281 238.922 225.3699 233.182 -0.6677 -6.302 -3.0541 -3.0542 True True True
147 1509 TSM TSMC 2025-08-07 positive medium short Tariff exemption strengthens TSMC's competitive position relative to non-U.S.-based semiconductor ma 240.5281 238.922 225.3699 233.182 -0.6677 -6.302 -3.0541 -3.0542 False False False
148 1510 TSM TSMC 2025-08-07 positive low short Exemption from high tariffs provides operational certainty and reduces near-term geopolitical risk, 240.5281 238.922 225.3699 233.182 -0.6677 -6.302 -3.0541 -3.0542 False False False
149 873 PLTR Palantir 2025-08-05 positive high short Palantir's strong earnings, revenue growth of nearly 50%, net income up 144%, raised guidance, and i 173.27 186.97 157.75 157.09 7.9067 -8.9571 -9.338 True False False
150 874 PLTR Palantir 2025-08-05 positive medium medium Investor confidence in Palantir's AI-powered efficiency and scalability may accelerate adoption in g 173.27 186.97 157.75 157.09 7.9067 -8.9571 -9.338 True False False
151 875 PLTR Palantir 2025-08-05 positive medium short Palantir's demonstrated ability to grow revenue while reducing workforce through AI gives it a perce 173.27 186.97 157.75 157.09 7.9067 -8.9571 -9.338 True False False
152 1463 META Meta 2025-08-01 positive high short Meta shares jump after strong third-quarter sales forecast and better-than-expected financial perfor 748.2527 767.4975 767.4976 783.3901 783.3902 736.9692 2.572 4.6959 -1.508 True True False
153 1307 MSFT Microsoft 2025-08-01 positive high short Microsoft's stock rose 3.9% on July 31, 2025, following record valuation and strong quarterly result 521.0829 519.0249 519.025 517.1657 504.5917 -0.395 -0.3949 -0.7517 -3.1648 False False False
154 1308 MSFT Microsoft 2025-08-01 positive medium medium Azure's 39% growth and increasing AI-driven cloud revenue suggest Microsoft is gaining cloud market 521.0829 519.0249 519.025 517.1657 504.5917 -0.395 -0.3949 -0.7517 -3.1648 False False False
155 1309 MSFT Microsoft 2025-08-01 positive high long Surpassing four trillion dollars in market cap, second only to Nvidia, reinforces Microsoft's elite 521.0829 519.0249 519.025 517.1657 504.5917 -0.395 -0.3949 -0.7517 -3.1648 False False False
156 1400 ARM Arm Holdings 2025-07-31 negative high short Arm's shares dropped nearly 13% following disappointing guidance and a strategic shift that risks cu 141.375 135.57 140.55 142.55 -4.1061 -0.5836 0.8311 True True False
157 1401 ARM Arm Holdings 2025-07-31 negative medium medium Developing full chip solutions may lead to conflicts of interest with key customers like Nvidia and 141.375 135.57 140.55 142.55 -4.1061 -0.5836 0.8311 True True False
158 1402 ARM Arm Holdings 2025-07-31 negative low long Long-term market share could be affected if customers reduce reliance on Arm's IP due to competitive 141.375 135.57 140.55 142.55 -4.1061 -0.5836 0.8311 True True False
163 1222 META Meta 2025-07-31 positive medium medium Aggressive investment in AI talent and infrastructure positions Meta to better compete with OpenAI, 771.6278 760.045 780.2974 749.3502 -1.5011 1.1235 -2.8871 False True False
164 1223 META Meta 2025-07-31 positive medium medium Strong ad revenue growth and AI-driven product enhancements may increase user engagement and ad mark 771.6278 760.045 780.2974 749.3502 -1.5011 1.1235 -2.8871 False True False
165 1279 UBS UBS 2025-07-30 negative medium medium Proposed capital requirements could impair competitiveness if implemented; CEO warns 42 billion doll 36.9761 37.0834 38.6529 39.15 0.29 4.5347 5.8793 False False False
166 893 META Meta 2025-07-26 positive high medium Hiring a foundational OpenAI researcher and formalizing leadership under a strong AI executive team 715.9486 748.2527 767.4975 767.4976 753.0215 4.5121 7.2001 5.1781 True True True
167 894 META Meta 2025-07-26 positive medium long Strengthening AI talent base supports future AI product development, potentially increasing market s 715.9486 748.2527 767.4975 767.4976 753.0215 4.5121 7.2001 5.1781 True True True
168 1558 VZ Verizon 2025-07-24 negative low short The $175 million penalty represents a one-time cost that may slightly pressure earnings, but given V 41.0128 40.7082 40.8891 42.8693 -0.7428 -0.3018 4.5264 4.5265 True True False
169 1559 VZ Verizon 2025-07-24 negative medium short Increased legal risk from patent litigation could affect investor sentiment and raise concerns about 41.0128 40.7082 40.8891 42.8693 -0.7428 -0.3018 4.5264 4.5265 True True False
170 799 META Meta 2025-07-17 negative medium short Public perception may be negatively influenced by the association of top executives with privacy vio 699.7665 713.1252 771.6278 780.2974 1.909 10.2693 11.5083 False False False
171 1109 NVDA NVIDIA 2025-07-10 positive high short Nvidia's stock has surged 69% since early April and analysts project an additional 17% rise to $190 164.0727 172.9713 173.7111 180.74 5.4235 5.8745 10.1584 True True True
172 1110 NVDA NVIDIA 2025-07-10 positive medium medium Ongoing demand from big tech and AI innovators for high-performance computing chips reinforces Nvidi 164.0727 172.9713 173.7111 180.74 5.4235 5.8745 10.1584 True True True
182 1084 MU Micron 2025-07-03 positive low long Sustained revenue growth from rising HBM demand and expanded production capacity could support long- 121.998 122.9316 113.0959 108.9819 0.7653 -7.2969 -10.6691 True False False
183 1506 BP BP 2025-07-02 positive medium short Takeover speculation and activist involvement typically create short-term stock price momentum, even 30.038 30.0093 30.633 30.9497 -0.0958 1.9808 3.0351 False True True
184 1507 BP BP 2025-07-02 negative medium medium Persistent speculation that BP could be acquired may weaken its strategic autonomy and bargaining po 30.038 30.0093 30.633 30.9497 -0.0958 1.9808 3.0351 True False False
185 902 META Meta 2025-06-13 positive high medium Acquiring key AI talent and investing heavily in AI infrastructure through Scale AI strengthens Meta 680.7462 680.7463 680.7512 731.9111 715.8289 0.0007 7.516 5.1536 5.1535 True True True
186 903 META Meta 2025-06-13 positive medium short Major strategic investment in AI and high-profile talent acquisition may be viewed favorably by inve 680.7462 680.7463 680.7512 731.9111 715.8289 0.0007 7.516 5.1536 5.1535 True True True
187 1476 NVS Novartis 2025-06-13 positive medium short Novo Nordisk's leadership turmoil and stock decline may weaken its market positioning, creating oppo 115.9217 112.3504 116.4652 117.4453 -3.0808 0.4688 1.3144 False True True
188 1477 NVS Novartis 2025-06-13 positive low short While Novartis is not directly affected by Novo Nordisk's CEO dismissal, reduced competitive pressur 115.9217 112.3504 116.4652 117.4453 -3.0808 0.4688 1.3144 False True True
189 1085 AMD AMD 2025-06-13 positive high medium AMD’s launch of the Helios server and partnership with OpenAI strengthen its position in the AI chip 116.16 128.24 143.81 146.42 10.3995 23.8034 26.0503 True True True
195 1397 UBS UBS 2025-06-08 positive high medium The new draft law significantly increases regulatory obligations, including capitalization of foreig 32.1019 31.1758 29.655 33.3107 -2.8849 -7.6222 3.7656 False False True
196 1556 UBS UBS 2025-06-06 negative medium short Stricter capital requirements may constrain UBS's ability to deploy capital efficiently, increasing 32.7745 31.1758 29.655 33.3107 -4.878 -9.5181 1.6359 True True False
197 1557 UBS UBS 2025-06-06 negative low short Announcement of higher capital requirements could lead to margin compression concerns, negatively im 32.7745 31.1758 29.655 33.3107 -4.878 -9.5181 1.6359 True True False
198 1393 AVGO Broadcom 2025-06-06 negative medium short Broadcom's stock fell 2% in extended trading after the forecast missed the loftiest expectations, de 244.9453 246.7011 248.5644 272.6165 272.6164 0.7168 1.4775 11.2969 False False False
199 913 META Meta 2025-06-04 positive medium long Securing long-term, stable nuclear power enhances Meta's ability to scale AI infrastructure, improvi 685.8104 685.8105 691.9812 694.1398 711.8981 0.8998 1.2145 3.8039 True True True
200 914 META Meta 2025-06-04 positive high long The 20-year power purchase agreement with Constellation Energy directly supports Meta's growing AI w 685.8104 685.8105 691.9812 694.1398 711.8981 0.8998 1.2145 3.8039 True True True
201 1106 AVGO Broadcom 2025-06-02 negative medium short Dissatisfied partners may drive customers toward competing private cloud solutions, increasing migra 246.711 242.3166 250.0738 274.0781 -1.7812 1.363 11.0927 11.0928 True False False
202 1107 AVGO Broadcom 2025-06-02 negative medium medium Reducing the number of channel partners, especially long-standing ones, could erode VMware's market 246.711 242.3166 250.0738 274.0781 -1.7812 1.363 11.0927 11.0928 True False False
203 1196 NVDA NVIDIA 2025-05-29 positive high short Nvidia's revenue surpassing $44bn despite China sales restrictions indicates robust global demand fo 139.1572 139.957 144.9759 154.9942 0.5748 4.1814 11.3807 True True True
204 1197 NVDA NVIDIA 2025-05-29 positive medium medium Ability to achieve record revenue under geopolitical constraints reinforces Nvidia's competitive adv 139.1572 139.957 144.9759 154.9942 0.5748 4.1814 11.3807 True True True
205 1198 NVDA NVIDIA 2025-05-29 positive medium short Strong revenue performance despite headwinds aligns with analyst sentiment supporting stock valuatio 139.1572 139.957 144.9759 154.9942 0.5748 4.1814 11.3807 True True True
206 1203 LHX L3Harris Technologies 2025-05-29 positive medium short Technical breakout above $232 resistance and inclusion in a model portfolio suggest near-term upward 239.3204 239.1635 247.3939 243.8468 -0.0655 3.3735 1.8914 False True True
207 1503 META Meta 2025-05-29 positive medium medium One billion monthly users of Meta AI strengthens Meta's position in the generative AI race, though i 643.0439 682.4907 691.2036 724.3888 724.3887 6.1344 7.4893 12.65 True True True
208 1504 META Meta 2025-05-29 positive low short High user engagement with Meta AI may lead to incremental gains in AI assistant market share, but Go 643.0439 682.4907 691.2036 724.3888 724.3887 6.1344 7.4893 12.65 True True True
209 1271 NVS Novartis 2025-05-29 positive medium short As a competitor in the metabolic and pharmaceutical space, Novartis may benefit from Novo Nordisk's 109.2546 114.3108 117.2027 116.766 4.6278 7.2748 6.8751 True True True
210 1272 NVS Novartis 2025-05-29 positive low short While not directly mentioned, the known positive impact of production investment and divestment on N 109.2546 114.3108 117.2027 116.766 4.6278 7.2748 6.8751 True True True
211 1273 META Meta 2025-05-29 positive medium medium Increased AI integration in advertising and user content, combined with high advertiser adoption, po 643.0439 682.4907 691.2036 724.3888 724.3887 6.1344 7.4893 12.65 True True True
212 1274 META Meta 2025-05-29 positive high medium Meta's massive AI investment, global user base, and early lead in AI-powered advertising tools stren 643.0439 682.4907 691.2036 724.3888 724.3887 6.1344 7.4893 12.65 True True True
213 1199 META Meta 2025-05-25 positive medium medium Expanding AI training with user data may improve Meta AI and Llama models, enhancing competitiveness 640.3224 640.3223 645.4763 695.5401 680.7512 0.8049 8.6234 6.3138 True True True
214 1200 META Meta 2025-05-25 negative high short Noyb's challenge and opt-out model may lead to GDPR enforcement actions, increasing regulatory and l 640.3224 640.3223 645.4763 695.5401 680.7512 0.8049 8.6234 6.3138 False False False
215 1201 META Meta 2025-05-25 negative medium short Public backlash over data usage for AI without explicit consent could harm user trust, especially in 640.3224 640.3223 645.4763 695.5401 680.7512 0.8049 8.6234 6.3138 False False False
216 1202 META Meta 2025-05-25 negative low short Short-term investor concerns may arise from increased regulatory scrutiny and reputational risk tied 640.3224 640.3223 645.4763 695.5401 680.7512 0.8049 8.6234 6.3138 False False False
217 1259 TSLA Tesla 2025-05-23 negative medium short Being outsold in Europe suggests Tesla is losing market share to a strong competitor in a key region 339.34 346.46 295.14 322.16 2.0982 -13.0253 -5.0628 False True True
218 1260 TSLA Tesla 2025-05-23 negative medium short A competitor labeled as a 'Tesla-killer' gaining sales leadership in Europe undermines Tesla's compe 339.34 346.46 295.14 322.16 2.0982 -13.0253 -5.0628 False True True
219 1261 TSLA Tesla 2025-05-23 negative low short Missing sales expectations in a major market can negatively impact investor sentiment, especially am 339.34 346.46 295.14 322.16 2.0982 -13.0253 -5.0628 False True True
220 1464 SHOP Shopify 2025-05-23 positive medium short The launch of the AI Store Builder enhances Shopify's product offering, differentiating its platform 101.51 107.22 111.41 106.4 5.6251 9.7527 4.8173 True True True
221 1189 WBD Warner Bros Discovery 2025-05-14 positive medium medium By refocusing on HBO's premium brand and distinct adult-oriented content, WBD aims to carve out a cl 9.21 8.95 10.02 10.51 -2.823 8.7948 14.1151 False True True
222 1282 META Meta 2025-05-08 negative medium short Public exposure of widespread scam activity leveraging Meta's platforms may weaken user trust and in 596.1501 596.1502 641.8775 634.5903 634.5902 682.4907 7.6704 6.4481 6.448 14.483 False False False
223 1283 META Meta 2025-05-08 negative low short While the takedown demonstrates proactive moderation, the underlying prevalence of sophisticated sca 596.1501 596.1502 641.8775 634.5903 634.5902 682.4907 7.6704 6.4481 6.448 14.483 False False False
224 1473 V Visa 2025-05-08 positive high long By enabling AI agents to use its payment network, Visa positions itself as a foundational player in 348.6606 360.2059 355.9009 364.6501 3.3113 2.0766 4.586 True True True
225 1474 V Visa 2025-05-08 positive medium medium Opening its network to AI developers and expanding in key markets like Europe by 2025 could increase 348.6606 360.2059 355.9009 364.6501 3.3113 2.0766 4.586 True True True
226 1475 V Visa 2025-05-08 positive low short The announcement of a forward-looking strategic initiative may generate investor interest, though im 348.6606 360.2059 355.9009 364.6501 3.3113 2.0766 4.586 True True True
235 1022 SPOT Spotify 2025-05-04 positive low long While Backstage is gaining traction in the internal developer portal space, its market share impact 637.65 648.25 656.3 665.14 1.6624 2.9248 4.3111 True True True
236 1067 AMZN Amazon 2025-05-02 positive medium short Amazon is positioned to gain market share during tariff-related uncertainty, as it did during the pa 189.98 193.06 205.59 205.01 1.6212 8.2167 7.9114 True True True
237 1068 AMZN Amazon 2025-05-02 positive medium short Diverse seller base and proactive inventory management reduce the risk of price increases, strengthe 189.98 193.06 205.59 205.01 1.6212 8.2167 7.9114 True True True
238 1375 META Meta 2025-05-02 positive medium medium Launching a premium AI service positions Meta to compete more effectively with OpenAI, Google, and M 595.1632 590.6473 638.3485 638.3484 645.4763 -0.7588 7.256 8.4537 False True True
239 1376 META Meta 2025-05-02 positive medium medium With nearly a billion users already on Meta AI and a potential premium tier offering enhanced featur 595.1632 590.6473 638.3485 638.3484 645.4763 -0.7588 7.256 8.4537 False True True
240 1037 META Meta 2025-04-29 positive medium short Launching a standalone AI app enhances Meta's visibility and positioning in the competitive AI assis 552.7156 585.4835 585.4834 653.9897 640.3223 5.9285 18.323 15.8502 True True True
241 1038 META Meta 2025-04-29 positive low medium The app leverages Meta's extensive user data for personalization, which could attract users over tim 552.7156 585.4835 585.4834 653.9897 640.3223 5.9285 18.323 15.8502 True True True
242 1039 PL Planet Labs 2025-04-29 negative medium medium The $20M funding enables Near Space Labs to scale its stratospheric imaging operations, increasing c 3.43 3.5 3.78 3.97 2.0408 10.2041 15.7434 False False False
243 1291 META Meta 2025-04-26 negative medium short High-profile public protest by grieving parents increases reputational damage and litigation risk, w 548.0302 595.1632 590.6473 625.1098 625.1097 8.6004 7.7764 14.0648 False False False
244 1292 META Meta 2025-04-26 negative medium medium Growing civil society and regulatory pressure could force Meta to implement stricter safety measures 548.0302 595.1632 590.6473 625.1098 625.1097 8.6004 7.7764 14.0648 False False False
245 1293 META Meta 2025-04-26 positive high short The protest is a direct indicator of escalating civil society pressure, which is likely to attract f 548.0302 595.1632 590.6473 625.1098 625.1097 8.6004 7.7764 14.0648 True True True
246 1362 GOOGL Alphabet 2025-04-24 positive medium short Alphabet exceeded earnings expectations and stock jumped over 7% in after-hours trading despite macr 158.7296 160.7426 153.7469 170.2796 1.2682 -3.1391 7.2765 True False True
247 1047 NFLX Netflix 2025-04-23 positive medium long Articulation of a $1 trillion market cap goal by co-CEO suggests strong long-term confidence, which 104.959 113.172 115.541 119.463 7.825 10.082 13.8187 True True True
248 1048 NFLX Netflix 2025-04-23 positive medium long Ambitious growth targets and diversification into new ventures like theater and retail may strengthe 104.959 113.172 115.541 119.463 7.825 10.082 13.8187 True True True
249 1052 META Meta 2025-04-23 positive medium medium Expanding ads globally increases Threads' competitiveness against X, leveraging high user engagement 518.652 547.2925 594.9539 633.5235 633.5236 5.5221 14.7116 22.1481 True True True
250 1053 META Meta 2025-04-23 positive high short Opening ad inventory to global advertisers directly expands monetization opportunities across a user 518.652 547.2925 594.9539 633.5235 633.5236 5.5221 14.7116 22.1481 True True True
251 1054 META Meta 2025-04-23 positive medium medium Meta positions Threads as more advertiser-friendly than X, using Instagram's network effects to stre 518.652 547.2925 594.9539 633.5235 633.5236 5.5221 14.7116 22.1481 True True True
252 1045 META Meta 2025-04-20 negative medium long Ongoing struggles with Facebook's cultural relevance may weaken Meta's competitive position over tim 483.1527 545.568 595.1632 638.3485 638.3484 12.9183 23.1833 32.1215 False False False
253 1046 META Meta 2025-04-20 negative medium long Declining cultural relevance of Facebook could lead to erosion in user engagement and time spent on 483.1527 545.568 595.1632 638.3485 638.3484 12.9183 23.1833 32.1215 False False False
254 1040 META Meta 2025-04-17 negative medium short TikTok's continued dominance in short-form video has already caused a dramatic slowdown in Meta's gr 499.9204 531.4919 570.4304 641.8775 6.3153 14.1043 28.3959 False False False
255 1041 META Meta 2025-04-17 negative medium short Zuckerberg's admission that TikTok directly slowed Meta's growth implies a loss of user engagement a 499.9204 531.4919 570.4304 641.8775 6.3153 14.1043 28.3959 False False False
256 1058 RIVN Rivian 2025-04-16 positive medium medium HelloFresh’s adoption of 70 Rivian vans marks the first major commercial customer beyond Amazon, sig 11.49 11.8 13.66 14.82 2.698 18.886 28.9817 True True True
261 1207 NVS Novartis 2025-04-11 positive medium short The announcement of a major investment in U.S. production facilities led to a 1.6% increase in Novar 104.3441 107.2749 108.8276 105.4892 2.8088 4.2969 1.0975 True True True
262 1372 HF Hugging Face 2025-04-11 positive medium medium Increased public legal conflict between OpenAI and Elon Musk may divert focus and resources from Ope 19.9983 20.0924 19.9884 19.9785 0.4707 -0.0495 -0.0991 True False False
263 1108 SHOP Shopify 2025-04-10 negative medium short Growing traction of TikTok Shop in social commerce, especially among Gen Z and legacy brands, may er 84.63 83.65 95.12 94.0 -1.158 12.3951 11.0717 True False False
264 1478 META Meta 2025-04-10 negative medium short Whistleblower testimony before Congress alleging collusion with the Chinese government on censorship 544.591 499.9204 531.4919 596.1501 596.1502 -8.2026 -2.4053 9.4675 True True False
265 1479 META Meta 2025-04-10 negative medium medium Allegations of aiding Chinese AI development via Llama could damage partnerships, restrict future AI 544.591 499.9204 531.4919 596.1501 596.1502 -8.2026 -2.4053 9.4675 True True False
266 1480 META Meta 2025-04-10 positive high short Senate testimony alleging Meta’s cooperation with the Chinese Communist Party on censorship and data 544.591 499.9204 531.4919 596.1501 596.1502 -8.2026 -2.4053 9.4675 False False True
267 1373 META Meta 2025-04-10 negative medium short Allegations of collaboration with the Chinese Communist Party on censorship tools, aired during a U. 544.591 499.9204 531.4919 596.1501 596.1502 -8.2026 -2.4053 9.4675 True True False
268 1374 META Meta 2025-04-10 negative medium medium Increased reputational damage and regulatory scrutiny from U.S. lawmakers may weaken Meta's public t 544.591 499.9204 531.4919 596.1501 596.1502 -8.2026 -2.4053 9.4675 True True False
269 1175 ORCL Oracle 2025-03-31 negative medium short Public criticism over handling of security incidents, particularly involving sensitive patient data, 137.9258 125.4463 133.3026 138.7479 138.748 -9.048 -3.3519 0.5961 True True False
270 1176 ORCL Oracle 2025-03-31 negative medium medium Security concerns, especially in healthcare and legacy infrastructure, may weaken trust in Oracle's 137.9258 125.4463 133.3026 138.7479 138.748 -9.048 -3.3519 0.5961 True True False
271 1481 TSLA Tesla 2025-03-27 positive medium short Tesla's 100% US production insulates it from the 25% import tariffs that will burden competitors lik 273.13 267.28 252.4 259.51 -2.1418 -7.5898 -4.9866 False False False
272 1482 TSLA Tesla 2025-03-27 positive low medium With competitors facing higher costs due to tariffs, Tesla may gain slight market share in the US, t 273.13 267.28 252.4 259.51 -2.1418 -7.5898 -4.9866 False False False
273 1554 RIVN Rivian 2025-03-26 positive medium medium By expanding into micromobility through Also, Rivian strengthens its technological brand and diversi 12.1 12.49 11.77 11.8 3.2231 -2.7273 -2.4793 True False False
274 1494 TSM TSMC 2025-03-25 negative medium medium The substantial capital expenditure with expected margin pressure from U.S. operations may weigh on 178.6869 166.5769 139.6405 149.5478 -6.7772 -21.8518 -21.8519 -16.3074 -16.3073 True True True
275 1181 META Meta 2025-03-24 negative medium short Meta's failed acquisition of FuriosaAI, an AI chip startup developing competitive chips for reasonin 616.9253 616.9254 574.5675 574.5674 514.6444 483.1527 483.1526 -6.866 -16.5791 -21.6838 True True True
276 1182 META Meta 2025-03-24 negative low medium While FuriosaAI remains independent and may expand its partnerships (e.g., with LG AI Research), Met 616.9253 616.9254 574.5675 574.5674 514.6444 483.1527 483.1526 -6.866 -16.5791 -21.6838 True True True
277 1183 FTNT Fortinet 2025-03-17 negative medium short The public disclosure of active exploitation of Fortinet vulnerabilities by a LockBit-linked group m 96.67 99.79 96.26 96.85 3.2275 -0.4241 0.1862 False True False
278 1184 FTNT Fortinet 2025-03-17 negative medium medium Repeated security breaches linked to Fortinet products could weaken its market standing versus compe 96.67 99.79 96.26 96.85 3.2275 -0.4241 0.1862 False True False
279 1359 RIVN Rivian 2025-03-05 positive high long Providing core software and architecture to a major automaker like Volkswagen enhances Rivian’s stra 11.42 11.06 11.36 12.49 -3.1524 -0.5254 9.3695 False False True
280 1360 RIVN Rivian 2025-03-05 positive medium short The influx of capital and validation of Rivian’s technology by Volkswagen may boost investor confide 11.42 11.06 11.36 12.49 -3.1524 -0.5254 9.3695 False False True
281 1354 META Meta 2025-03-05 positive medium medium Expanding facial recognition tools in regulated markets like the UK and EU strengthens Meta's positi 653.8467 653.8466 617.084 617.0841 582.2435 582.1139 582.114 -5.6225 -10.9511 -10.9709 False False False
282 1355 META Meta 2025-03-05 positive low medium Optional anti-fraud and verification tools may improve user trust and retention, particularly among 653.8467 653.8466 617.084 617.0841 582.2435 582.1139 582.114 -5.6225 -10.9511 -10.9709 False False False
283 1560 BLK BlackRock 2025-03-02 positive medium short Record inflows suggest investor confidence remains strong despite the ESG reversal, potentially supp 941.8132 927.7991 909.947 927.5837 927.5836 -1.488 -3.3835 -1.5109 False False False
284 1562 BLK BlackRock 2025-03-02 positive medium short By aligning with conservative political forces and avoiding regulatory scrutiny, BlackRock may gain 941.8132 927.7991 909.947 927.5837 927.5836 -1.488 -3.3835 -1.5109 False False False
285 1350 META Meta 2025-02-27 positive low short Terminating leakers may strengthen internal discipline and protect strategic information, slightly i 655.6096 655.6095 625.4207 588.2797 600.706 -4.6047 -10.2698 -8.3744 False False False
286 1351 META Meta 2025-02-27 negative medium short Public disclosure of internal leaks and subsequent firings may amplify perceptions of internal disse 655.6096 655.6095 625.4207 588.2797 600.706 -4.6047 -10.2698 -8.3744 True True True
287 1142 SAP SAP 2025-02-27 negative low short The stock is continuing a downward trend, underperforming the Dax, and trading volume has decreased, 272.1395 276.837 252.9034 265.7473 1.7261 -7.0685 -2.3489 False True True
288 1114 PLTR Palantir 2025-02-08 positive high short Retail investor enthusiasm, dollar-cost averaging, and a significant rise in stock price in 2024 and 116.65 119.16 101.35 84.91 2.1517 -13.1162 -27.2096 True False False
289 1065 AMD AMD 2025-02-04 positive medium medium Powering 100 million game consoles indicates strong market penetration in the gaming segment, likely 119.5 111.1 114.28 100.75 -7.0293 -4.3682 -15.6904 False False False
290 1066 AMD AMD 2025-02-04 positive medium short Success in securing design wins across major console platforms strengthens AMD's position against co 119.5 111.1 114.28 100.75 -7.0293 -4.3682 -15.6904 False False False
291 1125 NVDA NVIDIA 2025-01-30 negative medium short Technical indicators suggest further downside toward $110, with momentum shifting negative in the in 124.6092 128.6379 128.6378 135.2457 120.1106 3.2331 3.233 8.5359 -3.6101 False False True
292 1244 NVDA NVIDIA 2025-01-30 positive medium short The stock rebounded nearly 9% following a sharp decline, indicating strong investor resilience and c 124.6092 128.6379 128.6378 135.2457 120.1106 3.2331 3.233 8.5359 -3.6101 True True False
293 1243 MS Morgan Stanley 2025-01-24 positive medium short Morgan Stanley is highlighted as one of the top stocks to buy for strong Q4 earnings, with positive 133.331 132.6183 134.8122 134.0916 136.3217 135.593 128.2484 127.5628 1.1109 2.2431 -3.812 True True False
294 1248 STX Seagate 2025-01-23 positive medium short Solid 2Q25 performance driven by cloud sector recovery and increasing AI storage demand support upwa 106.1709 96.2413 94.5374 100.5108 -9.3525 -10.9574 -5.3311 False False False
295 1130 META Meta 2025-01-21 positive low short Enhanced cross-platform integration improves user engagement and data sharing across Meta's apps, sl 613.9966 671.6353 701.3759 713.5073 9.3875 14.2312 16.207 16.2071 True True True
296 1466 TSM TSMC 2025-01-16 positive high short Strong profit growth driven by high AI chip demand supports a positive short-term stock price moveme 211.3388 221.0109 204.8055 198.5871 4.5766 -3.0914 -6.0338 True False False
297 1467 TSM TSMC 2025-01-16 positive medium medium Continued leadership in advanced semiconductor manufacturing and strong customer relationships reinf 211.3388 221.0109 204.8055 198.5871 4.5766 -3.0914 -6.0338 True False False
298 1468 TSM TSMC 2025-01-16 negative medium medium Geopolitical uncertainties and export restrictions may negatively affect future business operations 211.3388 221.0109 204.8055 198.5871 4.5766 -3.0914 -6.0338 False True True
299 1312 META Meta 2025-01-10 negative high short Widespread condemnation from 71 fact-checking organizations, including a public open letter, signals 613.3989 613.3988 610.3214 610.3212 644.9025 711.6646 -0.5017 5.1359 16.0199 True False False
300 1313 META Meta 2025-01-10 positive medium medium Strong pushback from civil society groups may prompt increased scrutiny from regulators concerned wi 613.3989 613.3988 610.3214 610.3212 644.9025 711.6646 -0.5017 5.1359 16.0199 False True True
301 1159 NVDA NVIDIA 2025-01-07 positive medium short Analyst reaffirmation of Nvidia as a top pick following a major executive keynote typically boosts i 140.0941 131.7168 140.7839 118.6111 -5.9797 0.4924 -15.3347 False True False
302 1160 NVDA NVIDIA 2025-01-07 positive low medium Positive analyst sentiment following a strategic keynote may reinforce market perception of Nvidia's 140.0941 131.7168 140.7839 118.6111 -5.9797 0.4924 -15.3347 False True False
303 1157 RIVN Rivian 2025-01-03 positive high short Rivian's stock surged 24.5%, its largest daily increase since going public, after meeting revised pr 16.49 13.85 14.21 12.56 -16.0097 -13.8266 -23.8326 False False False
304 1158 RIVN Rivian 2025-01-03 positive medium medium Resolving production constraints and delivering above analyst expectations strengthens Rivian's posi 16.49 13.85 14.21 12.56 -16.0097 -13.8266 -23.8326 False False False
305 1162 AVGO Broadcom 2024-12-31 positive high short Broadcom's stock price rose 111% in 2024 due to strong AI-related demand and market outperformance r 229.2828 226.1181 222.2215 222.2216 205.0728 -1.3803 -3.0797 -10.559 False False False
306 1163 AVGO Broadcom 2024-12-31 positive medium medium Broadcom is gaining ground in the AI chip and networking space despite Nvidia's dominance, positioni 229.2828 226.1181 222.2215 222.2216 205.0728 -1.3803 -3.0797 -10.559 False False False
307 1161 AAPL Apple 2024-12-26 positive high medium Apple's stock soars to a record high, and JPMorgan has a positive outlook for the company in 2025, s 257.6127 242.5252 235.5632 222.4449 -5.8567 -8.5592 -13.6515 False False False
308 1317 LLY Eli Lilly 2024-12-23 positive medium short Eli Lilly's potential to extend a winning streak over the broad market for 6 years suggests continue 789.0677 766.8309 758.17 758.1701 735.6262 -2.8181 -3.9157 -6.7727 False False False
309 1427 SMCI Super Micro Computer 2024-12-16 negative medium short Removal from Nasdaq 100 triggers passive fund selling, combined with ongoing governance and complian 33.44 32.4 30.68 31.08 -3.11 -8.2536 -7.0574 True True True
310 1428 SMCI Super Micro Computer 2024-12-16 negative low medium Reduced market visibility and investor confidence may impair access to capital and strategic partner 33.44 32.4 30.68 31.08 -3.11 -8.2536 -7.0574 True True True
311 1254 META Meta 2024-12-14 positive medium medium By challenging OpenAI’s for-profit transition, Meta aims to constrain a key AI competitor’s flexibil 621.7454 582.9113 597.4131 613.3989 613.3988 -6.246 -3.9135 -3.9136 -1.3424 False False False
312 1255 META Meta 2024-12-14 positive high short Meta’s public call for regulatory intervention increases scrutiny on OpenAI, amplifying broader regu 621.7454 582.9113 597.4131 613.3989 613.3988 -6.246 -3.9135 -3.9136 -1.3424 False False False
313 1424 AAPL Apple 2024-12-13 positive medium medium Morgan Stanley naming Apple a top pick for 2025 signals strong institutional confidence, supporting 246.7819 253.1074 253.1073 254.2014 235.5632 2.5632 3.0065 -4.546 True True False
314 1441 SPOT Spotify 2024-12-11 positive medium short Public discussion around faking Spotify Wrapped indicates high user interest and emotional investmen 476.91 448.65 457.98 479.73 -5.9256 -3.9693 0.5913 False False True
315 1439 RIVN Rivian 2024-12-09 positive medium medium Rivian's superior charging experience and renewable energy partnerships enhance its differentiation 14.45 15.34 13.75 15.715 6.1592 -4.8443 8.7543 True False True
316 1440 RIVN Rivian 2024-12-09 positive low long Expanded charging infrastructure accessible to all EV users increases Rivian's visibility and brand 14.45 15.34 13.75 15.715 6.1592 -4.8443 8.7543 True False True
317 1431 CVX Chevron 2024-12-08 positive medium short Goldman Sachs reiterated a buy rating with a raised price target, citing strong shareholder returns 148.6666 145.6285 135.1987 139.9309 139.931 -2.0435 -9.0591 -5.876 False False False
318 1432 CVX Chevron 2024-12-08 positive medium medium Recognition by top Wall Street analysts as a top dividend stock enhances Chevron's profile among ene 148.6666 145.6285 135.1987 139.9309 139.931 -2.0435 -9.0591 -5.876 False False False
319 1429 SHOP Shopify 2024-12-06 positive medium short Analyst upgrade typically leads to improved market sentiment and short-term stock price momentum, es 118.37 114.63 108.95 109.25 -3.1596 -7.9581 -7.7047 False False False
320 1430 SHOP Shopify 2024-12-06 positive low medium Increased recognition of AI capabilities may enhance Shopify's positioning against competitors over 118.37 114.63 108.95 109.25 -3.1596 -7.9581 -7.7047 False False False
321 1437 AMD AMD 2024-12-04 positive medium short The article suggests a potential catch-up trade based on technical charts, indicating upward momentu 143.99 130.15 121.41 120.63 -9.6118 -15.6816 -16.2234 False False False
324 1433 NOW ServiceNow 2024-12-01 positive high medium Analyst upgraded price target due to strong financials, AI tailwinds, and confidence in near- and me 209.686 224.868 224.22 216.292 7.2403 6.9313 3.1504 True True True
325 1434 NOW ServiceNow 2024-12-01 positive medium long New Workflow Data Fabric product expected to power new workflows and AI agents, enhancing differenti 209.686 224.868 224.22 216.292 7.2403 6.9313 3.1504 True True True
326 1435 NOW ServiceNow 2024-12-01 positive high long Product innovation expected to double total addressable market to $500 billion, enabling greater mar 209.686 224.868 224.22 216.292 7.2403 6.9313 3.1504 True True True
327 1442 META Meta 2024-11-29 positive high long By building a private, globally spanning subsea cable, Meta gains greater control over data transmis 571.5638 620.7766 617.373 617.3729 597.4131 8.6102 8.0147 4.5226 4.5225 True True True
328 1443 META Meta 2024-11-29 negative medium short The $10 billion upfront investment may raise investor concerns about near-term profitability, especi 571.5638 620.7766 617.373 617.3729 597.4131 8.6102 8.0147 4.5226 4.5225 False False False
329 1444 META Meta 2024-11-29 positive medium long Exclusive control over high-capacity global data infrastructure will enable Meta to scale AI-driven 571.5638 620.7766 617.373 617.3729 597.4131 8.6102 8.0147 4.5226 4.5225 True True True
330 1446 META Meta 2024-11-21 positive low medium Proactive measures against scams may improve platform trustworthiness, slightly enhancing Meta's com 560.3878 571.5639 571.564 606.0079 606.0078 593.1899 593.19 1.9943 1.9944 8.1408 5.8535 True True True
331 1453 CMCSA Comcast 2024-11-20 positive medium short A spin-off of the cable business could unlock shareholder value and streamline operations, potential 37.9328 37.5534 37.5446 33.4063 -1.0002 -1.0235 -11.933 False False False
332 1454 CMCSA Comcast 2024-11-20 positive medium long Separating the cable business may allow Comcast to focus on growth areas like streaming and broadban 37.9328 37.5534 37.5446 33.4063 -1.0002 -1.0235 -11.933 False False False
333 1448 META Meta 2024-11-14 negative medium short The $840 million fine represents a significant financial penalty and reinforces investor concerns ab 574.3903 574.3902 560.3878 571.5639 571.564 627.7628 627.7629 -2.4378 -0.4921 -0.492 9.292 9.2921 True True False
334 1449 META Meta 2024-11-14 negative medium medium The EU ruling may force Meta to alter how Marketplace is integrated into Facebook, potentially reduc 574.3903 574.3902 560.3878 571.5639 571.564 627.7628 627.7629 -2.4378 -0.4921 -0.492 9.292 9.2921 True True False
335 1450 META Meta 2024-11-14 positive high long This fine adds to a pattern of EU enforcement actions, signaling sustained and increasing regulatory 574.3903 574.3902 560.3878 571.5639 571.564 627.7628 627.7629 -2.4378 -0.4921 -0.492 9.292 9.2921 False False True
336 1527 TSLA Tesla 2024-11-08 positive high short Tesla's stock surged 29% in one week following Trump's election, driven by investor optimism over re 321.22 320.72 352.56 389.22 -0.1557 9.7566 21.1693 False True True
337 1528 TSLA Tesla 2024-11-08 positive medium medium Potential higher tariffs on Chinese EVs like BYD could reduce competitive pressure in the U.S. marke 321.22 320.72 352.56 389.22 -0.1557 9.7566 21.1693 False True True
338 1552 RIVN Rivian 2024-10-17 positive low short The novelty of themed updates may attract media attention and increase short-term consumer interest, 10.12 10.43 10.1 10.31 3.0632 -0.1976 1.8775 True False True
+93
View File
@@ -10,11 +10,13 @@ services:
environment: environment:
NODE_ENV: production NODE_ENV: production
INTELLIGENCE_DB: /data/intelligence.sqlite INTELLIGENCE_DB: /data/intelligence.sqlite
DURIIN_RUN_SCHEDULER: "false"
restart: unless-stopped restart: unless-stopped
networks: networks:
- nginx_proxy_manager_default - nginx_proxy_manager_default
intelligence: intelligence:
profiles: [legacy]
build: build:
context: . context: .
provenance: false provenance: false
@@ -31,6 +33,97 @@ services:
networks: networks:
- nginx_proxy_manager_default - nginx_proxy_manager_default
autonomy:
profiles: [autonomy]
build:
context: .
provenance: false
command: node workers/autonomy-entrypoint.js
env_file: .env
volumes:
- ./config.json:/app/config.json:ro
- ./data:/data
environment:
NODE_ENV: production
DURIIN_DB: /data/archive.sqlite
INTELLIGENCE_DB: /data/intelligence.sqlite
AUTONOMY_POLL_MS: "1000"
restart: unless-stopped
networks:
- nginx_proxy_manager_default
coordinator:
profiles: [autonomy]
build:
context: .
provenance: false
command: node workers/coordinator-entrypoint.js
env_file: .env
volumes:
- ./config.json:/app/config.json:ro
- ./data:/data
environment:
NODE_ENV: production
DURIIN_DB: /data/archive.sqlite
INTELLIGENCE_DB: /data/intelligence.sqlite
AUTONOMY_POLL_MS: "1000"
restart: unless-stopped
networks:
- nginx_proxy_manager_default
autonomy-outcomes:
profiles: [autonomy]
build:
context: .
provenance: false
command: node workers/outcome-autonomy-entrypoint.js
env_file: .env
volumes:
- ./data:/data
environment:
NODE_ENV: production
INTELLIGENCE_DB: /data/intelligence.sqlite
AUTONOMY_OUTCOME_POLL_MS: "60000"
restart: unless-stopped
networks:
- nginx_proxy_manager_default
calibration:
profiles: [autonomy]
build:
context: .
provenance: false
command: node workers/calibration-entrypoint.js
env_file: .env
volumes:
- ./data:/data
environment:
NODE_ENV: production
INTELLIGENCE_DB: /data/intelligence.sqlite
AUTONOMY_CALIBRATION_POLL_MS: "60000"
restart: unless-stopped
networks:
- nginx_proxy_manager_default
execution:
profiles: [autonomy]
build:
context: .
provenance: false
command: node workers/execution-entrypoint.js
env_file: .env
volumes:
- ./data:/data
environment:
NODE_ENV: production
INTELLIGENCE_DB: /data/intelligence.sqlite
AUTONOMY_EXECUTION_MODE: "shadow"
AUTONOMY_DEFAULT_NOTIONAL: "100"
AUTONOMY_EXECUTION_POLL_MS: "10000"
restart: unless-stopped
networks:
- nginx_proxy_manager_default
networks: networks:
nginx_proxy_manager_default: nginx_proxy_manager_default:
external: true external: true
+53
View File
@@ -0,0 +1,53 @@
# Duriin autonomy runtime
The autonomy runtime is additive to the existing archive and intelligence
tables. It is deliberately disabled until the paper-trading cutover is
approved.
## Services
- `api`: HTTP only; no background scheduler when `DURIIN_RUN_SCHEDULER=false`.
- `autonomy`: bounded archive reconciliation and live/historical job creation.
- `coordinator`: LLM proposal extraction only. It cannot create an order.
- `autonomy-outcomes`: resolves matured predictions against market and benchmark returns.
- `calibration`: creates empirical calibration snapshots and deterministic decisions.
- `intelligence`: legacy worker, available only under the `legacy` Compose profile.
Start only the API by default:
```bash
docker compose up -d api
```
The new runtime is explicitly opt-in:
```bash
docker compose --profile autonomy up -d autonomy coordinator autonomy-outcomes calibration
```
## Authority rules
The coordinator may return categorical, evidence-backed proposals. It may not
return probabilities, returns, position sizes or trade actions. Proposals must
reference existing archive article IDs and instruments in
`autonomy_instruments` with `active=1` and `tradable=1`.
Calibration is computed from resolved market-relative outcomes. The policy
engine emits `BUY`, `SELL`, `HOLD` or `ABSTAIN`; an LLM is not in this path.
Paper order intents use deterministic client IDs and are bounded by the
execution validator. A broker adapter must be explicitly configured; the
included simulator is the default test adapter.
## Database initialization
The autonomy schema is initialized additively by the autonomy workers and
maintenance scripts in the intelligence database. To create the initial
reconciliation job without starting workers:
```bash
npm run autonomy:init
```
Legacy predictions remain legacy records and are not silently included in
calibration. New prospective predictions are the trusted learning set.
+6 -1
View File
@@ -5,7 +5,12 @@
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {
"start": "node server.js", "start": "node server.js",
"workers": "node workers/index.js" "workers": "node workers/index.js",
"test": "node --test test/**/*.test.js",
"autonomy:init": "node scripts/initialize-autonomy.js",
"autonomy:allowlist": "node scripts/set-autonomy-instrument.js",
"autonomy:sync-assets": "node scripts/sync-paper-assets.js",
"autonomy:import-legacy": "node scripts/import-legacy-intelligence.js"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env node
const path = require('path');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const sourcePath = process.env.LEGACY_INTELLIGENCE_DB || path.resolve(process.cwd(), 'intelligence.sqlite');
const db = new Database(sourcePath);
db.pragma('journal_mode = WAL');
initAutonomySchema(db);
const insert = db.prepare(`
INSERT OR IGNORE INTO autonomy_legacy_records(source_table, source_id, payload)
VALUES (?, ?, ?)
`);
const tx = db.transaction(() => {
for (const table of ['event_predictions', 'trade_signals', 'company_facts', 'company_relationships']) {
const exists = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(table);
if (!exists) continue;
const rows = db.prepare(`SELECT * FROM ${table}`).all();
for (const row of rows) insert.run(table, row.id, JSON.stringify(row));
console.log(`${table}: ${rows.length}`);
}
});
tx();
db.close();
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env node
// Initializes the additive autonomy schema and creates one reconciliation job.
// It deliberately does not rewrite legacy intelligence or enqueue millions of
// historical records; reconciliation workers discover those in bounded batches.
const path = require('path');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const { enqueueJob } = require('../src/autonomy/jobs');
const intelligencePath = process.env.INTELLIGENCE_DB || path.resolve(process.cwd(), 'intelligence.sqlite');
const db = new Database(intelligencePath);
db.pragma('journal_mode = WAL');
initAutonomySchema(db);
const result = enqueueJob(db, {
jobType: 'reconcile_archive',
lane: 'maintenance',
priority: 100,
entityType: 'archive',
entityId: 'archive',
idempotencyKey: 'reconcile_archive:v1',
});
console.log(JSON.stringify({ intelligencePath, reconciliationJobInserted: result.inserted }));
db.close();
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env node
const Database = require('better-sqlite3');
const path = require('path');
const { initAutonomySchema } = require('../src/autonomy/schema');
const symbol = String(process.argv[2] || '').trim().toUpperCase();
if (!/^[A-Z0-9._/-]+$/.test(symbol)) {
console.error('usage: node scripts/set-autonomy-instrument.js SYMBOL [broker]');
process.exit(2);
}
const broker = String(process.argv[3] || 'simulator');
const db = new Database(process.env.INTELLIGENCE_DB || path.resolve(process.cwd(), 'intelligence.sqlite'));
initAutonomySchema(db);
db.prepare(`
INSERT INTO autonomy_instruments(symbol, broker, active, tradable)
VALUES (?, ?, 1, 1)
ON CONFLICT(symbol) DO UPDATE SET broker=excluded.broker, active=1, tradable=1, updated_at=datetime('now')
`).run(symbol, broker);
console.log(JSON.stringify({ symbol, broker, active: true, tradable: true }));
db.close();
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env node
const path = require('path');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const { createAlpacaPaperClient } = require('../src/brokers/alpacaPaper');
async function main() {
const client = createAlpacaPaperClient({
keyId: process.env.ALPACA_PAPER_KEY_ID,
secretKey: process.env.ALPACA_PAPER_SECRET_KEY,
});
const assets = await client.getAssets();
const db = new Database(process.env.INTELLIGENCE_DB || path.resolve(process.cwd(), 'intelligence.sqlite'));
initAutonomySchema(db);
const upsert = db.prepare(`
INSERT INTO autonomy_instruments(symbol, broker, asset_class, active, tradable, shortable, fractionable, updated_at)
VALUES (?, 'alpaca-paper', ?, ?, ?, ?, ?, datetime('now'))
ON CONFLICT(symbol) DO UPDATE SET
broker=excluded.broker, asset_class=excluded.asset_class, active=excluded.active,
tradable=excluded.tradable, shortable=excluded.shortable, fractionable=excluded.fractionable,
updated_at=datetime('now')
`);
const tx = db.transaction(() => assets.forEach((asset) => upsert.run(
asset.symbol, asset.class || 'us_equity', asset.status === 'active' ? 1 : 0,
asset.tradable ? 1 : 0, asset.shortable ? 1 : 0, asset.fractionable ? 1 : 0
)));
tx();
console.log(JSON.stringify({ synced: assets.length }));
db.close();
}
main().catch((error) => { console.error(error.message); process.exit(1); });
+7 -1
View File
@@ -6,6 +6,7 @@ const sourcesRoutes = require('./src/routes/sources');
const eventRoutes = require('./src/routes/events'); const eventRoutes = require('./src/routes/events');
const adminRoutes = require('./src/routes/admin'); const adminRoutes = require('./src/routes/admin');
const devRoutes = require('./src/routes/dev'); const devRoutes = require('./src/routes/dev');
const autonomyRoutes = require('./src/routes/autonomy');
const config = require('./src/config'); const config = require('./src/config');
const { startScheduler } = require('./src/scheduler'); const { startScheduler } = require('./src/scheduler');
@@ -18,13 +19,18 @@ app.register(sourcesRoutes);
app.register(eventRoutes); app.register(eventRoutes);
app.register(adminRoutes); app.register(adminRoutes);
app.register(devRoutes); app.register(devRoutes);
app.register(autonomyRoutes);
app.get('/', async () => ({ ok: true })); app.get('/', async () => ({ ok: true }));
async function start() { async function start() {
await app.listen({ port: config.server.port, host: config.server.host }); await app.listen({ port: config.server.port, host: config.server.host });
startScheduler(); if (process.env.DURIIN_RUN_SCHEDULER !== 'false') {
startScheduler();
} else {
app.log.warn('Background ingestion and enrichment scheduler is disabled');
}
} }
start().catch((error) => { start().catch((error) => {
+39
View File
@@ -0,0 +1,39 @@
function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); }
function betaMean(wins, total, priorWins = 1, priorLosses = 1) {
return (wins + priorWins) / (total + priorWins + priorLosses);
}
function quantile(values, q) {
if (!values.length) return null;
const sorted = [...values].sort((a, b) => a - b);
const position = (sorted.length - 1) * q;
const lower = Math.floor(position);
const upper = Math.ceil(position);
if (lower === upper) return sorted[lower];
return sorted[lower] + (sorted[upper] - sorted[lower]) * (position - lower);
}
function cohortKey({ direction, eventType, horizonDays, sector = 'unknown' }) {
return [sector, eventType || 'unknown', horizonDays, direction].join('|');
}
function calibrateOutcomes(rows, parent = null) {
const clean = rows.filter((row) => Number.isFinite(Number(row.excess_return)));
const wins = clean.filter((row) => Number(row.direction_correct) === 1).length;
const total = clean.length;
const priorProbability = parent ? parent.directionalProbability : 0.5;
const priorStrength = parent ? Math.max(2, Math.min(20, parent.effectiveSampleSize / 10)) : 2;
const probability = (wins + priorProbability * priorStrength) / (total + priorStrength);
const returns = clean.map((row) => Number(row.excess_return));
return {
sampleSize: total,
effectiveSampleSize: total + priorStrength,
directionalProbability: clamp(probability, 0.01, 0.99),
expectedExcessReturn: returns.length ? returns.reduce((sum, value) => sum + value, 0) / returns.length : null,
lowerReturn: quantile(returns, 0.1),
upperReturn: quantile(returns, 0.9),
};
}
module.exports = { betaMean, cohortKey, calibrateOutcomes, quantile };
+90
View File
@@ -0,0 +1,90 @@
const ALLOWED_DIRECTIONS = new Set(['positive', 'negative']);
const ALLOWED_HORIZONS = new Set([1, 5, 10, 20, 30, 60, 90]);
function normalizeProposal(raw, { informationCutoff, model = 'unknown', promptVersion = 'unknown' } = {}) {
if (!raw || typeof raw !== 'object') throw new Error('coordinator output must be an object');
const predictions = Array.isArray(raw.predictions) ? raw.predictions : [];
const normalized = predictions.map((item) => {
const instrument = String(item.instrument || item.ticker || '').trim().toUpperCase();
const direction = String(item.direction || '').trim().toLowerCase();
const horizonDays = Number(item.horizon_days || item.horizonDays);
if (!instrument) throw new Error('prediction instrument is required');
if (!ALLOWED_DIRECTIONS.has(direction)) throw new Error(`invalid direction: ${direction}`);
if (!ALLOWED_HORIZONS.has(horizonDays)) throw new Error(`invalid horizon_days: ${horizonDays}`);
const articleIds = Array.isArray(item.evidence_article_ids)
? item.evidence_article_ids.map(Number).filter(Number.isInteger)
: [];
if (articleIds.length === 0) throw new Error(`prediction for ${instrument} has no evidence`);
return {
instrument,
direction,
eventType: String(item.event_type || 'unknown').trim().toLowerCase(),
causalChannel: item.causal_channel ? String(item.causal_channel).trim() : null,
horizonDays,
evidenceArticleIds: [...new Set(articleIds)],
invalidationCondition: item.invalidation_condition ? String(item.invalidation_condition).trim() : null,
};
});
return {
schemaVersion: 1,
informationCutoff: informationCutoff || new Date().toISOString(),
coordinatorModel: model,
promptVersion,
predictions: normalized,
};
}
function verifyEvidence(archiveDb, articleIds) {
const placeholders = articleIds.map(() => '?').join(',');
const rows = archiveDb.prepare(`SELECT id FROM articles WHERE id IN (${placeholders})`).all(...articleIds);
const found = new Set(rows.map((row) => row.id));
return articleIds.every((id) => found.has(id));
}
function acceptProposal(intelligenceDb, archiveDb, raw, metadata = {}) {
const proposal = normalizeProposal(raw, metadata);
for (const prediction of proposal.predictions) {
if (!verifyEvidence(archiveDb, prediction.evidenceArticleIds)) {
throw new Error(`proposal references missing evidence for ${prediction.instrument}`);
}
const instrument = intelligenceDb.prepare(
"SELECT tradable FROM autonomy_instruments WHERE symbol = ? AND active = 1 AND tradable = 1"
).get(prediction.instrument);
if (!instrument) throw new Error(`instrument is not currently allowlisted: ${prediction.instrument}`);
}
const insert = intelligenceDb.prepare(`
INSERT INTO autonomy_proposals
(event_id, payload, information_cutoff, coordinator_model, prompt_version, status)
VALUES (?, ?, ?, ?, ?, 'accepted')
`);
const insertPrediction = intelligenceDb.prepare(`
INSERT INTO autonomy_predictions
(proposal_id, event_id, instrument, direction, event_type, causal_channel,
horizon_days, information_cutoff, evidence_article_ids, invalidation_condition, learning_eligible, strategy_version)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
const tx = intelligenceDb.transaction(() => {
const proposalResult = insert.run(metadata.eventId || null, JSON.stringify(proposal), proposal.informationCutoff,
proposal.coordinatorModel, proposal.promptVersion);
for (const prediction of proposal.predictions) {
insertPrediction.run(proposalResult.lastInsertRowid, metadata.eventId || null, prediction.instrument,
prediction.direction, prediction.eventType, prediction.causalChannel, prediction.horizonDays,
proposal.informationCutoff, JSON.stringify(prediction.evidenceArticleIds), prediction.invalidationCondition,
metadata.learningEligible ? 1 : 0, metadata.strategyVersion || 'autonomy-1');
}
return Number(proposalResult.lastInsertRowid);
});
return { proposalId: tx(), predictionCount: proposal.predictions.length };
}
function recordRejectedProposal(intelligenceDb, raw, metadata = {}, reason = 'validation failed') {
const payload = raw && typeof raw === 'object' ? raw : { raw: String(raw) };
return intelligenceDb.prepare(`
INSERT INTO autonomy_proposals
(event_id, payload, information_cutoff, coordinator_model, prompt_version, status, rejection_reason, reviewed_at)
VALUES (?, ?, ?, ?, ?, 'rejected', ?, datetime('now'))
`).run(metadata.eventId || null, JSON.stringify(payload), metadata.informationCutoff || new Date().toISOString(),
metadata.model || 'unknown', metadata.promptVersion || 'unknown', String(reason).slice(0, 1000)).lastInsertRowid;
}
module.exports = { normalizeProposal, verifyEvidence, acceptProposal, recordRejectedProposal };
+34
View File
@@ -0,0 +1,34 @@
function makeClientOrderId(decisionId) {
return `duriin-${String(decisionId)}`;
}
function validatePaperIntent(intent, constraints = {}) {
if (!intent || !intent.decisionId || !intent.instrument) throw new Error('decisionId and instrument are required');
if (!['BUY', 'SELL'].includes(intent.action)) throw new Error('only BUY and SELL create order intents');
if (!Number.isFinite(Number(intent.notional)) || Number(intent.notional) <= 0) throw new Error('notional must be positive');
const maxNotional = Number(constraints.maxNotional ?? 1000);
if (Number(intent.notional) > maxNotional) throw new Error('notional exceeds paper risk limit');
if (constraints.tradable !== true) throw new Error('instrument is not confirmed tradable');
return {
clientOrderId: makeClientOrderId(intent.decisionId),
instrument: String(intent.instrument).toUpperCase(),
side: intent.action === 'BUY' ? 'buy' : 'sell',
notional: Number(intent.notional),
mode: 'paper',
};
}
function createSimulator() {
const orders = new Map();
return {
submit(intent) {
if (orders.has(intent.clientOrderId)) return orders.get(intent.clientOrderId);
const order = { ...intent, brokerOrderId: `sim-${intent.clientOrderId}`, status: 'accepted' };
orders.set(intent.clientOrderId, order);
return order;
},
get(clientOrderId) { return orders.get(clientOrderId) || null; },
};
}
module.exports = { makeClientOrderId, validatePaperIntent, createSimulator };
+17
View File
@@ -0,0 +1,17 @@
const { initAutonomySchema } = require('./schema');
const jobs = require('./jobs');
const coordinator = require('./coordinator');
const calibration = require('./calibration');
const policy = require('./policy');
const execution = require('./execution');
const orderIntents = require('./orderIntents');
module.exports = {
initAutonomySchema,
...jobs,
...coordinator,
...calibration,
...policy,
...execution,
...orderIntents,
};
+56
View File
@@ -0,0 +1,56 @@
function enqueueJob(db, { jobType, lane = 'historical', priority = 0, entityType, entityId, idempotencyKey }) {
const result = db.prepare(`
INSERT OR IGNORE INTO autonomy_jobs
(job_type, lane, priority, entity_type, entity_id, idempotency_key)
VALUES (?, ?, ?, ?, ?, ?)
`).run(jobType, lane, priority, entityType, String(entityId), idempotencyKey);
return { inserted: result.changes > 0 };
}
function leaseNextJob(db, workerId, leaseSeconds = 60, jobTypes = null) {
const tx = db.transaction(() => {
const typeClause = Array.isArray(jobTypes) && jobTypes.length
? `AND job_type IN (${jobTypes.map(() => '?').join(',')})`
: '';
const typeParams = Array.isArray(jobTypes) && jobTypes.length ? jobTypes : [];
const job = db.prepare(`
SELECT * FROM autonomy_jobs
WHERE ((status = 'pending' AND datetime(available_at) <= datetime('now'))
OR (status = 'leased' AND datetime(lease_expires_at) <= datetime('now')))
${typeClause}
ORDER BY CASE lane WHEN 'live' THEN 3 WHEN 'maintenance' THEN 2 ELSE 1 END DESC,
priority DESC, id ASC
LIMIT 1
`).get(...typeParams);
if (!job) return null;
const updated = db.prepare(`
UPDATE autonomy_jobs
SET status = 'leased', leased_by = ?, lease_expires_at = datetime('now', ?),
attempts = attempts + 1
WHERE id = ?
`).run(workerId, `+${Math.max(1, Math.floor(leaseSeconds))} seconds`, job.id);
return updated.changes ? { ...job, status: 'leased', leased_by: workerId } : null;
});
return tx();
}
function completeJob(db, id, workerId) {
return db.prepare(`
UPDATE autonomy_jobs
SET status = 'complete', completed_at = datetime('now'),
leased_by = NULL, lease_expires_at = NULL
WHERE id = ? AND leased_by = ?
`).run(id, workerId).changes > 0;
}
function failJob(db, id, workerId, error, maxAttempts = 5) {
return db.prepare(`
UPDATE autonomy_jobs
SET status = CASE WHEN attempts >= ? THEN 'dead_letter' ELSE 'pending' END,
available_at = datetime('now', '+60 seconds'), last_error = ?,
leased_by = NULL, lease_expires_at = NULL
WHERE id = ? AND leased_by = ?
`).run(maxAttempts, String(error || 'unknown error').slice(0, 2000), id, workerId).changes > 0;
}
module.exports = { enqueueJob, leaseNextJob, completeJob, failJob };
+32
View File
@@ -0,0 +1,32 @@
function extractJson(text) {
const value = String(text || '').trim().replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/, '');
try { return JSON.parse(value); } catch (_) {
const start = value.indexOf('{');
const end = value.lastIndexOf('}');
if (start >= 0 && end > start) return JSON.parse(value.slice(start, end + 1));
throw new Error('LLM response did not contain valid JSON');
}
}
async function callCoordinator(config, prompt) {
const apiKey = String(config?.openRouter?.apiKey || '').trim();
if (!apiKey) throw new Error('OpenRouter API key is not configured');
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
model: config.openRouter.llmModel,
temperature: 0,
response_format: { type: 'json_object' },
messages: [
{ role: 'system', content: 'You are a coordinator. Extract only evidence-backed categorical hypotheses. Never output probabilities, expected returns, confidence scores, position sizes, or trade actions.' },
{ role: 'user', content: prompt },
],
}),
});
if (!response.ok) throw new Error(`coordinator request failed with ${response.status}`);
const body = await response.json();
return extractJson(body?.choices?.[0]?.message?.content);
}
module.exports = { extractJson, callCoordinator };
+25
View File
@@ -0,0 +1,25 @@
const { validatePaperIntent } = require('./execution');
function createOrderIntent(db, decisionId, notional, constraints = {}) {
const row = db.prepare(`
SELECT d.id AS decision_id, d.action, p.instrument,
COALESCE(ai.active, 0) AS active, COALESCE(ai.tradable, 0) AS tradable
FROM autonomy_decisions d
JOIN autonomy_predictions p ON p.id = d.prediction_id
LEFT JOIN autonomy_instruments ai ON ai.symbol = p.instrument
WHERE d.id = ?
`).get(decisionId);
if (!row) throw new Error(`decision ${decisionId} does not exist`);
const intent = validatePaperIntent({ decisionId, instrument: row.instrument, action: row.action, notional }, {
...constraints,
tradable: row.active === 1 && row.tradable === 1,
});
const result = db.prepare(`
INSERT OR IGNORE INTO autonomy_order_intents
(decision_id, client_order_id, instrument, side, notional, status)
VALUES (?, ?, ?, ?, ?, 'shadow')
`).run(decisionId, intent.clientOrderId, intent.instrument, intent.side, intent.notional);
return { ...intent, inserted: result.changes > 0 };
}
module.exports = { createOrderIntent };
+35
View File
@@ -0,0 +1,35 @@
function addTradingDays(date, days) {
const value = new Date(`${date}T00:00:00Z`);
let remaining = Math.max(0, Number(days) || 0);
while (remaining > 0) {
value.setUTCDate(value.getUTCDate() + 1);
const weekday = value.getUTCDay();
if (weekday !== 0 && weekday !== 6) remaining -= 1;
}
return value.toISOString().slice(0, 10);
}
function nearestOnOrAfter(history, date) {
return history.find((row) => row.date >= date)?.close ?? null;
}
function calculateOutcome(prediction, instrumentHistory, benchmarkHistory) {
const eventDate = String(prediction.information_cutoff).slice(0, 10);
const horizonDate = addTradingDays(eventDate, prediction.horizon_days);
const price0 = nearestOnOrAfter(instrumentHistory, eventDate);
const priceHorizon = nearestOnOrAfter(instrumentHistory, horizonDate);
const benchmark0 = nearestOnOrAfter(benchmarkHistory, eventDate);
const benchmarkHorizon = nearestOnOrAfter(benchmarkHistory, horizonDate);
if (![price0, priceHorizon, benchmark0, benchmarkHorizon].every(Number.isFinite)) return null;
const instrumentReturn = (priceHorizon - price0) / price0;
const benchmarkReturn = (benchmarkHorizon - benchmark0) / benchmark0;
const excessReturn = instrumentReturn - benchmarkReturn;
const directionCorrect = prediction.direction === 'positive' ? excessReturn > 0 : excessReturn < 0;
return {
price0, priceHorizon, benchmark0, benchmarkHorizon,
excessReturn, directionCorrect: directionCorrect ? 1 : 0,
eventDate, horizonDate,
};
}
module.exports = { addTradingDays, nearestOnOrAfter, calculateOutcome };
+26
View File
@@ -0,0 +1,26 @@
function decide({ direction = 'positive', probability, expectedExcessReturn, lowerReturn, upperReturn, sampleSize }, rules = {}) {
const minSampleSize = Number(rules.minSampleSize ?? 30);
const minProbability = Number(rules.minProbability ?? 0.58);
const minExpectedReturn = Number(rules.minExpectedReturn ?? 0.005);
const maxDownside = Number(rules.maxDownside ?? -0.08);
if (![probability, expectedExcessReturn].every(Number.isFinite)) {
return { action: 'ABSTAIN', rationale: 'calibration unavailable' };
}
if (sampleSize < minSampleSize) {
return { action: 'ABSTAIN', rationale: `insufficient calibration sample (${sampleSize}/${minSampleSize})` };
}
const signedExpectedReturn = direction === 'negative' ? -expectedExcessReturn : expectedExcessReturn;
const signedLowerReturn = direction === 'negative'
? (Number.isFinite(upperReturn) ? -upperReturn : null)
: (Number.isFinite(lowerReturn) ? lowerReturn : null);
if (Number.isFinite(signedLowerReturn) && signedLowerReturn < maxDownside) {
return { action: 'HOLD', rationale: 'calibrated downside exceeds policy limit' };
}
if (probability >= minProbability && signedExpectedReturn >= minExpectedReturn) {
return { action: direction === 'negative' ? 'SELL' : 'BUY', rationale: 'calibrated edge clears policy thresholds' };
}
return { action: 'HOLD', rationale: 'calibrated edge does not clear policy thresholds' };
}
module.exports = { decide };
+192
View File
@@ -0,0 +1,192 @@
const AUTONOMY_SCHEMA_VERSION = 1;
function initAutonomySchema(db) {
db.exec(`
CREATE TABLE IF NOT EXISTS autonomy_schema (
version INTEGER PRIMARY KEY,
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_jobs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_type TEXT NOT NULL,
lane TEXT NOT NULL CHECK (lane IN ('live', 'historical', 'maintenance')),
priority INTEGER NOT NULL DEFAULT 0,
entity_type TEXT NOT NULL,
entity_id TEXT NOT NULL,
idempotency_key TEXT NOT NULL UNIQUE,
status TEXT NOT NULL DEFAULT 'pending'
CHECK (status IN ('pending', 'leased', 'complete', 'failed', 'dead_letter')),
attempts INTEGER NOT NULL DEFAULT 0,
available_at TEXT NOT NULL DEFAULT (datetime('now')),
leased_by TEXT,
lease_expires_at TEXT,
last_error TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
completed_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_autonomy_jobs_claim
ON autonomy_jobs(status, lane, priority DESC, available_at);
CREATE TABLE IF NOT EXISTS autonomy_cursors (
key TEXT PRIMARY KEY,
value INTEGER NOT NULL DEFAULT 0,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_proposals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_id INTEGER,
payload TEXT NOT NULL,
information_cutoff TEXT NOT NULL,
coordinator_model TEXT,
prompt_version TEXT,
status TEXT NOT NULL DEFAULT 'candidate'
CHECK (status IN ('candidate', 'accepted', 'rejected', 'superseded')),
rejection_reason TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
reviewed_at TEXT
);
CREATE TABLE IF NOT EXISTS autonomy_instruments (
symbol TEXT PRIMARY KEY,
broker TEXT NOT NULL,
asset_class TEXT NOT NULL DEFAULT 'us_equity',
active INTEGER NOT NULL DEFAULT 0,
tradable INTEGER NOT NULL DEFAULT 0,
shortable INTEGER NOT NULL DEFAULT 0,
fractionable INTEGER NOT NULL DEFAULT 0,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_legacy_records (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source_table TEXT NOT NULL,
source_id INTEGER NOT NULL,
payload TEXT NOT NULL,
calibration_eligible INTEGER NOT NULL DEFAULT 0,
imported_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(source_table, source_id)
);
CREATE TABLE IF NOT EXISTS autonomy_predictions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
proposal_id INTEGER NOT NULL REFERENCES autonomy_proposals(id),
event_id INTEGER,
instrument TEXT NOT NULL,
direction TEXT NOT NULL CHECK (direction IN ('positive', 'negative')),
event_type TEXT NOT NULL,
causal_channel TEXT,
horizon_days INTEGER NOT NULL,
information_cutoff TEXT NOT NULL,
evidence_article_ids TEXT NOT NULL,
invalidation_condition TEXT,
learning_eligible INTEGER NOT NULL DEFAULT 0,
strategy_version TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'open'
CHECK (status IN ('open', 'resolved', 'unresolvable', 'invalidated')),
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_autonomy_predictions_resolution
ON autonomy_predictions(status, information_cutoff, instrument);
CREATE TABLE IF NOT EXISTS autonomy_outcomes (
prediction_id INTEGER PRIMARY KEY REFERENCES autonomy_predictions(id),
price_0 REAL,
price_horizon REAL,
benchmark_0 REAL,
benchmark_horizon REAL,
excess_return REAL,
direction_correct INTEGER,
error_type TEXT,
evaluated_at TEXT NOT NULL DEFAULT (datetime('now')),
notes TEXT
);
CREATE TABLE IF NOT EXISTS autonomy_calibration_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cohort_key TEXT NOT NULL,
sample_size INTEGER NOT NULL,
effective_sample_size REAL NOT NULL,
directional_probability REAL NOT NULL,
expected_excess_return REAL,
lower_return REAL,
upper_return REAL,
parent_cohort_key TEXT,
version TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_autonomy_calibration_lookup
ON autonomy_calibration_snapshots(cohort_key, created_at DESC);
CREATE TABLE IF NOT EXISTS autonomy_decisions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
prediction_id INTEGER NOT NULL REFERENCES autonomy_predictions(id),
action TEXT NOT NULL CHECK (action IN ('BUY', 'SELL', 'HOLD', 'ABSTAIN')),
calibrated_probability REAL,
expected_excess_return REAL,
rationale TEXT NOT NULL,
strategy_version TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_order_intents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
decision_id INTEGER NOT NULL REFERENCES autonomy_decisions(id),
client_order_id TEXT NOT NULL UNIQUE,
instrument TEXT NOT NULL,
side TEXT NOT NULL CHECK (side IN ('buy', 'sell')),
notional REAL NOT NULL CHECK (notional > 0),
status TEXT NOT NULL DEFAULT 'shadow'
CHECK (status IN ('shadow', 'pending', 'submitted', 'filled', 'partially_filled', 'rejected', 'cancelled')),
broker_order_id TEXT,
attempts INTEGER NOT NULL DEFAULT 0,
last_error TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_broker_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
broker TEXT NOT NULL,
event_type TEXT NOT NULL,
broker_id TEXT,
payload TEXT NOT NULL,
occurred_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(broker, event_type, broker_id, occurred_at)
);
CREATE TABLE IF NOT EXISTS autonomy_account_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
broker TEXT NOT NULL,
account_id TEXT,
equity REAL,
cash REAL,
buying_power REAL,
payload TEXT NOT NULL,
captured_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_position_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
broker TEXT NOT NULL,
instrument TEXT NOT NULL,
quantity REAL,
market_value REAL,
unrealized_pl REAL,
payload TEXT NOT NULL,
captured_at TEXT NOT NULL DEFAULT (datetime('now'))
);
INSERT OR IGNORE INTO autonomy_schema(version) VALUES (${AUTONOMY_SCHEMA_VERSION});
`);
for (const statement of [
'ALTER TABLE autonomy_order_intents ADD COLUMN attempts INTEGER NOT NULL DEFAULT 0',
'ALTER TABLE autonomy_order_intents ADD COLUMN last_error TEXT',
'ALTER TABLE autonomy_predictions ADD COLUMN learning_eligible INTEGER NOT NULL DEFAULT 0',
]) {
try { db.exec(statement); } catch (_) {}
}
}
module.exports = { AUTONOMY_SCHEMA_VERSION, initAutonomySchema };
+36
View File
@@ -0,0 +1,36 @@
const PAPER_BASE_URL = 'https://paper-api.alpaca.markets';
function createAlpacaPaperClient({ keyId, secretKey } = {}) {
if (!keyId || !secretKey) throw new Error('Alpaca paper credentials are required');
async function request(path, options = {}) {
const response = await fetch(`${PAPER_BASE_URL}${path}`, {
...options,
headers: {
'APCA-API-KEY-ID': keyId,
'APCA-API-SECRET-KEY': secretKey,
'Content-Type': 'application/json',
...(options.headers || {}),
},
});
const text = await response.text();
let body = null;
try { body = text ? JSON.parse(text) : null; } catch (_) { body = { raw: text }; }
if (!response.ok) {
const error = new Error(body?.message || `Alpaca paper API returned ${response.status}`);
error.status = response.status;
error.body = body;
throw error;
}
return body;
}
return {
getAccount: () => request('/v2/account'),
getAssets: () => request('/v2/assets?status=active&asset_class=us_equity'),
getOrders: () => request('/v2/orders?status=all&limit=500&direction=desc'),
getPositions: () => request('/v2/positions'),
getOrderByClientId: (clientOrderId) => request(`/v2/orders:by_client_order_id?client_order_id=${encodeURIComponent(clientOrderId)}`),
submitOrder: (order) => request('/v2/orders', { method: 'POST', body: JSON.stringify(order) }),
};
}
module.exports = { PAPER_BASE_URL, createAlpacaPaperClient };
+7 -1
View File
@@ -48,6 +48,12 @@ db.exec(`
CREATE INDEX IF NOT EXISTS idx_articles_event_id ON articles(event_id); CREATE INDEX IF NOT EXISTS idx_articles_event_id ON articles(event_id);
CREATE INDEX IF NOT EXISTS idx_articles_has_embedding ON articles(has_embedding); CREATE INDEX IF NOT EXISTS idx_articles_has_embedding ON articles(has_embedding);
CREATE INDEX IF NOT EXISTS idx_articles_pub_date_effective ON articles(pub_date_effective DESC); CREATE INDEX IF NOT EXISTS idx_articles_pub_date_effective ON articles(pub_date_effective DESC);
CREATE INDEX IF NOT EXISTS idx_articles_usable_pub_date
ON articles(pub_date_effective DESC, id DESC)
WHERE content IS NOT NULL
AND content != ''
AND is_index_page = 0
AND has_embedding = 1;
`); `);
db.exec(` db.exec(`
@@ -149,4 +155,4 @@ db.exec(`
); );
`); `);
module.exports = db; module.exports = db;
+1 -1
View File
@@ -60,7 +60,7 @@ function buildArticlesQuery(query) {
return { return {
sql: ` sql: `
SELECT id, title, description, content, ${includeEmbedding ? 'embedding,' : ''} url, normalized_title, source, pub_date, ingested_at SELECT id, title, description, content, ${includeEmbedding ? 'embedding,' : ''} url, normalized_title, source, pub_date, ingested_at
FROM articles FROM articles INDEXED BY idx_articles_usable_pub_date
${whereClause} ${whereClause}
ORDER BY ${orderBy} ORDER BY ${orderBy}
LIMIT ? OFFSET ? LIMIT ? OFFSET ?
+43
View File
@@ -0,0 +1,43 @@
const path = require('path');
const Database = require('better-sqlite3');
const intelligencePath = process.env.INTELLIGENCE_DB || path.resolve(process.cwd(), 'intelligence.sqlite');
const db = new Database(intelligencePath, { readonly: true });
async function autonomyRoutes(fastify) {
fastify.get('/health', async () => ({ ok: true, service: 'duriin-api' }));
fastify.get('/autonomy/status', async () => {
const exists = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='autonomy_jobs'").get();
if (!exists) return { enabled: false, reason: 'autonomy schema is not initialized' };
const jobs = db.prepare(`
SELECT lane, status, COUNT(*) AS count
FROM autonomy_jobs
GROUP BY lane, status
ORDER BY lane, status
`).all();
const predictions = db.prepare(`
SELECT status, COUNT(*) AS count
FROM autonomy_predictions
GROUP BY status
ORDER BY status
`).all();
const decisions = db.prepare(`
SELECT action, COUNT(*) AS count
FROM autonomy_decisions
GROUP BY action
ORDER BY action
`).all();
const outcomes = db.prepare(`
SELECT COUNT(*) AS total,
SUM(direction_correct) AS correct,
AVG(excess_return) AS average_excess_return
FROM autonomy_outcomes
`).get();
const legacy = db.prepare('SELECT COUNT(*) AS count FROM autonomy_legacy_records').get();
const instruments = db.prepare('SELECT COUNT(*) AS count FROM autonomy_instruments WHERE active=1 AND tradable=1').get();
return { enabled: true, jobs, predictions, decisions, outcomes, legacyRecords: legacy.count, allowlistedInstruments: instruments.count };
});
}
module.exports = autonomyRoutes;
+14 -1
View File
@@ -6,7 +6,20 @@ let statusCacheAt = 0;
const STATUS_CACHE_TTL_MS = 30 * 1000; const STATUS_CACHE_TTL_MS = 30 * 1000;
async function statusRoutes(fastify) { async function statusRoutes(fastify) {
fastify.get('/status', async () => { fastify.get('/status', async (request) => {
const deep = String(request.query?.deep || '').toLowerCase() === 'true';
if (!deep) {
const sequence = db.prepare("SELECT seq FROM sqlite_sequence WHERE name = 'articles'").get();
return {
total: sequence ? sequence.seq : 0,
usable: null,
lastIngestionBySource: getLastIngestionBySource(),
bySource: null,
embeddingModels: null,
mode: 'lightweight',
deep_status_url: '/status?deep=true',
};
}
const now = Date.now(); const now = Date.now();
if (statusCache && now - statusCacheAt < STATUS_CACHE_TTL_MS) { if (statusCache && now - statusCacheAt < STATUS_CACHE_TTL_MS) {
return statusCache; return statusCache;
+111
View File
@@ -0,0 +1,111 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const { enqueueJob, leaseNextJob, completeJob } = require('../src/autonomy/jobs');
const { normalizeProposal, acceptProposal } = require('../src/autonomy/coordinator');
const { calibrateOutcomes, cohortKey } = require('../src/autonomy/calibration');
const { decide } = require('../src/autonomy/policy');
const { validatePaperIntent, createSimulator } = require('../src/autonomy/execution');
const { calculateOutcome } = require('../src/autonomy/outcomes');
const { createOrderIntent } = require('../src/autonomy/orderIntents');
const { reconcileArchiveBatch, reconcileLiveBatch } = require('../workers/autonomyWorker');
test('autonomy schema and leased jobs are restart-safe', () => {
const db = new Database(':memory:');
initAutonomySchema(db);
assert.equal(enqueueJob(db, {
jobType: 'enrich', lane: 'live', priority: 10, entityType: 'article', entityId: 42,
idempotencyKey: 'enrich:42',
}).inserted, true);
assert.equal(enqueueJob(db, {
jobType: 'enrich', lane: 'live', priority: 10, entityType: 'article', entityId: 42,
idempotencyKey: 'enrich:42',
}).inserted, false);
const job = leaseNextJob(db, 'test-worker');
assert.equal(job.lane, 'live');
assert.equal(completeJob(db, job.id, 'test-worker'), true);
assert.equal(db.prepare("SELECT status FROM autonomy_jobs WHERE id = ?").get(job.id).status, 'complete');
});
test('coordinator proposals require evidence and contain no arbitrary numeric confidence', () => {
const normalized = normalizeProposal({ predictions: [{
instrument: 'nvda', direction: 'positive', event_type: 'supply_constraint',
horizon_days: 10, evidence_article_ids: [7],
}] }, { informationCutoff: '2026-01-01T00:00:00Z', model: 'test-model' });
assert.equal(normalized.predictions[0].instrument, 'NVDA');
assert.equal('probability' in normalized.predictions[0], false);
assert.throws(() => normalizeProposal({ predictions: [{ instrument: 'NVDA', direction: 'positive', horizon_days: 10 }] }));
});
test('accepted proposal preserves evidence and creates immutable prediction', () => {
const archive = new Database(':memory:');
archive.exec('CREATE TABLE articles (id INTEGER PRIMARY KEY)');
archive.prepare('INSERT INTO articles (id) VALUES (?)').run(7);
const intelligence = new Database(':memory:');
initAutonomySchema(intelligence);
intelligence.prepare("INSERT INTO autonomy_instruments(symbol, broker, active, tradable) VALUES ('NVDA', 'test', 1, 1)").run();
const result = acceptProposal(intelligence, archive, {
predictions: [{ instrument: 'NVDA', direction: 'positive', event_type: 'earnings', horizon_days: 10, evidence_article_ids: [7] }],
}, { informationCutoff: '2026-01-01T00:00:00Z', strategyVersion: 'test' });
assert.equal(result.predictionCount, 1);
assert.deepEqual(JSON.parse(intelligence.prepare('SELECT evidence_article_ids FROM autonomy_predictions').get().evidence_article_ids), [7]);
});
test('calibration and policy abstain on insufficient evidence', () => {
const calibration = calibrateOutcomes([
{ excess_return: 0.02, direction_correct: 1 },
{ excess_return: -0.01, direction_correct: 0 },
]);
assert.equal(calibration.sampleSize, 2);
const result = decide({ ...calibration }, { minSampleSize: 30 });
assert.equal(result.action, 'ABSTAIN');
assert.equal(cohortKey({ sector: 'tech', eventType: 'earnings', horizonDays: 10, direction: 'positive' }), 'tech|earnings|10|positive');
assert.equal(decide({ direction: 'negative', probability: 0.8, expectedExcessReturn: -0.02, lowerReturn: -0.04, sampleSize: 40 }).action, 'SELL');
});
test('paper execution is allowlisted, bounded and idempotent', () => {
const intent = validatePaperIntent({ decisionId: 12, instrument: 'NVDA', action: 'BUY', notional: 100 }, { tradable: true, maxNotional: 500 });
const broker = createSimulator();
assert.deepEqual(broker.submit(intent), broker.submit(intent));
assert.throws(() => validatePaperIntent({ decisionId: 13, instrument: 'PRIVATE', action: 'BUY', notional: 100 }, { tradable: false }));
assert.throws(() => validatePaperIntent({ decisionId: 14, instrument: 'NVDA', action: 'BUY', notional: 501 }, { tradable: true, maxNotional: 500 }));
});
test('archive reconciliation prioritizes recent usable events and is bounded', () => {
const archive = new Database(':memory:');
archive.exec('CREATE TABLE articles (id INTEGER PRIMARY KEY, event_id INTEGER, ingested_at TEXT, content TEXT, has_embedding INTEGER)');
archive.prepare('INSERT INTO articles VALUES (1, 99, ?, ?, 1)').run(new Date().toISOString(), 'content');
const intelligence = new Database(':memory:');
initAutonomySchema(intelligence);
const result = reconcileArchiveBatch(archive, intelligence, 1);
assert.equal(result.scanned, 1);
const job = intelligence.prepare("SELECT lane, priority FROM autonomy_jobs WHERE job_type='coordinator_event'").get();
assert.equal(job.lane, 'live');
assert.equal(job.priority, 100);
const live = reconcileLiveBatch(archive, intelligence, 1);
assert.equal(live.scanned, 1);
});
test('outcome calculation uses benchmark-relative return', () => {
const outcome = calculateOutcome(
{ information_cutoff: '2026-01-02T00:00:00Z', horizon_days: 5, direction: 'positive' },
[{ date: '2026-01-02', close: 100 }, { date: '2026-01-09', close: 110 }],
[{ date: '2026-01-02', close: 100 }, { date: '2026-01-09', close: 105 }]
);
assert.equal(outcome.directionCorrect, 1);
assert.equal(outcome.excessReturn, 0.05);
});
test('order intents require the explicit instrument allowlist', () => {
const db = new Database(':memory:');
initAutonomySchema(db);
db.prepare("INSERT INTO autonomy_instruments(symbol, broker, active, tradable) VALUES ('NVDA', 'sim', 1, 1)").run();
const proposal = db.prepare(`INSERT INTO autonomy_proposals(payload, information_cutoff, status) VALUES ('{}', datetime('now'), 'accepted')`).run();
const prediction = db.prepare(`INSERT INTO autonomy_predictions(proposal_id, instrument, direction, event_type, horizon_days, information_cutoff, evidence_article_ids, learning_eligible, strategy_version) VALUES (?, 'NVDA', 'positive', 'test', 10, datetime('now'), '[1]', 1, 'test')`).run(proposal.lastInsertRowid);
const decision = db.prepare(`INSERT INTO autonomy_decisions(prediction_id, action, rationale, strategy_version) VALUES (?, 'BUY', 'test', 'test')`).run(prediction.lastInsertRowid);
const intent = createOrderIntent(db, decision.lastInsertRowid, 100, { maxNotional: 100 });
assert.equal(intent.side, 'buy');
assert.equal(db.prepare('SELECT status FROM autonomy_order_intents').get().status, 'shadow');
});
+111 -12
View File
@@ -2,6 +2,11 @@ const https = require("https");
const http = require("http"); const http = require("http");
const { findMatchedCompaniesByEmbedding } = require("./embeddings"); const { findMatchedCompaniesByEmbedding } = require("./embeddings");
const { getPriceContext, formatPriceContext } = require("./priceContext");
const REPROCESS_MIN_NEW_ARTICLES = 3;
const REPROCESS_COOLDOWN_HOURS = 6;
async function runAugorWorker(archiveDb, intelligenceDb, config) { async function runAugorWorker(archiveDb, intelligenceDb, config) {
const loopDelay = config.workers?.augorLoopDelayMs ?? 1500; const loopDelay = config.workers?.augorLoopDelayMs ?? 1500;
@@ -11,6 +16,26 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
SELECT * FROM article_queue WHERE status = 'pending' LIMIT 1 SELECT * FROM article_queue WHERE status = 'pending' LIMIT 1
`); `);
const getProcessingState = intelligenceDb.prepare(
"SELECT last_processed_at, articles_at_last_run FROM event_processing_state WHERE event_id = ?"
);
const upsertProcessingState = intelligenceDb.prepare(`
INSERT INTO event_processing_state (event_id, last_processed_at, articles_at_last_run)
VALUES (?, CURRENT_TIMESTAMP, ?)
ON CONFLICT(event_id) DO UPDATE SET
last_processed_at = CURRENT_TIMESTAMP,
articles_at_last_run = excluded.articles_at_last_run
`);
const getCompanyAccuracy = intelligenceDb.prepare(`
SELECT
COUNT(*) as total,
SUM(correct_10d) as correct
FROM prediction_outcomes
WHERE company_id = ? AND correct_10d IS NOT NULL
`);
const recordEvent = intelligenceDb.prepare( const recordEvent = intelligenceDb.prepare(
`INSERT INTO worker_events (worker) VALUES ('augor')` `INSERT INTO worker_events (worker) VALUES ('augor')`
); );
@@ -45,8 +70,8 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
VALUES (?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)
`); `);
const insertPrediction = intelligenceDb.prepare(` const insertPrediction = intelligenceDb.prepare(`
INSERT INTO event_predictions (event_id, company_id, type, direction, magnitude, timeframe, rationale, event_date) INSERT INTO event_predictions (event_id, company_id, type, direction, magnitude, timeframe, rationale, probability, event_date)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`); `);
const getEventDate = archiveDb.prepare(` const getEventDate = archiveDb.prepare(`
@@ -66,7 +91,6 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
const queueRow = getPending.get(); const queueRow = getPending.get();
if (!queueRow) { if (!queueRow) {
await sleep(loopDelay);
continue; continue;
} }
@@ -98,12 +122,29 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
const eventArticleIds = eventArticles.map(a => a.id); const eventArticleIds = eventArticles.map(a => a.id);
// event-level batching guard — skip re-processing if we already ran on this event recently
// and not enough new articles have arrived to justify another LLM call
const state = getProcessingState.get(eventId);
if (state && state.last_processed_at) {
const newArticles = eventArticles.length - state.articles_at_last_run;
const lastRunMs = new Date(state.last_processed_at + "Z").getTime();
const hoursSince = (Date.now() - lastRunMs) / 3_600_000;
if (newArticles < REPROCESS_MIN_NEW_ARTICLES && hoursSince < REPROCESS_COOLDOWN_HOURS) {
for (const r of getEventArticleIds.all(eventId)) setStatusByArticleId.run(r.id);
console.log(`[augor] event ${eventId} — only ${newArticles} new articles in ${hoursSince.toFixed(1)}h, skipping re-process`);
continue;
}
}
const matchedCompanies = findMatchedCompaniesByEmbedding( const matchedCompanies = findMatchedCompaniesByEmbedding(
eventArticleIds, archiveDb, intelligenceDb, config eventArticleIds, archiveDb, intelligenceDb, config
); );
if (matchedCompanies.length === 0) { if (matchedCompanies.length === 0) {
for (const r of getEventArticleIds.all(eventId)) setStatusByArticleId.run(r.id); for (const r of getEventArticleIds.all(eventId)) setStatusByArticleId.run(r.id);
upsertProcessingState.run(eventId, eventArticles.length);
console.log(`[augor] event ${eventId} — no company match, skipped`); console.log(`[augor] event ${eventId} — no company match, skipped`);
continue; continue;
} }
@@ -114,6 +155,7 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
const eventDateRow = getEventDate.get(eventId); const eventDateRow = getEventDate.get(eventId);
const eventDate = eventDateRow ? eventDateRow.pub_date_effective : null; const eventDate = eventDateRow ? eventDateRow.pub_date_effective : null;
const eventDateOnly = eventDate ? eventDate.slice(0, 10) : null;
const articleText = eventArticles.map((a, i) => { const articleText = eventArticles.map((a, i) => {
const body = (a.content || a.description || "").slice(0, 2000); const body = (a.content || a.description || "").slice(0, 2000);
@@ -130,9 +172,30 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
factsBlock = `Known facts about ${company.name}:\n${lines}`; factsBlock = `Known facts about ${company.name}:\n${lines}`;
} }
const result = await callLlm(llmConfig, buildPrompt(company.name, event.title, articleText, factsBlock));
// pull live market context for the company at the time of the event
let priceBlock = null;
if (company.ticker && eventDateOnly) {
try {
const snapshot = await getPriceContext(intelligenceDb, company.ticker, eventDateOnly);
priceBlock = formatPriceContext(snapshot, company.ticker);
} catch (_) {}
}
// historical accuracy of past predictions for this company
let accuracyBlock = null;
const acc = getCompanyAccuracy.get(company.id);
if (acc && acc.total >= 5) {
const pct = (acc.correct / acc.total * 100).toFixed(0);
accuracyBlock = `Past prediction accuracy for ${company.name}: ${pct}% over ${acc.total} evaluated calls.`;
}
const result = await callLlm(llmConfig, buildPrompt(company.name, event.title, articleText, factsBlock, priceBlock, accuracyBlock));
if (result) { if (result) {
const seenPreds = new Set();
const writeAll = intelligenceDb.transaction(() => { const writeAll = intelligenceDb.transaction(() => {
for (const r of (result.knowledge?.relationships || [])) { for (const r of (result.knowledge?.relationships || [])) {
insertKnowledge.run(eventId, company.id, "relationship", JSON.stringify(r), eventDate); insertKnowledge.run(eventId, company.id, "relationship", JSON.stringify(r), eventDate);
@@ -145,7 +208,21 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
} }
for (const p of (result.predictions || [])) { for (const p of (result.predictions || [])) {
insertPrediction.run(eventId, company.id, p.type, p.direction, p.magnitude, p.timeframe, p.rationale, eventDate); // hard filter — neutral predictions are dead weight, skip them
if (p.direction === "neutral") continue;
if (p.direction !== "positive" && p.direction !== "negative") continue;
const key = `${p.type}|${p.direction}|${p.magnitude}|${p.timeframe}`;
if (seenPreds.has(key)) continue;
seenPreds.add(key);
const prob = typeof p.probability === "number" && p.probability >= 0 && p.probability <= 1
? p.probability
: null;
insertPrediction.run(
eventId, company.id, p.type, p.direction, p.magnitude, p.timeframe, p.rationale, prob, eventDate
);
} }
}); });
@@ -158,6 +235,7 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
} }
for (const r of getEventArticleIds.all(eventId)) setStatusByArticleId.run(r.id); for (const r of getEventArticleIds.all(eventId)) setStatusByArticleId.run(r.id);
upsertProcessingState.run(eventId, eventArticles.length);
recordEvent.run(); recordEvent.run();
pruneCounter++; pruneCounter++;
if (pruneCounter >= 100) { pruneEvents.run(); pruneCounter = 0; } if (pruneCounter >= 100) { pruneEvents.run(); pruneCounter = 0; }
@@ -165,23 +243,44 @@ async function runAugorWorker(archiveDb, intelligenceDb, config) {
} catch (err) { } catch (err) {
console.error("[augor] error:", err.message); console.error("[augor] error:", err.message);
} finally {
// Enforce pacing on every path, including the many early `continue`
// branches for skipped or already-processed events.
await sleep(loopDelay); await sleep(loopDelay);
} }
} }
} }
function buildPrompt(companyName, eventTitle, articleText, factsBlock) { function buildPrompt(companyName, eventTitle, articleText, factsBlock, priceBlock, accuracyBlock) {
const factsPart = factsBlock ? `${factsBlock}\n\n` : ""; const factsPart = factsBlock ? `${factsBlock}\n\n` : "";
const pricePart = priceBlock ? `Market context for ${companyName}:\n${priceBlock}\n\n` : "";
const accPart = accuracyBlock ? `${accuracyBlock}\n\n` : "";
return `You are a financial intelligence analyst focused on ${companyName}. Always respond in English regardless of the language of the input articles. return `You are a financial intelligence analyst. Always respond in English.
${factsPart}Assess the impact of the following news event on ${companyName} given what you already know about the company. ${factsPart}${pricePart}${accPart}Event: ${eventTitle}
Event: ${eventTitle}
${articleText} ${articleText}
Return JSON only — no explanation. Shape: Analyze the impact of this event on ${companyName}. Return JSON only — no explanation.
Strict rules — read carefully:
- predictions must be directly caused by THIS specific event — no speculation, no priced-in narrative
- only emit a prediction if the evidence is unambiguous AND the effect on ${companyName} is concrete and quantifiable
- the default answer is no prediction. an empty predictions array is the correct output for most news. only emit one when the event clearly moves the needle
- never emit two predictions that share type+direction+magnitude+timeframe — collapse them into one
- direction must be "positive" or "negative" only — no neutral predictions, ever. if the impact is unclear, emit nothing
- magnitude:
"high" = major revenue/market-share shift, expected >5% stock move
"medium" = measurable but limited, expected 1-5% stock move
omit any prediction that doesnt clear the medium bar
- timeframe:
"short" = days to 2 weeks (use sparingly — short-horizon predictions are unreliable)
"medium" = 2 weeks to 3 months
"long" = 3+ months — preferred when the thesis is structural
- probability: your honest calibrated probability that the directional call is correct over the stated timeframe, as a number between 0.5 and 0.95. if you cant honestly assign >= 0.6, dont emit the prediction
- if the market context shows the stock has already moved sharply (>10% in 30 days), be sceptical that this event adds new information — the move may already be priced in
{ {
"knowledge": { "knowledge": {
"relationships": [ "relationships": [
@@ -195,7 +294,7 @@ Return JSON only — no explanation. Shape:
] ]
}, },
"predictions": [ "predictions": [
{ "type": "market_share|stock_price|competitive_position|other", "direction": "positive|negative|neutral", "magnitude": "high|medium|low", "timeframe": "short|medium|long", "rationale": "string" } { "type": "market_share|stock_price|competitive_position|other", "direction": "positive|negative", "magnitude": "high|medium", "timeframe": "short|medium|long", "probability": 0.0, "rationale": "string" }
] ]
} }
+11
View File
@@ -0,0 +1,11 @@
const path = require('path');
const { runAutonomyWorker } = require('./autonomyWorker');
runAutonomyWorker({
archivePath: process.env.DURIIN_DB || path.resolve('/data/archive.sqlite'),
intelligencePath: process.env.INTELLIGENCE_DB || path.resolve('/data/intelligence.sqlite'),
pollMs: Number(process.env.AUTONOMY_POLL_MS) || 1000,
}).catch((error) => {
console.error('[autonomy] fatal:', error);
process.exit(1);
});
+98
View File
@@ -0,0 +1,98 @@
const os = require('os');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const { enqueueJob, leaseNextJob, completeJob, failJob } = require('../src/autonomy/jobs');
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
function reconcileArchiveBatch(archiveDb, intelligenceDb, batchSize = 250) {
const cursor = intelligenceDb.prepare("SELECT value FROM autonomy_cursors WHERE key = 'archive_reconcile'").get();
const afterId = cursor ? cursor.value : 0;
const rows = archiveDb.prepare(`
SELECT id, event_id, ingested_at, content, has_embedding
FROM articles
WHERE id > ?
ORDER BY id ASC
LIMIT ?
`).all(afterId, batchSize);
if (!rows.length) {
intelligenceDb.prepare(`
INSERT INTO autonomy_cursors(key, value) VALUES ('archive_reconcile', 0)
ON CONFLICT(key) DO UPDATE SET value = 0, updated_at = datetime('now')
`).run();
return { scanned: 0, nextCursor: 0, reset: true };
}
const enqueue = intelligenceDb.transaction(() => {
for (const row of rows) {
const isLive = row.ingested_at && Date.now() - Date.parse(row.ingested_at) <= 48 * 60 * 60 * 1000;
const readyForIntelligence = row.event_id && row.content && row.has_embedding;
if (readyForIntelligence) {
enqueueJob(intelligenceDb, {
jobType: 'coordinator_event',
lane: isLive ? 'live' : 'historical',
priority: isLive ? 100 : 10,
entityType: 'event',
entityId: row.event_id,
idempotencyKey: `coordinator_event:${row.event_id}`,
});
}
}
intelligenceDb.prepare(`
INSERT INTO autonomy_cursors(key, value) VALUES ('archive_reconcile', ?)
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = datetime('now')
`).run(rows[rows.length - 1].id);
});
enqueue();
return { scanned: rows.length, nextCursor: rows[rows.length - 1].id, reset: false };
}
function reconcileLiveBatch(archiveDb, intelligenceDb, batchSize = 250) {
const rows = archiveDb.prepare(`
SELECT id, event_id, ingested_at, content, has_embedding
FROM articles
WHERE ingested_at >= datetime('now', '-48 hours')
ORDER BY ingested_at DESC, id DESC
LIMIT ?
`).all(batchSize);
let queued = 0;
for (const row of rows) {
if (!row.event_id || !row.content || !row.has_embedding) continue;
const result = enqueueJob(intelligenceDb, {
jobType: 'coordinator_event', lane: 'live', priority: 100,
entityType: 'event', entityId: row.event_id,
idempotencyKey: `coordinator_event:${row.event_id}`,
});
if (result.inserted) queued++;
}
return { scanned: rows.length, queued };
}
async function runAutonomyWorker({ archivePath, intelligencePath, workerId = `autonomy-${os.hostname()}-${process.pid}`, pollMs = 1000 } = {}) {
const archiveDb = new Database(archivePath, { readonly: true });
const intelligenceDb = new Database(intelligencePath);
intelligenceDb.pragma('journal_mode = WAL');
initAutonomySchema(intelligenceDb);
while (true) {
const job = leaseNextJob(intelligenceDb, workerId, 120);
if (!job) { await sleep(pollMs); continue; }
try {
if (job.job_type === 'reconcile_archive') {
reconcileLiveBatch(archiveDb, intelligenceDb);
reconcileArchiveBatch(archiveDb, intelligenceDb);
// Keep the reconciler alive as a bounded maintenance loop.
enqueueJob(intelligenceDb, {
jobType: 'reconcile_archive', lane: 'maintenance', priority: 100,
entityType: 'archive', entityId: 'archive',
idempotencyKey: `reconcile_archive:${Date.now()}`,
});
}
completeJob(intelligenceDb, job.id, workerId);
} catch (error) {
failJob(intelligenceDb, job.id, workerId, error);
}
await sleep(pollMs);
}
}
module.exports = { reconcileArchiveBatch, reconcileLiveBatch, runAutonomyWorker };
+10
View File
@@ -0,0 +1,10 @@
const path = require('path');
const { runCalibrationWorker } = require('./calibrationWorker');
runCalibrationWorker({
intelligencePath: process.env.INTELLIGENCE_DB || path.resolve('/data/intelligence.sqlite'),
pollMs: Number(process.env.AUTONOMY_CALIBRATION_POLL_MS) || 60000,
}).catch((error) => {
console.error('[calibration] fatal:', error);
process.exit(1);
});
+88
View File
@@ -0,0 +1,88 @@
const os = require('os');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const { calibrateOutcomes, cohortKey } = require('../src/autonomy/calibration');
const { decide } = require('../src/autonomy/policy');
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
function refreshCalibration(db, version = `cal-${Date.now()}`) {
const groups = db.prepare(`
SELECT p.direction, p.event_type, p.horizon_days, o.*
FROM autonomy_predictions p
JOIN autonomy_outcomes o ON o.prediction_id = p.id
WHERE p.status = 'resolved' AND p.learning_eligible = 1
`).all().reduce((map, row) => {
const key = cohortKey({ direction: row.direction, eventType: row.event_type, horizonDays: row.horizon_days });
if (!map.has(key)) map.set(key, []);
map.get(key).push(row);
return map;
}, new Map());
const insert = db.prepare(`
INSERT INTO autonomy_calibration_snapshots
(cohort_key, sample_size, effective_sample_size, directional_probability,
expected_excess_return, lower_return, upper_return, parent_cohort_key, version)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
const tx = db.transaction(() => {
for (const [key, rows] of groups) {
if (db.prepare("SELECT 1 FROM autonomy_calibration_snapshots WHERE cohort_key = ? AND version = ?").get(key, version)) continue;
const result = calibrateOutcomes(rows);
insert.run(key, result.sampleSize, result.effectiveSampleSize, result.directionalProbability,
result.expectedExcessReturn, result.lowerReturn, result.upperReturn, null, version);
}
});
tx();
return groups.size;
}
function createDecisions(db, strategyVersion = 'autonomy-1') {
const predictions = db.prepare(`
SELECT p.* FROM autonomy_predictions p
LEFT JOIN autonomy_decisions d ON d.prediction_id = p.id
WHERE d.prediction_id IS NULL AND p.status = 'open'
`).all();
const latest = db.prepare(`
SELECT * FROM autonomy_calibration_snapshots
WHERE cohort_key = ? ORDER BY created_at DESC, id DESC LIMIT 1
`);
const insert = db.prepare(`
INSERT INTO autonomy_decisions
(prediction_id, action, calibrated_probability, expected_excess_return, rationale, strategy_version)
VALUES (?, ?, ?, ?, ?, ?)
`);
let created = 0;
const tx = db.transaction(() => {
for (const prediction of predictions) {
const key = cohortKey({ direction: prediction.direction, eventType: prediction.event_type, horizonDays: prediction.horizon_days });
const calibration = latest.get(key);
const decision = calibration
? decide({ ...calibration, direction: prediction.direction }, { minSampleSize: 30 })
: { action: 'ABSTAIN', rationale: 'calibration unavailable' };
insert.run(prediction.id, decision.action, calibration?.directional_probability || null,
calibration?.expected_excess_return || null, decision.rationale, strategyVersion);
created++;
}
});
tx();
return created;
}
async function runCalibrationWorker({ intelligencePath, pollMs = 60000, workerId = `calibration-${os.hostname()}-${process.pid}` } = {}) {
const db = new Database(intelligencePath);
db.pragma('journal_mode = WAL');
initAutonomySchema(db);
while (true) {
try {
const state = db.prepare('SELECT COUNT(*) AS count, COALESCE(MAX(prediction_id), 0) AS max_id FROM autonomy_outcomes').get();
const groups = refreshCalibration(db, `cal-${state.count}-${state.max_id}`);
const decisions = createDecisions(db);
if (groups || decisions) console.log(`[${workerId}] calibration groups=${groups} decisions=${decisions}`);
} catch (error) {
console.error(`[${workerId}] calibration error:`, error.message);
}
await sleep(pollMs);
}
}
module.exports = { refreshCalibration, createDecisions, runCalibrationWorker };
+11
View File
@@ -0,0 +1,11 @@
const path = require('path');
const { runCoordinatorWorker } = require('./coordinatorWorker');
runCoordinatorWorker({
archivePath: process.env.DURIIN_DB || path.resolve('/data/archive.sqlite'),
intelligencePath: process.env.INTELLIGENCE_DB || path.resolve('/data/intelligence.sqlite'),
pollMs: Number(process.env.AUTONOMY_POLL_MS) || 1000,
}).catch((error) => {
console.error('[coordinator] fatal:', error);
process.exit(1);
});
+86
View File
@@ -0,0 +1,86 @@
const os = require('os');
const fs = require('fs');
const path = require('path');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const { leaseNextJob, completeJob, failJob } = require('../src/autonomy/jobs');
const { callCoordinator } = require('../src/autonomy/llm');
const { acceptProposal, recordRejectedProposal } = require('../src/autonomy/coordinator');
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
function loadConfig() {
const configPath = path.resolve(process.env.DURIIN_CONFIG || path.join(__dirname, '..', 'config.json'));
const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));
require('dotenv').config({ path: path.resolve(path.dirname(configPath), '.env') });
raw.openRouter = { ...(raw.openRouter || {}) };
if (process.env.OPEN_ROUTER_API_KEY) raw.openRouter.apiKey = process.env.OPEN_ROUTER_API_KEY;
if (process.env.OPEN_ROUTER_LLM_MODEL) raw.openRouter.llmModel = process.env.OPEN_ROUTER_LLM_MODEL;
return raw;
}
function buildPrompt(event, articles) {
const evidence = articles.map((article, index) =>
`[Evidence ${index + 1}] article_id=${article.id}\nTitle: ${article.title}\n${String(article.content || article.description || '').slice(0, 4000)}`
).join('\n\n---\n\n');
return `Event title: ${event.title}\n\n${evidence}\n\nReturn JSON only in this shape:\n${JSON.stringify({ predictions: [{
instrument: 'NVDA', direction: 'positive|negative', event_type: 'stable_enum',
causal_channel: 'short description', horizon_days: 10,
evidence_article_ids: [123], invalidation_condition: 'condition',
}] }, null, 2)}\n\nUse only instruments and evidence directly supported by the articles. Return an empty predictions array when there is no clear, tradable hypothesis. Never include probabilities, returns, confidence, position sizes, or actions.`;
}
async function runCoordinatorWorker({ archivePath, intelligencePath, workerId = `coordinator-${os.hostname()}-${process.pid}`, pollMs = 1000 } = {}) {
const archiveDb = new Database(archivePath, { readonly: true });
const intelligenceDb = new Database(intelligencePath);
intelligenceDb.pragma('journal_mode = WAL');
initAutonomySchema(intelligenceDb);
const config = loadConfig();
while (true) {
const job = leaseNextJob(intelligenceDb, workerId, 180, ['coordinator_event']);
if (!job) { await sleep(pollMs); continue; }
try {
const event = archiveDb.prepare('SELECT id, title FROM events WHERE id = ?').get(job.entity_id);
if (!event) throw new Error(`event ${job.entity_id} does not exist`);
const articles = archiveDb.prepare(`
SELECT id, title, description, content, pub_date_effective
FROM articles
WHERE event_id = ? AND content IS NOT NULL AND content != '' AND is_index_page = 0
ORDER BY pub_date_effective ASC, id ASC LIMIT 25
`).all(job.entity_id);
const allowlisted = intelligenceDb.prepare(
"SELECT 1 FROM autonomy_instruments WHERE active=1 AND tradable=1 LIMIT 1"
).get();
if (!allowlisted) throw new Error('no tradable instruments are allowlisted');
const historical = job.lane === 'historical';
const informationCutoff = historical
? (articles.map((article) => article.pub_date_effective).filter(Boolean).sort().pop() || new Date().toISOString())
: new Date().toISOString();
const raw = await callCoordinator(config, buildPrompt(event, articles));
try {
acceptProposal(intelligenceDb, archiveDb, raw, {
eventId: event.id,
informationCutoff,
model: config.openRouter.llmModel || 'unknown',
promptVersion: 'coordinator-1',
strategyVersion: 'autonomy-1',
learningEligible: !historical,
});
} catch (validationError) {
recordRejectedProposal(intelligenceDb, raw, {
eventId: event.id,
informationCutoff,
model: config.openRouter.llmModel || 'unknown',
promptVersion: 'coordinator-1',
learningEligible: !historical,
}, validationError.message);
}
completeJob(intelligenceDb, job.id, workerId);
} catch (error) {
failJob(intelligenceDb, job.id, workerId, error);
}
await sleep(pollMs);
}
}
module.exports = { buildPrompt, runCoordinatorWorker };
+46
View File
@@ -1,5 +1,6 @@
const Database = require("better-sqlite3"); const Database = require("better-sqlite3");
const sqliteVec = require("sqlite-vec"); const sqliteVec = require("sqlite-vec");
const { initAutonomySchema } = require("../src/autonomy/schema");
let archiveDb = null; let archiveDb = null;
let intelligenceDb = null; let intelligenceDb = null;
@@ -17,6 +18,7 @@ function getIntelligenceDb(dbPath) {
if (!intelligenceDb) { if (!intelligenceDb) {
intelligenceDb = new Database(dbPath); intelligenceDb = new Database(dbPath);
intelligenceDb.pragma("journal_mode = WAL"); intelligenceDb.pragma("journal_mode = WAL");
initAutonomySchema(intelligenceDb);
} }
return intelligenceDb; return intelligenceDb;
} }
@@ -109,6 +111,7 @@ function runMigrations(db) {
function runColumnMigrations(db) { function runColumnMigrations(db) {
try { db.exec("ALTER TABLE event_predictions ADD COLUMN event_date TEXT"); } catch (_) {} try { db.exec("ALTER TABLE event_predictions ADD COLUMN event_date TEXT"); } catch (_) {}
try { db.exec("ALTER TABLE event_knowledge ADD COLUMN event_date TEXT"); } catch (_) {} try { db.exec("ALTER TABLE event_knowledge ADD COLUMN event_date TEXT"); } catch (_) {}
try { db.exec("ALTER TABLE event_predictions ADD COLUMN probability REAL"); } catch (_) {}
db.exec(` db.exec(`
CREATE TABLE IF NOT EXISTS worker_events ( CREATE TABLE IF NOT EXISTS worker_events (
@@ -137,6 +140,49 @@ function runColumnMigrations(db) {
); );
`); `);
// tracks last-processed state per event so augor doesnt redundantly re-run on every new article
db.exec(`
CREATE TABLE IF NOT EXISTS event_processing_state (
event_id INTEGER PRIMARY KEY,
last_processed_at DATETIME,
articles_at_last_run INTEGER NOT NULL DEFAULT 0
);
`);
// cached daily price snapshots so the augor prompt can include real market context
db.exec(`
CREATE TABLE IF NOT EXISTS price_snapshots (
ticker TEXT NOT NULL,
as_of TEXT NOT NULL,
price REAL,
price_30d_ago REAL,
price_90d_ago REAL,
vol_30d REAL,
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ticker, as_of)
);
`);
// outcomes — actual realized returns for each prediction, populated by the outcome worker
db.exec(`
CREATE TABLE IF NOT EXISTS prediction_outcomes (
prediction_id INTEGER PRIMARY KEY,
company_id INTEGER,
ticker TEXT,
event_date TEXT,
price_0 REAL,
price_5d REAL,
price_10d REAL,
r5 REAL,
r10 REAL,
correct_5d INTEGER,
correct_10d INTEGER,
evaluated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_prediction_outcomes_company ON prediction_outcomes (company_id);
`);
// prune rows older than 1 hour so the table doesnt grow unbounded // prune rows older than 1 hour so the table doesnt grow unbounded
db.exec(`DELETE FROM worker_events WHERE completed_at < datetime('now', '-1 hour')`); db.exec(`DELETE FROM worker_events WHERE completed_at < datetime('now', '-1 hour')`);
} }
+12
View File
@@ -0,0 +1,12 @@
const path = require('path');
const { runExecutionWorker } = require('./executionWorker');
runExecutionWorker({
intelligencePath: process.env.INTELLIGENCE_DB || path.resolve('/data/intelligence.sqlite'),
pollMs: Number(process.env.AUTONOMY_EXECUTION_POLL_MS) || 10000,
mode: process.env.AUTONOMY_EXECUTION_MODE || 'shadow',
notional: Number(process.env.AUTONOMY_DEFAULT_NOTIONAL) || 100,
}).catch((error) => {
console.error('[execution] fatal:', error);
process.exit(1);
});
+100
View File
@@ -0,0 +1,100 @@
const os = require('os');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const { createOrderIntent } = require('../src/autonomy/orderIntents');
const { createAlpacaPaperClient } = require('../src/brokers/alpacaPaper');
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
async function runExecutionWorker({ intelligencePath, pollMs = 10000, mode = 'shadow', notional = 100, workerId = `execution-${os.hostname()}-${process.pid}` } = {}) {
if (!['shadow', 'paper'].includes(mode)) throw new Error(`unsupported execution mode: ${mode}`);
const db = new Database(intelligencePath);
db.pragma('journal_mode = WAL');
initAutonomySchema(db);
const paperClient = mode === 'paper'
? createAlpacaPaperClient({ keyId: process.env.ALPACA_PAPER_KEY_ID, secretKey: process.env.ALPACA_PAPER_SECRET_KEY })
: null;
while (true) {
if (paperClient) {
try {
const [account, positions, orders] = await Promise.all([
paperClient.getAccount(), paperClient.getPositions(), paperClient.getOrders(),
]);
db.prepare(`
INSERT INTO autonomy_account_snapshots(broker, account_id, equity, cash, buying_power, payload)
VALUES ('alpaca-paper', ?, ?, ?, ?, ?)
`).run(account.id || null, Number(account.equity), Number(account.cash), Number(account.buying_power), JSON.stringify(account));
const insertPosition = db.prepare(`
INSERT INTO autonomy_position_snapshots(broker, instrument, quantity, market_value, unrealized_pl, payload)
VALUES ('alpaca-paper', ?, ?, ?, ?, ?)
`);
for (const position of positions || []) {
insertPosition.run(position.symbol, Number(position.qty), Number(position.market_value), Number(position.unrealized_pl), JSON.stringify(position));
}
for (const order of orders || []) {
if (!order.client_order_id) continue;
const mapped = { accepted: 'submitted', new: 'submitted', pending_new: 'submitted', partially_filled: 'partially_filled', filled: 'filled', canceled: 'cancelled', cancelled: 'cancelled', rejected: 'rejected' }[order.status];
if (!mapped) continue;
db.prepare(`
UPDATE autonomy_order_intents SET status=?, broker_order_id=?, updated_at=datetime('now')
WHERE client_order_id=?
`).run(mapped, order.id || null, order.client_order_id);
db.prepare(`
INSERT INTO autonomy_broker_events(broker, event_type, broker_id, payload)
VALUES ('alpaca-paper', ?, ?, ?)
`).run(order.status, order.id || null, JSON.stringify(order));
}
} catch (error) {
console.error(`[${workerId}] broker reconciliation:`, error.message);
}
}
const decisions = db.prepare(`
SELECT d.id FROM autonomy_decisions d
LEFT JOIN autonomy_order_intents oi ON oi.decision_id = d.id
WHERE oi.id IS NULL AND d.action IN ('BUY', 'SELL')
ORDER BY d.created_at ASC LIMIT 25
`).all();
for (const decision of decisions) {
try {
const intent = createOrderIntent(db, decision.id, notional, { tradable: true, maxNotional: notional });
if (mode === 'paper') db.prepare("UPDATE autonomy_order_intents SET status='pending', updated_at=datetime('now') WHERE client_order_id=?").run(intent.clientOrderId);
console.log(`[${workerId}] ${mode} intent ${intent.clientOrderId}`);
} catch (error) {
console.error(`[${workerId}] decision ${decision.id}:`, error.message);
}
}
if (paperClient) {
const pending = db.prepare("SELECT * FROM autonomy_order_intents WHERE status='pending' ORDER BY created_at ASC LIMIT 25").all();
for (const intent of pending) {
try {
let order;
try { order = await paperClient.getOrderByClientId(intent.client_order_id); } catch (error) {
if (error.status !== 404) throw error;
}
if (!order) {
order = await paperClient.submitOrder({
symbol: intent.instrument,
notional: String(intent.notional),
side: intent.side,
type: 'market',
time_in_force: 'day',
client_order_id: intent.client_order_id,
});
}
db.prepare(`
UPDATE autonomy_order_intents
SET status = ?, broker_order_id = ?, updated_at = datetime('now')
WHERE id = ?
`).run(order.status === 'filled' ? 'filled' : 'submitted', order.id || null, intent.id);
} catch (error) {
console.error(`[${workerId}] paper order ${intent.client_order_id}:`, error.message);
db.prepare("UPDATE autonomy_order_intents SET attempts=attempts+1, last_error=?, updated_at=datetime('now') WHERE id=?")
.run(String(error.message).slice(0, 1000), intent.id);
}
}
}
await sleep(pollMs);
}
}
module.exports = { runExecutionWorker };
+6
View File
@@ -8,6 +8,7 @@ const { ensureCompanyEmbeddings } = require("./embeddings");
const { runConsolidationWorker } = require("./consolidationWorker"); const { runConsolidationWorker } = require("./consolidationWorker");
const { runGraphWorker } = require("./graphWorker"); const { runGraphWorker } = require("./graphWorker");
const { runSignalWorker } = require("./signalWorker"); const { runSignalWorker } = require("./signalWorker");
const { runOutcomeWorker } = require("./outcomeWorker");
require("dotenv").config({ path: path.resolve(__dirname, "../.env") }); require("dotenv").config({ path: path.resolve(__dirname, "../.env") });
@@ -77,6 +78,11 @@ runSignalWorker(archiveDb, intelligenceDb, config).catch(err => {
process.exit(1); process.exit(1);
}); });
runOutcomeWorker(archiveDb, intelligenceDb, config).catch(err => {
console.error("[outcome] fatal:", err);
process.exit(1);
});
process.on("SIGINT", () => { process.on("SIGINT", () => {
console.log("[intelligence] shutting down"); console.log("[intelligence] shutting down");
process.exit(0); process.exit(0);
+10
View File
@@ -0,0 +1,10 @@
const path = require('path');
const { resolveAutonomyOutcomes } = require('./outcomeAutonomyWorker');
resolveAutonomyOutcomes({
intelligencePath: process.env.INTELLIGENCE_DB || path.resolve('/data/intelligence.sqlite'),
pollMs: Number(process.env.AUTONOMY_OUTCOME_POLL_MS) || 60000,
}).catch((error) => {
console.error('[autonomy-outcome] fatal:', error);
process.exit(1);
});
+71
View File
@@ -0,0 +1,71 @@
const os = require('os');
const https = require('https');
const Database = require('better-sqlite3');
const { initAutonomySchema } = require('../src/autonomy/schema');
const { calculateOutcome } = require('../src/autonomy/outcomes');
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
function httpGet(url) {
return new Promise((resolve, reject) => {
const request = https.get(url, { headers: { 'User-Agent': 'duriin-autonomy/1.0' } }, (response) => {
let body = '';
response.setEncoding('utf8');
response.on('data', (chunk) => { body += chunk; });
response.on('end', () => response.statusCode >= 200 && response.statusCode < 300
? resolve(body) : reject(new Error(`market data returned ${response.statusCode}`)));
});
request.setTimeout(15000, () => request.destroy(new Error('market data timeout')));
request.on('error', reject);
});
}
async function history(symbol) {
const url = `https://query1.finance.yahoo.com/v8/finance/chart/${encodeURIComponent(symbol)}?range=10y&interval=1d`;
const body = JSON.parse(await httpGet(url));
const result = body?.chart?.result?.[0];
if (!result) return [];
return (result.timestamp || []).map((timestamp, index) => ({
date: new Date(timestamp * 1000).toISOString().slice(0, 10),
close: result.indicators?.quote?.[0]?.close?.[index],
})).filter((row) => Number.isFinite(row.close));
}
async function resolveAutonomyOutcomes({ intelligencePath, workerId = `outcome-${os.hostname()}-${process.pid}`, pollMs = 60000 } = {}) {
const db = new Database(intelligencePath);
db.pragma('journal_mode = WAL');
initAutonomySchema(db);
const cache = new Map();
while (true) {
const predictions = db.prepare(`
SELECT p.* FROM autonomy_predictions p
LEFT JOIN autonomy_outcomes o ON o.prediction_id = p.id
WHERE p.status = 'open' AND o.prediction_id IS NULL
AND datetime(p.information_cutoff, '+' || p.horizon_days || ' days') <= datetime('now')
ORDER BY p.information_cutoff ASC LIMIT 25
`).all();
for (const prediction of predictions) {
try {
if (!cache.has(prediction.instrument)) cache.set(prediction.instrument, await history(prediction.instrument));
if (!cache.has('SPY')) cache.set('SPY', await history('SPY'));
const result = calculateOutcome(prediction, cache.get(prediction.instrument), cache.get('SPY'));
if (!result) {
db.prepare("UPDATE autonomy_predictions SET status = 'unresolvable' WHERE id = ?").run(prediction.id);
continue;
}
db.prepare(`
INSERT OR REPLACE INTO autonomy_outcomes
(prediction_id, price_0, price_horizon, benchmark_0, benchmark_horizon, excess_return, direction_correct, error_type)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`).run(prediction.id, result.price0, result.priceHorizon, result.benchmark0, result.benchmarkHorizon,
result.excessReturn, result.directionCorrect, result.directionCorrect ? null : 'direction_error');
db.prepare("UPDATE autonomy_predictions SET status = 'resolved' WHERE id = ?").run(prediction.id);
} catch (error) {
console.error(`[autonomy-outcome] ${workerId} prediction ${prediction.id}:`, error.message);
}
await sleep(800);
}
await sleep(pollMs);
}
}
module.exports = { calculateOutcome, resolveAutonomyOutcomes };
+173
View File
@@ -0,0 +1,173 @@
// evaluates predictions older than 11 days against realized stock returns
// runs continuously, batching by ticker so we hit yahoo once per company per cycle
const { getPriceContext } = require("./priceContext");
const https = require("https");
async function runOutcomeWorker(archiveDb, intelligenceDb, config) {
const loopDelay = config.workers?.outcomeLoopDelayMs ?? 60000;
// pull predictions that are old enough to evaluate (>= 11 calendar days) and dont have an outcome yet
const getPending = intelligenceDb.prepare(`
SELECT ep.id, ep.company_id, ep.event_date, ep.direction, tc.ticker
FROM event_predictions ep
JOIN tracked_companies tc ON ep.company_id = tc.id
LEFT JOIN prediction_outcomes po ON po.prediction_id = ep.id
WHERE po.prediction_id IS NULL
AND ep.event_date IS NOT NULL
AND date(ep.event_date) <= date('now', '-11 days')
AND ep.direction IN ('positive', 'negative')
AND tc.ticker IS NOT NULL
AND tc.ticker NOT LIKE '%.%'
AND length(tc.ticker) <= 5
ORDER BY ep.event_date ASC
LIMIT 50
`);
const insertOutcome = intelligenceDb.prepare(`
INSERT OR REPLACE INTO prediction_outcomes
(prediction_id, company_id, ticker, event_date, price_0, price_5d, price_10d, r5, r10, correct_5d, correct_10d)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
while (true) {
try {
const pending = getPending.all();
if (pending.length === 0) {
await sleep(loopDelay);
continue;
}
// group by ticker so we only fetch each company's history once per cycle
const byTicker = new Map();
for (const p of pending) {
if (!byTicker.has(p.ticker)) byTicker.set(p.ticker, []);
byTicker.get(p.ticker).push(p);
}
let evaluated = 0;
for (const [ticker, preds] of byTicker.entries()) {
let history;
try {
history = await fetchYahooHistory(ticker, "1y");
} catch (err) {
console.error(`[outcome] yahoo error for ${ticker}: ${err.message}`);
continue;
}
if (!history || history.length === 0) continue;
for (const pred of preds) {
const eventDate = pred.event_date.slice(0, 10);
const price0 = nearestOnOrAfter(history, eventDate);
if (price0 == null) continue;
const date5 = addTradingDays(eventDate, 5);
const date10 = addTradingDays(eventDate, 10);
const price5 = nearestOnOrAfter(history, date5);
const price10 = nearestOnOrAfter(history, date10);
const r5 = price5 != null ? (price5 - price0) / price0 * 100 : null;
const r10 = price10 != null ? (price10 - price0) / price0 * 100 : null;
const correct5 = r5 == null ? null : (pred.direction === "positive" ? (r5 > 0 ? 1 : 0) : (r5 < 0 ? 1 : 0));
const correct10 = r10 == null ? null : (pred.direction === "positive" ? (r10 > 0 ? 1 : 0) : (r10 < 0 ? 1 : 0));
insertOutcome.run(
pred.id, pred.company_id, ticker, eventDate,
price0, price5, price10, r5, r10, correct5, correct10
);
evaluated++;
}
// small delay between tickers so we dont hammer yahoo
await sleep(800);
}
if (evaluated > 0) {
console.log(`[outcome] evaluated ${evaluated} predictions across ${byTicker.size} tickers`);
}
await sleep(loopDelay);
} catch (err) {
console.error("[outcome] cycle error:", err.message);
await sleep(loopDelay);
}
}
}
async function fetchYahooHistory(ticker, range) {
const url = `https://query1.finance.yahoo.com/v8/finance/chart/${encodeURIComponent(ticker)}?range=${range}&interval=1d`;
const body = await httpGet(url, { "User-Agent": "Mozilla/5.0 (compatible; duriin-intelligence/1.0)" });
const parsed = JSON.parse(body);
const result = parsed?.chart?.result?.[0];
if (!result) return null;
const ts = result.timestamp || [];
const closes = result.indicators?.quote?.[0]?.close || [];
const out = [];
for (let i = 0; i < ts.length; i++) {
if (closes[i] == null) continue;
out.push({
date: new Date(ts[i] * 1000).toISOString().slice(0, 10),
close: closes[i],
});
}
return out;
}
function nearestOnOrAfter(history, dateStr) {
for (const row of history) {
if (row.date >= dateStr) return row.close;
}
return null;
}
function addTradingDays(dateStr, n) {
const dt = new Date(dateStr);
let count = 0;
while (count < n) {
dt.setDate(dt.getDate() + 1);
const dow = dt.getDay();
if (dow >= 1 && dow <= 5) count++;
}
return dt.toISOString().slice(0, 10);
}
function httpGet(url, headers) {
return new Promise((resolve, reject) => {
const u = new URL(url);
const req = https.request({
hostname: u.hostname,
path: u.pathname + u.search,
method: "GET",
headers,
}, (res) => {
let data = "";
res.on("data", chunk => data += chunk);
res.on("end", () => {
if (res.statusCode >= 200 && res.statusCode < 300) resolve(data);
else reject(new Error(`yahoo ${res.statusCode}: ${data.slice(0, 200)}`));
});
});
req.on("error", reject);
req.end();
});
}
function sleep(ms) {
return new Promise(r => setTimeout(r, ms));
}
module.exports = { runOutcomeWorker };
+171
View File
@@ -0,0 +1,171 @@
const https = require("https");
// fetches daily OHLC from yahoo finance v8 chart api
// no api key needed but rate limited so we cache aggressively
async function fetchYahooHistory(ticker, range = "6mo") {
const url = `https://query1.finance.yahoo.com/v8/finance/chart/${encodeURIComponent(ticker)}?range=${range}&interval=1d`;
const body = await httpGet(url, {
"User-Agent": "Mozilla/5.0 (compatible; duriin-intelligence/1.0)",
});
let parsed;
try {
parsed = JSON.parse(body);
} catch (_) {
throw new Error(`yahoo response not JSON: ${body.slice(0, 200)}`);
}
const result = parsed?.chart?.result?.[0];
if (!result) return null;
const ts = result.timestamp || [];
const closes = result.indicators?.quote?.[0]?.close || [];
const out = [];
for (let i = 0; i < ts.length; i++) {
if (closes[i] == null) continue;
out.push({
date: new Date(ts[i] * 1000).toISOString().slice(0, 10),
close: closes[i],
});
}
return out;
}
function nearestPriceOnOrBefore(history, dateStr) {
// history is sorted ascending by date
let last = null;
for (const row of history) {
if (row.date <= dateStr) last = row;
else break;
}
return last ? last.close : null;
}
function computeStdev(values) {
if (values.length < 2) return 0;
const mean = values.reduce((a, b) => a + b, 0) / values.length;
const sq = values.reduce((acc, v) => acc + (v - mean) ** 2, 0);
return Math.sqrt(sq / (values.length - 1));
}
function computeReturns(history) {
const rets = [];
for (let i = 1; i < history.length; i++) {
const prev = history[i - 1].close;
const cur = history[i].close;
if (prev > 0) rets.push((cur - prev) / prev);
}
return rets;
}
// returns { price, price_30d_ago, price_90d_ago, vol_30d } as_of a given date
async function getPriceContext(intelligenceDb, ticker, asOfDate) {
if (!ticker || !asOfDate) return null;
// skip private/synthetic tickers — yahoo wont know them
if (/^(OPENAI|ANTHROPIC|XAI|HUAWEI|BYTEDANCE|DEEPSEEK|MISTRAL|COHERE|GROQ|SCALEAI|MCKINSEY|DELOITTE|STABILITY|INFLECTION|SPACEX|BLUEORIGIN)$/i.test(ticker)) {
return null;
}
const cacheRow = intelligenceDb.prepare(
"SELECT price, price_30d_ago, price_90d_ago, vol_30d FROM price_snapshots WHERE ticker = ? AND as_of = ?"
).get(ticker, asOfDate);
if (cacheRow) return cacheRow;
let history;
try {
history = await fetchYahooHistory(ticker, "6mo");
} catch (err) {
// dont blow up the worker on a single bad ticker
return null;
}
if (!history || history.length === 0) return null;
const price = nearestPriceOnOrBefore(history, asOfDate);
if (price == null) return null;
const date30 = new Date(asOfDate);
date30.setDate(date30.getDate() - 30);
const price30 = nearestPriceOnOrBefore(history, date30.toISOString().slice(0, 10));
const date90 = new Date(asOfDate);
date90.setDate(date90.getDate() - 90);
const price90 = nearestPriceOnOrBefore(history, date90.toISOString().slice(0, 10));
// 30-day annualized vol from daily returns
const recent = history.filter(h => h.date <= asOfDate).slice(-30);
const vol30 = computeStdev(computeReturns(recent)) * Math.sqrt(252);
const snapshot = {
price,
price_30d_ago: price30,
price_90d_ago: price90,
vol_30d: vol30,
};
try {
intelligenceDb.prepare(
"INSERT OR REPLACE INTO price_snapshots (ticker, as_of, price, price_30d_ago, price_90d_ago, vol_30d) VALUES (?, ?, ?, ?, ?, ?)"
).run(ticker, asOfDate, snapshot.price, snapshot.price_30d_ago, snapshot.price_90d_ago, snapshot.vol_30d);
} catch (_) {}
return snapshot;
}
// formats the snapshot for inclusion in the LLM prompt
function formatPriceContext(snapshot, ticker) {
if (!snapshot || snapshot.price == null) return null;
const lines = [`${ticker} price as of event: $${snapshot.price.toFixed(2)}`];
if (snapshot.price_30d_ago) {
const ret30 = (snapshot.price - snapshot.price_30d_ago) / snapshot.price_30d_ago * 100;
lines.push(`30-day return: ${ret30 >= 0 ? "+" : ""}${ret30.toFixed(1)}%`);
}
if (snapshot.price_90d_ago) {
const ret90 = (snapshot.price - snapshot.price_90d_ago) / snapshot.price_90d_ago * 100;
lines.push(`90-day return: ${ret90 >= 0 ? "+" : ""}${ret90.toFixed(1)}%`);
}
if (snapshot.vol_30d) {
lines.push(`30-day annualized volatility: ${(snapshot.vol_30d * 100).toFixed(1)}%`);
}
return lines.join("\n");
}
function httpGet(url, headers) {
return new Promise((resolve, reject) => {
const u = new URL(url);
const req = https.request({
hostname: u.hostname,
path: u.pathname + u.search,
method: "GET",
headers,
}, (res) => {
let data = "";
res.on("data", chunk => data += chunk);
res.on("end", () => {
if (res.statusCode >= 200 && res.statusCode < 300) resolve(data);
else reject(new Error(`yahoo ${res.statusCode}: ${data.slice(0, 200)}`));
});
});
req.on("error", reject);
req.end();
});
}
module.exports = { getPriceContext, formatPriceContext };
+19 -1
View File
@@ -4,6 +4,10 @@
async function runQueueFeeder(archiveDb, intelligenceDb, config) { async function runQueueFeeder(archiveDb, intelligenceDb, config) {
const batchSize = config.workers?.queueFeederBatchSize ?? 100; const batchSize = config.workers?.queueFeederBatchSize ?? 100;
const loopDelay = config.workers?.queueFeederLoopDelayMs ?? 3000; const loopDelay = config.workers?.queueFeederLoopDelayMs ?? 3000;
const maxPending = Math.max(
batchSize,
config.workers?.queueFeederMaxPending ?? 250
);
const getCursor = intelligenceDb.prepare( const getCursor = intelligenceDb.prepare(
"SELECT value FROM cursors WHERE key = 'queue_feeder'" "SELECT value FROM cursors WHERE key = 'queue_feeder'"
@@ -16,11 +20,21 @@ async function runQueueFeeder(archiveDb, intelligenceDb, config) {
INSERT OR IGNORE INTO article_queue (article_id, status, created_at) INSERT OR IGNORE INTO article_queue (article_id, status, created_at)
VALUES (?, 'pending', CURRENT_TIMESTAMP) VALUES (?, 'pending', CURRENT_TIMESTAMP)
`); `);
const getPendingCount = intelligenceDb.prepare(
"SELECT COUNT(*) AS count FROM article_queue WHERE status = 'pending'"
);
while (true) { while (true) {
try { try {
const pending = getPendingCount.get().count;
if (pending >= maxPending) {
await sleep(loopDelay);
continue;
}
const cursorRow = getCursor.get(); const cursorRow = getCursor.get();
const cursor = cursorRow ? cursorRow.value : 0; const cursor = cursorRow ? cursorRow.value : 0;
const availableSlots = Math.min(batchSize, maxPending - pending);
const articles = archiveDb.prepare(` const articles = archiveDb.prepare(`
SELECT id FROM articles SELECT id FROM articles
@@ -31,7 +45,7 @@ async function runQueueFeeder(archiveDb, intelligenceDb, config) {
AND event_id IS NOT NULL AND event_id IS NOT NULL
ORDER BY id ASC ORDER BY id ASC
LIMIT ? LIMIT ?
`).all(cursor, batchSize); `).all(cursor, availableSlots);
if (articles.length === 0) { if (articles.length === 0) {
await sleep(loopDelay); await sleep(loopDelay);
@@ -53,6 +67,10 @@ async function runQueueFeeder(archiveDb, intelligenceDb, config) {
console.log(`[feeder] queued ${inserted} articles, cursor now ${newCursor}`); console.log(`[feeder] queued ${inserted} articles, cursor now ${newCursor}`);
} }
// Always yield between archive scans. The query is synchronous and can
// otherwise monopolise the event loop while catching up a large archive.
await sleep(loopDelay);
} catch (err) { } catch (err) {
console.error("[feeder] error:", err.message); console.error("[feeder] error:", err.message);
await sleep(loopDelay); await sleep(loopDelay);
+76 -9
View File
@@ -1,10 +1,14 @@
const https = require("https"); const https = require("https");
const http = require("http"); const http = require("http");
const { getPriceContext, formatPriceContext } = require("./priceContext");
const CONCURRENCY = 4; const CONCURRENCY = 4;
const PREDICTION_WINDOW_DAYS = 21;
async function runSignalWorker(archiveDb, intelligenceDb, config) { async function runSignalWorker(archiveDb, intelligenceDb, config) {
const loopDelay = config.workers?.signalLoopDelayMs ?? 1000;
const llmConfig = config.openRouter || {}; const llmConfig = config.openRouter || {};
// add as_of column if it doesnt exist yet // add as_of column if it doesnt exist yet
@@ -28,15 +32,28 @@ async function runSignalWorker(archiveDb, intelligenceDb, config) {
LIMIT 1 LIMIT 1
`); `);
// decay window — only feed recent predictions into the signal prompt.
// backtest showed signal degrades sharply after ~10 days, so use 21d as a soft window
const getPredictions = intelligenceDb.prepare(` const getPredictions = intelligenceDb.prepare(`
SELECT type, direction, magnitude, timeframe, rationale, event_date, id SELECT type, direction, magnitude, timeframe, rationale, probability, event_date, id
FROM event_predictions FROM event_predictions
WHERE company_id = ? WHERE company_id = ?
AND substr(event_date, 1, 10) <= ? AND substr(event_date, 1, 10) <= ?
AND date(substr(event_date, 1, 10)) >= date(?, '-${PREDICTION_WINDOW_DAYS} days')
AND timeframe != 'short'
AND direction IN ('positive', 'negative')
ORDER BY event_date DESC ORDER BY event_date DESC
LIMIT 50 LIMIT 50
`); `);
const getCompanyAccuracy = intelligenceDb.prepare(`
SELECT
COUNT(*) as total,
SUM(correct_10d) as correct
FROM prediction_outcomes
WHERE company_id = ? AND correct_10d IS NOT NULL
`);
const getFacts = intelligenceDb.prepare(` const getFacts = intelligenceDb.prepare(`
SELECT claim, type, confidence, confirmation_count SELECT claim, type, confidence, confirmation_count
FROM company_facts FROM company_facts
@@ -118,11 +135,31 @@ async function runSignalWorker(archiveDb, intelligenceDb, config) {
continue; continue;
} }
const predictions = getPredictions.all(company_id, checkpoint_date); const predictions = getPredictions.all(company_id, checkpoint_date, checkpoint_date);
const facts = getFacts.all(company_id, checkpoint_date); const facts = getFacts.all(company_id, checkpoint_date);
const relationships = getRelationships.all(company_id, checkpoint_date); const relationships = getRelationships.all(company_id, checkpoint_date);
const prompt = buildPrompt(company.name, facts, relationships, predictions, checkpoint_date); // skip if the decay window left us with nothing useful
if (predictions.length === 0) {
inFlight.delete(key);
continue;
}
// pull market context + historical accuracy for this company
let priceBlock = null;
if (company.ticker) {
try {
const snapshot = await getPriceContext(intelligenceDb, company.ticker, checkpoint_date);
priceBlock = formatPriceContext(snapshot, company.ticker);
} catch (_) {}
}
const acc = getCompanyAccuracy.get(company_id);
const accuracyBlock = (acc && acc.total >= 5)
? `Past prediction accuracy for ${company.name}: ${(acc.correct / acc.total * 100).toFixed(0)}% over ${acc.total} evaluated calls.`
: null;
const prompt = buildPrompt(company.name, facts, relationships, predictions, checkpoint_date, priceBlock, accuracyBlock);
let result; let result;
try { try {
@@ -165,6 +202,10 @@ async function runSignalWorker(archiveDb, intelligenceDb, config) {
} catch (err) { } catch (err) {
console.error(`[signal:${id}] cycle error:`, err.message); console.error(`[signal:${id}] cycle error:`, err.message);
} finally {
// Successful and early-exit paths must yield too; otherwise an invalid
// checkpoint can turn this into a tight synchronous SQLite loop.
await sleep(loopDelay);
} }
} }
} }
@@ -179,7 +220,7 @@ async function runSignalWorker(archiveDb, intelligenceDb, config) {
} }
function buildPrompt(companyName, facts, relationships, predictions, asOf) { function buildPrompt(companyName, facts, relationships, predictions, asOf, priceBlock, accuracyBlock) {
const factsBlock = facts.length > 0 const factsBlock = facts.length > 0
? facts.map(f => `- ${f.claim} (confirmed ${f.confirmation_count}x)`).join("\n") ? facts.map(f => `- ${f.claim} (confirmed ${f.confirmation_count}x)`).join("\n")
: "No known facts yet."; : "No known facts yet.";
@@ -188,9 +229,30 @@ function buildPrompt(companyName, facts, relationships, predictions, asOf) {
? relationships.map(r => `- ${r.relationship_type}: ${r.to_entity} (${r.confidence})`).join("\n") ? relationships.map(r => `- ${r.relationship_type}: ${r.to_entity} (${r.confidence})`).join("\n")
: "No known relationships."; : "No known relationships.";
const predBlock = predictions.map((p, i) =>
`${i + 1}. [${p.type}] ${p.direction} / ${p.magnitude} / ${p.timeframe}${p.rationale || "no rationale"}` // recency-weighted prediction block — newer predictions get a [RECENT] tag,
).join("\n"); // and high-magnitude + long-timeframe gets [HIGH CONFIDENCE].
// probability is surfaced when present so the LLM can weight by it.
const asOfMs = new Date(asOf + "T00:00:00Z").getTime();
const predBlock = predictions.map((p, i) => {
const tags = [];
if (p.magnitude === "high" && p.timeframe === "long") tags.push("HIGH CONFIDENCE");
if (p.event_date) {
const ageDays = Math.round((asOfMs - new Date(p.event_date.slice(0, 10) + "T00:00:00Z").getTime()) / 86_400_000);
if (ageDays <= 7) tags.push(`RECENT ${ageDays}d`);
else tags.push(`${ageDays}d old`);
}
const probStr = (typeof p.probability === "number") ? ` p=${p.probability.toFixed(2)}` : "";
const tagStr = tags.length ? ` [${tags.join(", ")}]` : "";
return `${i + 1}. [${p.type}]${tagStr}${probStr} ${p.direction} / ${p.magnitude} / ${p.timeframe}${p.rationale || "no rationale"}`;
}).join("\n");
const pricePart = priceBlock ? `\nMarket context for ${companyName}:\n${priceBlock}\n` : "";
const accPart = accuracyBlock ? `\n${accuracyBlock}\n` : "";
return `You are a financial intelligence analyst generating a trade signal for ${companyName} as of ${asOf}. return `You are a financial intelligence analyst generating a trade signal for ${companyName} as of ${asOf}.
@@ -199,10 +261,12 @@ ${factsBlock}
Known relationships: Known relationships:
${relBlock} ${relBlock}
${pricePart}${accPart}
Event predictions up to ${asOf}: Recent event predictions (last 21 days):
${predBlock} ${predBlock}
Weight RECENT and HIGH CONFIDENCE predictions more heavily. Discount older predictions and any that lack a probability score. Predictions that disagree with the recent price trajectory are weaker — be sceptical of bullish predictions on a name that has already rallied 20% in 30 days, and vice versa.
Generate a trade signal as JSON with this exact shape: Generate a trade signal as JSON with this exact shape:
{ {
"signal": "BUY | HOLD | SELL", "signal": "BUY | HOLD | SELL",
@@ -214,11 +278,14 @@ Generate a trade signal as JSON with this exact shape:
"summary": "2-3 sentence plain English summary" "summary": "2-3 sentence plain English summary"
} }
Default to HOLD when the predictions are mixed, stale, or low-probability. Reserve BUY/SELL for cases where the weight of high-confidence recent evidence is unambiguous.
Risk factors should be derived from: Risk factors should be derived from:
- Supply chain concentration (heavy dependence on single suppliers) - Supply chain concentration (heavy dependence on single suppliers)
- Geopolitical exposure (relationships with entities in sensitive regions) - Geopolitical exposure (relationships with entities in sensitive regions)
- Competitive threats (strong competitors gaining ground) - Competitive threats (strong competitors gaining ground)
- Regulatory exposure (themes mentioning regulation or export controls) - Regulatory exposure (themes mentioning regulation or export controls)
- Stretched valuation given recent price moves
- Negative prediction patterns in recent events - Negative prediction patterns in recent events
Only output valid JSON. Always respond in English.`; Only output valid JSON. Always respond in English.`;