Development of Crypto Asset Recommendation System
A recommendation system for crypto assets is not Netflix "you might like this movie." It's a system that based on user profile (risk appetite, investment horizon, current portfolio) and current market data proposes assets for purchase, sale or rebalancing.
Problem Statement
Content-based recommendations: recommend assets similar to ones user already holds or liked.
Collaborative filtering: recommend assets held by similar users (by risk profile, portfolio size, horizon).
Hybrid approach: combination of both + market signals.
Context-aware: account for current market conditions — different recommendations in bear vs bull market.
User Profiling
from dataclasses import dataclass
from enum import Enum
class RiskProfile(Enum):
CONSERVATIVE = 'conservative'
MODERATE = 'moderate'
AGGRESSIVE = 'aggressive'
DEGEN = 'degen'
@dataclass
class UserProfile:
user_id: str
risk_profile: RiskProfile
investment_horizon_days: int
portfolio_value_usd: float
current_holdings: dict # {symbol: value_usd}
preferred_categories: list # ['defi', 'layer1', 'gaming']
excluded_categories: list
max_single_asset_pct: float # 0.20 = max 20% in one asset
def get_available_budget(self):
invested = sum(self.current_holdings.values())
return max(0, self.portfolio_value_usd - invested)
Asset Scoring Engine
class AssetScorer:
def __init__(self, market_data, on_chain_data=None):
self.market_data = market_data
self.on_chain_data = on_chain_data
def score_asset(self, symbol, user_profile, market_regime):
"""Final score = weighted sum of sub-scores"""
scores = {}
weights = self._get_weights_for_profile(user_profile.risk_profile)
# 1. Momentum score
scores['momentum'] = self._momentum_score(symbol)
# 2. Risk-adjusted return score
scores['risk_return'] = self._risk_adjusted_score(symbol, user_profile)
# 3. Diversification benefit
scores['diversification'] = self._diversification_score(
symbol, user_profile.current_holdings
)
# 4. Liquidity score
scores['liquidity'] = self._liquidity_score(symbol, user_profile.portfolio_value_usd)
# 5. Sentiment score
scores['sentiment'] = self._sentiment_score(symbol)
# 6. Fundamentals (on-chain + protocol metrics)
scores['fundamentals'] = self._fundamentals_score(symbol)
# 7. Market regime fit
scores['regime_fit'] = self._regime_fit_score(symbol, market_regime)
# Weighted final score
final_score = sum(scores[k] * weights.get(k, 0.1) for k in scores)
return {
'symbol': symbol,
'final_score': final_score,
'sub_scores': scores,
'weights': weights
}
Portfolio Construction from Recommendations
def build_recommended_portfolio(user_profile, scored_assets, max_positions=10):
"""Build optimal portfolio from scored assets"""
# Filtering
filtered = [a for a in scored_assets
if a['symbol'] not in user_profile.excluded_categories
and a['final_score'] > 0.3]
# Sort by score
filtered.sort(key=lambda x: x['final_score'], reverse=True)
# Select top-N with diversification
selected = []
selected_categories = set()
for asset in filtered[:50]:
if len(selected) >= max_positions:
break
category = get_asset_category(asset['symbol'])
if selected_categories.count(category) >= 3:
continue
selected.append(asset)
selected_categories.add(category)
# Allocation (weight by score)
total_score = sum(a['final_score'] for a in selected)
available_budget = user_profile.get_available_budget()
allocations = []
for asset in selected:
raw_allocation = (asset['final_score'] / total_score) * available_budget
max_alloc = user_profile.portfolio_value_usd * user_profile.max_single_asset_pct
final_allocation = min(raw_allocation, max_alloc)
allocations.append({
'symbol': asset['symbol'],
'allocation_usd': final_allocation,
'allocation_pct': final_allocation / user_profile.portfolio_value_usd,
'score': asset['final_score'],
'sub_scores': asset['sub_scores']
})
return allocations
Explainability
Users need to understand recommendation logic:
def generate_recommendation_explanation(asset, score_result, user_profile):
reasons = []
sub_scores = score_result['sub_scores']
if sub_scores['momentum'] > 0.7:
reasons.append(f"Strong momentum: +{get_return(asset, 30):.1f}% in 30 days")
if sub_scores['diversification'] > 0.7:
reasons.append(f"Low correlation with portfolio ({get_correlation(asset):.2f})")
if sub_scores['fundamentals'] > 0.7:
reasons.append(f"High on-chain activity: TVL grew {get_tvl_change(asset):.0f}%")
if sub_scores['sentiment'] > 0.6:
reasons.append("Positive community sentiment last 7 days")
risk_warning = []
if get_volatility(asset) > 0.8:
risk_warning.append("High volatility")
if get_market_cap(asset) < 100_000_000:
risk_warning.append("Small cap — high risk")
return {
'reasons': reasons,
'risk_warnings': risk_warning,
'confidence': score_result['final_score']
}
Dashboard and UX
Recommendation panel: top-10 recommendations with score breakdown, explanation in plain language, button to auto-execute, expected portfolio characteristics.
Personalization: risk profile settings, investment horizon, excluded categories.
Performance tracking: backtesting of recommendation algorithm.
Developing a recommendation system with multi-factor scoring, user profiling, portfolio construction with diversification constraints and explainable recommendations.







