# Robo-Advisor SPARQL Templates

PREFIX robo: <http://ggen.dev/ontology/robo-advisor#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

# Query 1: Get client portfolio summary
# PARAM: ?clientId - Client identifier
SELECT ?portfolio ?totalValue ?cashBalance ?assetCount
WHERE {
  ?client robo:clientId ?clientId ;
          robo:hasPortfolio ?portfolio .
  ?portfolio robo:totalValue ?totalValue ;
             robo:cashBalance ?cashBalance .
  {
    SELECT ?portfolio (COUNT(?asset) AS ?assetCount)
    WHERE {
      ?portfolio robo:holdsAsset ?asset .
    }
    GROUP BY ?portfolio
  }
}

# Query 2: Get client goals with progress tracking
# PARAM: ?clientId - Client identifier
SELECT ?goal ?goalName ?targetAmount ?currentAmount ?targetDate ?progress
WHERE {
  ?client robo:clientId ?clientId ;
          robo:hasGoal ?goal ;
          robo:hasPortfolio ?portfolio .
  ?goal robo:goalName ?goalName ;
        robo:targetAmount ?targetAmount ;
        robo:targetDate ?targetDate .
  ?portfolio robo:totalValue ?currentAmount .
  BIND((?currentAmount / ?targetAmount) * 100 AS ?progress)
}
ORDER BY ?targetDate

# Query 3: Get risk profile assessment
# PARAM: ?clientId - Client identifier
SELECT ?client ?riskScore ?riskCategory ?timeHorizonYears ?tolerance
WHERE {
  ?client robo:clientId ?clientId ;
          robo:hasRiskProfile ?profile .
  ?profile robo:riskScore ?riskScore ;
           robo:riskCategory ?riskCategory .
  ?client robo:hasGoal ?goal .
  ?goal robo:hasTimeHorizon ?horizon .
  ?horizon robo:timeHorizonYears ?timeHorizonYears .
  ?profile robo:hasTolerance ?tolMetric .
  ?tolMetric robo:toleranceLevel ?tolerance .
}

# Query 4: Calculate current portfolio allocation
# PARAM: ?portfolioId - Portfolio identifier
SELECT ?assetClass (SUM(?value) AS ?totalValue) ?targetAllocation ?currentAllocation
WHERE {
  ?portfolio robo:portfolioId ?portfolioId ;
             robo:holdsAsset ?asset ;
             robo:hasAllocation ?allocation .
  ?asset robo:assetClass ?assetClass ;
         robo:currentValue ?value .
  ?allocation robo:assetClass ?assetClass ;
              robo:targetAllocation ?targetAllocation .
  ?portfolio robo:totalValue ?portfolioTotal .
  BIND((SUM(?value) / ?portfolioTotal) * 100 AS ?currentAllocation)
}
GROUP BY ?assetClass ?targetAllocation ?portfolioTotal

# Query 5: Identify rebalancing opportunities
# PARAM: ?portfolioId - Portfolio identifier
# PARAM: ?threshold - Drift threshold percentage (e.g., 5.0)
SELECT ?assetClass ?targetAllocation ?currentAllocation ?drift ?recommendedAction
WHERE {
  ?portfolio robo:portfolioId ?portfolioId ;
             robo:hasAllocation ?allocation .
  ?allocation robo:assetClass ?assetClass ;
              robo:targetAllocation ?targetAllocation ;
              robo:currentAllocation ?currentAllocation .
  BIND(ABS(?currentAllocation - ?targetAllocation) AS ?drift)
  BIND(IF(?currentAllocation > ?targetAllocation, "SELL", "BUY") AS ?recommendedAction)
  FILTER (?drift > ?threshold)
}
ORDER BY DESC(?drift)

