How to Build a Crypto Portfolio Tracker with AI Insights and Alerts
Build a personal crypto portfolio tracker that monitors your wallets and exchange balances, calculates P&L, and uses AI to generate weekly performance insights and rebalancing recommendations.
Builder of AI agents, crypto trading bots, and open-source automation tools. Sharing practical guides on how to build, deploy, and profit from AI and DeFi technology.
Why Build Your Own Portfolio Tracker?
Apps like CoinStats and Delta are convenient, but they have limitations: they don't track DeFi positions well, they can't execute trades, and they definitely can't generate personalized AI analysis. Building your own gives you full control and a platform to add automation.
Architecture
Data Sources:
โโโ CEX APIs (Binance, Coinbase, Kraken)
โโโ On-chain wallets (Ethereum, Solana, BSC)
โโโ DeFi protocols (Uniswap positions, Aave balances)
โ
Portfolio Aggregator
โ
P&L Calculator + Historical DB
โ
AI Analysis Engine (GPT-4o)
โ
Dashboard + Alerts (Telegram/Discord/Email)
Step 1: Aggregating Exchange Balances
import ccxt
from dataclasses import dataclass
@dataclass
class Position:
asset: str
quantity: float
avg_buy_price: float
current_price: float
exchange: str
@property
def value_usd(self) -> float:
return self.quantity * self.current_price
@property
def pnl_pct(self) -> float:
return (self.current_price - self.avg_buy_price) / self.avg_buy_price * 100
def get_exchange_balances(api_configs: dict) -> list[Position]:
positions = []
for exchange_id, config in api_configs.items():
exchange = getattr(ccxt, exchange_id)(config)
try:
balance = exchange.fetch_balance()
tickers = exchange.fetch_tickers()
for asset, data in balance['total'].items():
if data > 0 and asset != 'USDT':
symbol = f"{asset}/USDT"
if symbol in tickers:
current_price = tickers[symbol]['last']
# Get average buy price from trade history
avg_price = get_average_buy_price(exchange, symbol)
positions.append(Position(
asset=asset,
quantity=data,
avg_buy_price=avg_price,
current_price=current_price,
exchange=exchange_id
))
except Exception as e:
print(f"Error fetching {exchange_id}: {e}")
return positions
Step 2: On-Chain Wallet Tracking
from web3 import Web3
from decimal import Decimal
import requests
# Track ERC-20 token balances
MORALIS_API_KEY = 'your_key'
def get_wallet_positions(wallet_address: str) -> list[Position]:
"""Get all token balances for an Ethereum wallet"""
url = f"https://deep-index.moralis.io/api/v2.2/wallets/{wallet_address}/tokens"
headers = {'X-API-Key': MORALIS_API_KEY}
params = {'chain': 'eth', 'exclude_spam': 'true', 'exclude_unverified_contracts': 'true'}
response = requests.get(url, headers=headers, params=params)
tokens = response.json().get('result', [])
positions = []
for token in tokens:
if float(token.get('usd_value', 0)) < 10: # Skip dust
continue
positions.append(Position(
asset=token['symbol'],
quantity=float(token['balance_formatted']),
avg_buy_price=0, # Hard to track on-chain without full history
current_price=float(token.get('usd_price', 0)),
exchange=f"wallet:{wallet_address[:8]}..."
))
return positions
Step 3: Portfolio Database
import sqlite3
from datetime import datetime
def init_db(db_path='portfolio.db'):
conn = sqlite3.connect(db_path)
conn.execute('''CREATE TABLE IF NOT EXISTS snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
asset TEXT NOT NULL,
quantity REAL,
price_usd REAL,
value_usd REAL,
exchange TEXT
)''')
conn.execute('''CREATE TABLE IF NOT EXISTS daily_totals (
date TEXT PRIMARY KEY,
total_value_usd REAL,
btc_value REAL,
eth_value REAL
)''')
conn.commit()
return conn
def save_snapshot(conn, positions: list[Position]):
timestamp = datetime.now().isoformat()
for pos in positions:
conn.execute('''INSERT INTO snapshots
(timestamp, asset, quantity, price_usd, value_usd, exchange)
VALUES (?, ?, ?, ?, ?, ?)''',
(timestamp, pos.asset, pos.quantity, pos.current_price,
pos.value_usd, pos.exchange))
conn.commit()
Step 4: AI Performance Analysis
from openai import OpenAI
openai = OpenAI()
def generate_ai_weekly_report(positions: list[Position], weekly_history: list) -> str:
"""Generate a personalized weekly portfolio analysis using GPT-4o"""
total_value = sum(p.value_usd for p in positions)
total_pnl = sum((p.current_price - p.avg_buy_price) * p.quantity for p in positions if p.avg_buy_price > 0)
portfolio_summary = "\n".join([
f"- {p.asset}: {p.quantity:.4f} @ ${p.current_price:.2f} = ${p.value_usd:.0f} ({p.pnl_pct:+.1f}%)"
for p in sorted(positions, key=lambda x: x.value_usd, reverse=True)[:10]
])
weekly_change = calculate_weekly_pnl(weekly_history)
prompt = f"""
Analyze this crypto portfolio and provide weekly insights:
PORTFOLIO SUMMARY:
Total Value: ${total_value:,.0f}
Weekly P&L: ${weekly_change:+,.0f} ({weekly_change/total_value*100:+.1f}%)
Unrealized P&L: ${total_pnl:+,.0f}
TOP POSITIONS:
{portfolio_summary}
Please provide:
1. Key performance drivers this week
2. Risk assessment (concentration risk, correlated assets)
3. Specific rebalancing suggestions if any allocation is > 30% of portfolio
4. 3 actionable insights for next week
Keep the response concise and specific.
"""
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
Step 5: Automated Alerts
import telegram
bot = telegram.Bot(token=TELEGRAM_TOKEN)
async def check_and_alert(positions: list[Position]):
alerts = []
for pos in positions:
# Large loss alert
if pos.pnl_pct < -20:
alerts.append(f"๐ด {pos.asset}: Down {pos.pnl_pct:.1f}% from avg buy")
# Large gain โ consider taking profits
if pos.pnl_pct > 100:
alerts.append(f"๐ข {pos.asset}: Up {pos.pnl_pct:.1f}% โ consider taking some profits")
# Concentration risk
total = sum(p.value_usd for p in positions)
if pos.value_usd / total > 0.40:
alerts.append(f"โ ๏ธ {pos.asset}: {pos.value_usd/total:.0%} of portfolio โ consider diversifying")
if alerts:
message = "๐ **Portfolio Alert**\n\n" + "\n".join(alerts)
await bot.send_message(chat_id=TELEGRAM_CHAT_ID, text=message, parse_mode='Markdown')
# Schedule weekly reports
import schedule
schedule.every().monday.at("08:00").do(lambda: asyncio.run(send_weekly_report()))
schedule.every(30).minutes.do(lambda: asyncio.run(check_and_alert(get_all_positions())))
Sample Output
๐ WEEKLY PORTFOLIO REPORT โ Week of March 6, 2026
Total Value: $47,832 (+$3,241 this week, +7.3%)
TOP PERFORMERS:
โ
SOL: +18.2% this week (now 28% of portfolio)
โ
ETH: +6.1%
โ BNB: -2.3%
AI INSIGHTS:
1. SOL now represents 28% of your portfolio โ above the 25% target threshold.
Consider trimming 10-15% of your SOL position and rotating into BTC for balance.
2. Your portfolio is heavily correlated โ 85% of value in ETH ecosystem assets.
Adding BTC or non-correlated assets (LINK, ATOM) would reduce drawdown risk.
3. Your average buy prices suggest you DCA'd well during the Dec-Feb dip.
Current unrealized gains of +$8,400 represent a 21% gain on invested capital.
RECOMMENDATION: Maintain current positions. Consider setting limit orders to
take 15% profits on SOL above $280.
This tracker takes a weekend to build and provides insights that most paid apps can't match โ personalized, AI-generated, and fully automated.
Tagged in
Related Articles
Grok AI for Crypto Trading: How Elon's AI Gives an Edge in 2026
4 min read
AI AgentsHow to Build a Crypto Twitter (X) Bot That Goes Viral in 2026
5 min read
AI AgentsAgentic AI Frameworks Compared: LangGraph vs CrewAI vs AutoGen in 2026
6 min read
AI AgentsBest AI Coding Tools for Building Crypto Bots in 2026: Cursor vs Copilot vs Devin
5 min read