Files
trading-bot/scripts/find_isa_candidates.py
T

90 lines
3.7 KiB
Python

import pandas as pd
import json
import logging
from src.strategy.scanner import scan_for_candidates
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def find_best_isa_tickers():
"""
1. Reads available Trading212 instruments.
2. Filters for US Stocks (excluding ETFs/Warrants which are often non-ISA compliant or bad for this strategy).
3. Maps T212 tickers to Yahoo Finance tickers.
4. Runs the strategy scanner to find the most volatile/liquid candidates.
"""
try:
with open('available_instruments.json', 'r') as f:
instruments = json.load(f)
except FileNotFoundError:
logger.error("Please run get_available_tickers.py first to generate available_instruments.json")
return
# Filter for US Stocks only
# - type == 'STOCK': Excludes US ETFs (not allowed in UK ISAs) and Warrants
# - currencyCode == 'USD': Ensures it's trading during the US session (09:30 EST)
us_stocks = [
inst for inst in instruments
if inst.get('type') == 'STOCK' and inst.get('currencyCode') == 'USD'
]
logger.info(f"Filtered down to {len(us_stocks)} US Stocks from Trading212.")
# Extract short names (Yahoo Finance tickers)
# Trading212 usually uses 'shortName' for the actual market ticker (e.g., AAPL)
# and 'ticker' for their internal ID (e.g., AAPL_US_EQ).
t212_to_yf_map = {}
for stock in us_stocks:
short_name = stock.get('shortName')
t212_id = stock.get('ticker')
if short_name and t212_id:
# Avoid preferred shares/warrants that might sneak in with hyphens or dots
# if yfinance can't parse them easily, but we'll try them all.
t212_to_yf_map[short_name] = t212_id
yf_tickers = list(t212_to_yf_map.keys())
# We don't want to scan all 6,000+ stocks at once (Yahoo Finance will rate limit us).
# Let's filter locally first using T212 maxOpenQuantity or just take a known subset,
# OR we can pass the top 500 popular ones. For this script, let's scan a robust list of
# well-known highly liquid tech/growth stocks that are definitely ISA eligible.
# Known high-liquidity ISA-eligible US stocks:
focus_list = [
"TSLA", "NVDA", "AMD", "AAPL", "MSFT", "META", "AMZN", "GOOGL", "NFLX",
"COIN", "MSTR", "PLTR", "UBER", "HOOD", "RST", "SNOW", "CRM", "CRWD",
"PANW", "SMCI", "ARM", "SQ", "SHOP", "ROKU", "DDOG", "NET", "DOCN"
]
# Ensure they exist in our T212 account
valid_yf_tickers = [t for t in focus_list if t in t212_to_yf_map]
logger.info(f"Scanning {len(valid_yf_tickers)} highly liquid known ISA-eligible stocks...")
# Run the scanner
results_df = scan_for_candidates(tickers=valid_yf_tickers, min_price=20.0, min_volume=2_000_000)
if results_df.empty:
logger.warning("No candidates met the minimum price/volume criteria.")
return
# Map back to Trading212 internal tickers so the bot knows what to trade
results_df['T212_Ticker'] = results_df['Ticker'].map(t212_to_yf_map)
# Reorder columns
cols = ['Ticker', 'T212_Ticker', 'Close', 'ATR_14', 'ATR_Percent', 'Avg_Volume']
results_df = results_df[cols]
print("\n" + "="*80)
print("🏆 BEST ISA-ELIGIBLE CANDIDATES FOR TOUCH & TURN TODAY 🏆")
print("="*80)
print(results_df.to_string(index=False))
print("\n* Use the 'T212_Ticker' column when configuring the ExecutionManager.")
# Save the day's watchlist
results_df.to_csv("isa_watchlist.csv", index=False)
logger.info("Saved shortlist to isa_watchlist.csv")
return results_df
if __name__ == "__main__":
find_best_isa_tickers()