# Query 6: Get tax-loss harvesting opportunities
# PARAM: ?portfolioId - Portfolio identifier
# PARAM: ?minLoss - Minimum loss threshold
SELECT ?asset ?assetSymbol ?taxLot ?costBasis ?currentValue ?unrealizedLoss ?purchaseDate
WHERE {
  ?portfolio robo:portfolioId ?portfolioId ;
             robo:holdsAsset ?asset ;
             robo:hasTaxLot ?taxLot .
  ?asset robo:assetSymbol ?assetSymbol ;
         robo:currentValue ?currentValue .
  ?taxLot robo:costBasis ?costBasis ;
          robo:unrealizedGainLoss ?unrealizedLoss ;
          robo:purchaseDate ?purchaseDate .
  FILTER (?unrealizedLoss < -?minLoss)
  FILTER (NOW() - ?purchaseDate > 30)  # Avoid wash sale
}
ORDER BY ?unrealizedLoss

# Query 7: Generate tax lot optimization strategy
# PARAM: ?portfolioId - Portfolio identifier
# PARAM: ?assetSymbol - Asset to sell
# PARAM: ?quantity - Quantity to sell
SELECT ?taxLot ?taxLotId ?quantity ?costBasis ?taxImpact ?method
WHERE {
  ?portfolio robo:portfolioId ?portfolioId ;
             robo:hasTaxLot ?taxLot .
  ?taxLot robo:assetSymbol ?assetSymbol ;
          robo:taxLotId ?taxLotId ;
          robo:quantity ?quantity ;
          robo:costBasis ?costBasis .
  ?portfolio robo:appliesTaxStrategy ?strategy .
  ?strategy a robo:TaxLotOptimization ;
            robo:selectionMethod ?method ;
            robo:calculatesTaxImpact ?taxImpact .
}
ORDER BY (IF(?method = "HIFO", DESC(?costBasis), ASC(?costBasis)))
LIMIT ?quantity

# Query 8: Get portfolio performance metrics
# PARAM: ?portfolioId - Portfolio identifier
# PARAM: ?startDate - Period start date
# PARAM: ?endDate - Period end date
SELECT ?portfolio ?totalReturn ?annualizedReturn ?sharpeRatio ?maxDrawdown
WHERE {
  ?portfolio robo:portfolioId ?portfolioId ;
             robo:hasPerformance ?perf .
  ?perf robo:totalReturn ?totalReturn ;
        robo:annualizedReturn ?annualizedReturn ;
        robo:sharpeRatio ?sharpeRatio ;
        robo:maxDrawdown ?maxDrawdown ;
        robo:startDate ?startDate ;
        robo:endDate ?endDate .
}

# Query 9: Recommend allocation model based on risk profile
# PARAM: ?clientId - Client identifier
SELECT ?model ?modelName ?expectedReturn ?expectedVolatility ?allocation
WHERE {
  ?client robo:clientId ?clientId ;
          robo:hasRiskProfile ?profile .
  ?profile robo:riskScore ?riskScore .
  ?model a robo:AllocationModel ;
         robo:modelName ?modelName ;
         robo:suitableForRiskScore ?riskScore ;
         robo:expectedReturn ?expectedReturn ;
         robo:expectedVolatility ?expectedVolatility ;
         robo:recommendedAllocation ?allocation .
}
ORDER BY DESC(?expectedReturn)

# Query 10: Calculate required contributions to meet goal
# PARAM: ?goalId - Goal identifier
SELECT ?goal ?goalName ?targetAmount ?currentAmount ?yearsRemaining ?monthlyContribution
WHERE {
  ?goal robo:goalId ?goalId ;
        robo:goalName ?goalName ;
        robo:targetAmount ?targetAmount ;
        robo:targetDate ?targetDate .
  ?client robo:hasGoal ?goal ;
          robo:hasPortfolio ?portfolio .
  ?portfolio robo:totalValue ?currentAmount .
  BIND((YEAR(?targetDate) - YEAR(NOW())) AS ?yearsRemaining)
  BIND((?targetAmount - ?currentAmount) / (?yearsRemaining * 12) AS ?monthlyContribution)
  FILTER (?yearsRemaining > 0)
}

# Query 11: Get transaction history with tax implications
# PARAM: ?portfolioId - Portfolio identifier
# PARAM: ?taxYear - Tax year
SELECT ?transaction ?transactionDate ?transactionType ?asset ?quantity ?price ?gainLoss ?holding Period
WHERE {
  ?portfolio robo:portfolioId ?portfolioId ;
             robo:executesTransaction ?transaction .
  ?transaction robo:transactionDate ?transactionDate ;
               robo:transactionType ?transactionType ;
               robo:asset ?asset ;
               robo:quantity ?quantity ;
               robo:price ?price .
  OPTIONAL { ?transaction robo:realizedGainLoss ?gainLoss }
  OPTIONAL { ?transaction robo:holdingPeriod ?holdingPeriod }
  FILTER (YEAR(?transactionDate) = ?taxYear)
}
ORDER BY ?transactionDate

# Query 12: Asset location optimization (tax-efficient placement)
# PARAM: ?clientId - Client identifier
SELECT ?asset ?assetSymbol ?currentAccount ?recommendedAccount ?taxDrag
WHERE {
  ?client robo:clientId ?clientId ;
          robo:hasPortfolio ?portfolio .
  ?portfolio robo:holdsAsset ?asset .
  ?asset robo:assetSymbol ?assetSymbol ;
         robo:currentAccount ?currentAccount ;
         robo:taxEfficiency ?taxEfficiency .
  ?client robo:appliesTaxStrategy ?strategy .
  ?strategy a robo:AssetLocation ;
            robo:recommendsAccount ?recommendedAccount ;
            robo:estimatedTaxDrag ?taxDrag .
  FILTER (?currentAccount != ?recommendedAccount)
}
ORDER BY DESC(?taxDrag)

# Query 13: Dividend reinvestment tracking
# PARAM: ?portfolioId - Portfolio identifier
# PARAM: ?year - Calendar year
SELECT ?asset ?assetSymbol (SUM(?dividendAmount) AS ?totalDividends) (COUNT(?dividend) AS ?paymentCount)
WHERE {
  ?portfolio robo:portfolioId ?portfolioId ;
             robo:holdsAsset ?asset ;
             robo:executesTransaction ?transaction .
  ?transaction a robo:Dividend ;
               robo:asset ?asset ;
               robo:dividendAmount ?dividendAmount ;
               robo:paymentDate ?paymentDate .
  ?asset robo:assetSymbol ?assetSymbol .
  FILTER (YEAR(?paymentDate) = ?year)
}
GROUP BY ?asset ?assetSymbol
ORDER BY DESC(?totalDividends)

# Query 14: Behavioral analysis alerts
# PARAM: ?clientId - Client identifier
SELECT ?analysis ?behaviorType ?riskLevel ?recommendation ?detectedAt
WHERE {
  ?client robo:clientId ?clientId ;
          robo:hasRiskProfile ?profile .
  ?profile robo:hasBehavioralAnalysis ?analysis .
  ?analysis robo:behaviorType ?behaviorType ;
            robo:riskLevel ?riskLevel ;
            robo:recommendation ?recommendation ;
            robo:detectedAt ?detectedAt .
  FILTER (?riskLevel IN ("medium", "high"))
}
ORDER BY DESC(?detectedAt)

# Query 15: Compare portfolio to benchmark
# PARAM: ?portfolioId - Portfolio identifier
# PARAM: ?benchmarkId - Benchmark identifier
SELECT ?portfolio ?benchmark ?portfolioReturn ?benchmarkReturn ?activeReturn ?trackingError
WHERE {
  ?portfolio robo:portfolioId ?portfolioId ;
             robo:totalReturn ?portfolioReturn ;
             robo:comparesWith ?benchmark .
  ?benchmark robo:benchmarkId ?benchmarkId ;
             robo:totalReturn ?benchmarkReturn .
  BIND(?portfolioReturn - ?benchmarkReturn AS ?activeReturn)
  ?portfolio robo:trackingError ?trackingError .
}
