TL;DR: When you are done you get what I would call an App (with internal AI, ability to upload documents, search the web and be modified by the user). Joel Greenblatt as an example:
Want to explore investor-style AI workflows? Try this:
- Copy the code below
- Visit this link: Claude Artifact Workspace (a free membership should work)
- Type: “Create an artifact with this code”
- Paste or upload the code
- Enter the name of your favorite investor into the Artifact
- Ask Claude to customize the Artifact with your own ideas or improvements
Important: Turn on " Create AI-powered artifacts" in the settings. This allow Claude AI to work within the artifact.
This is an early proof of concept. You may need to refine the generated code before using it in a ranking system. However, if this approach gains traction, we could develop a set of standard uploads—or a shared link—containing properly formatted P123 feature code (with additional resources). This would allow AI-generated features to be copied and pasted directly into ranking systems with minimal adjustments. I haven’t implemented that here, but members and staff could collaborate on it if we decide to adopt Artifacts more broadly.
If there’s enough interest, we could build a shared library of AI-generated investing Artifacts and standard tools, contributed by both members and staff.
Note: When you copy and run an Artifact, it operates entirely within your own Claude account (it will work with free accounts). The original creator’s account is neither accessed or billed.
import React, { useState } from 'react';
import { Search, TrendingUp, Copy, CheckCircle, User } from 'lucide-react';
const InvestorRankingGenerator = () => {
const [investorName, setInvestorName] = useState('');
const [loading, setLoading] = useState(false);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
const [copiedIndex, setCopiedIndex] = useState(null);
const generateRanking = async () => {
if (!investorName.trim()) return;
setLoading(true);
setError(null);
setResult(null);
try {
const prompt = `
You are an expert in quantitative investment analysis and Portfolio 123 ranking systems.
Research the investment philosophy and methodology of ${investorName}. Then generate a Portfolio 123 ranking system that captures their investment style.
Respond with ONLY valid JSON in this exact format:
{
"investor": "Investor Name",
"philosophy": "Brief description of their investment approach",
"factors": [
{
"name": "Factor Name",
"description": "Why this factor represents their style",
"weight": 25,
"formula": "Portfolio 123 formula syntax"
}
],
"rankingFormula": "Combined Portfolio 123 ranking formula",
"explanation": "How this ranking system reflects their methodology"
}
Important:
- Use actual Portfolio 123 syntax for formulas (e.g., "ROE()", "PERatio()", "DebtToEquity()")
- Weights should sum to 100
- Include 4-6 key factors that best represent their style
- Make formulas implementable in Portfolio 123
CRITICAL: Your entire response must be ONLY the JSON object. DO NOT include markdown code blocks, backticks, or any other text. Start directly with { and end with }.
`;
const response = await window.claude.complete(prompt);
// Handle potential markdown wrapping
let cleanResponse = response.trim();
if (cleanResponse.startsWith('```json')) {
cleanResponse = cleanResponse.replace(/```json\s*/, '').replace(/```\s*$/, '');
}
if (cleanResponse.startsWith('```')) {
cleanResponse = cleanResponse.replace(/```\s*/, '').replace(/```\s*$/, '');
}
const parsedResult = JSON.parse(cleanResponse);
setResult(parsedResult);
} catch (err) {
setError('Failed to generate ranking system. Please try again.');
console.error('Error:', err);
} finally {
setLoading(false);
}
};
const copyToClipboard = async (text, index) => {
try {
await navigator.clipboard.writeText(text);
setCopiedIndex(index);
setTimeout(() => setCopiedIndex(null), 2000);
} catch (err) {
console.error('Failed to copy:', err);
}
};
return (
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-blue-900 to-slate-900 text-white">
<div className="container mx-auto px-4 py-8">
{/* Header */}
<div className="text-center mb-12">
<div className="flex items-center justify-center gap-3 mb-6">
<TrendingUp className="w-12 h-12 text-blue-400" />
<h1 className="text-4xl font-bold bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent">
Investor Style Ranking Generator
</h1>
</div>
<p className="text-xl text-slate-300 max-w-2xl mx-auto">
Transform any investor's philosophy into Portfolio 123 ranking formulas
</p>
</div>
{/* Input Form */}
<div className="max-w-2xl mx-auto mb-12">
<div className="space-y-6">
<div className="relative">
<User className="absolute left-4 top-4 w-5 h-5 text-slate-400" />
<input
type="text"
value={investorName}
onChange={(e) => setInvestorName(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && generateRanking()}
placeholder="Enter investor name (e.g., Warren Buffett, Peter Lynch, Joel Greenblatt)"
className="w-full pl-12 pr-4 py-4 bg-slate-800/50 border border-slate-600 rounded-xl text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-lg"
/>
</div>
<button
onClick={generateRanking}
disabled={loading || !investorName.trim()}
className="w-full py-4 px-6 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 disabled:from-slate-600 disabled:to-slate-600 disabled:cursor-not-allowed rounded-xl font-semibold text-lg transition-all duration-200 flex items-center justify-center gap-2"
>
{loading ? (
<>
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
Researching {investorName}…
</>
) : (
<>
<Search className="w-5 h-5" />
Generate Ranking System
</>
)}
</button>
</div>
</div>
{/* Error Display */}
{error && (
<div className="max-w-4xl mx-auto mb-8 p-4 bg-red-900/20 border border-red-700 rounded-xl">
<p className="text-red-300">{error}</p>
</div>
)}
{/* Results */}
{result && (
<div className="max-w-6xl mx-auto space-y-8">
{/* Investor Overview */}
<div className="bg-slate-800/30 backdrop-blur-sm border border-slate-700 rounded-xl p-6">
<h2 className="text-2xl font-bold mb-4 text-blue-400">{result.investor}</h2>
<p className="text-slate-300 text-lg leading-relaxed">{result.philosophy}</p>
</div>
{/* Factors */}
<div className="bg-slate-800/30 backdrop-blur-sm border border-slate-700 rounded-xl p-6">
<h3 className="text-xl font-bold mb-6 text-purple-400">Ranking Factors</h3>
<div className="grid gap-4">
{result.factors.map((factor, index) => (
<div key={index} className="bg-slate-900/40 border border-slate-600 rounded-lg p-4">
<div className="flex items-start justify-between mb-2">
<h4 className="text-lg font-semibold text-white">{factor.name}</h4>
<span className="bg-blue-600 text-white px-2 py-1 rounded-md text-sm font-medium">
{factor.weight}%
</span>
</div>
<p className="text-slate-300 mb-3">{factor.description}</p>
<div className="bg-slate-800 rounded-md p-3 font-mono text-sm">
<div className="flex items-center justify-between">
<code className="text-green-400">{factor.formula}</code>
<button
onClick={() => copyToClipboard(factor.formula, `factor-${index}`)}
className="ml-2 p-1 hover:bg-slate-700 rounded transition-colors"
>
{copiedIndex === `factor-${index}` ? (
<CheckCircle className="w-4 h-4 text-green-400" />
) : (
<Copy className="w-4 h-4 text-slate-400" />
)}
</button>
</div>
</div>
</div>
))}
</div>
</div>
{/* Implementation Framework */}
<div className="bg-slate-800/30 backdrop-blur-sm border border-slate-700 rounded-xl p-6">
<h3 className="text-xl font-bold mb-4 text-purple-400">Implementation Framework</h3>
{/* Factor Summary */}
<div className="mb-6">
<h4 className="text-lg font-semibold mb-3 text-white">Factor Weights Summary</h4>
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
{result.factors.map((factor, index) => (
<div key={index} className="bg-slate-900/40 border border-slate-600 rounded-lg p-3">
<div className="flex justify-between items-center">
<span className="text-white font-medium">{factor.name}</span>
<span className="bg-blue-600 text-white px-2 py-1 rounded text-sm font-medium">
{factor.weight}%
</span>
</div>
</div>
))}
</div>
</div>
{/* Sample Code */}
<div className="mb-4">
<h4 className="text-lg font-semibold mb-3 text-white">Sample Portfolio 123 Code Structure</h4>
<div className="bg-slate-900/60 rounded-lg p-4">
<div className="flex items-start justify-between">
<code className="text-green-400 font-mono text-sm leading-relaxed break-all">
{result.rankingFormula}
</code>
<button
onClick={() => copyToClipboard(result.rankingFormula, 'main-formula')}
className="ml-3 p-2 hover:bg-slate-700 rounded transition-colors flex-shrink-0"
>
{copiedIndex === 'main-formula' ? (
<CheckCircle className="w-5 h-5 text-green-400" />
) : (
<Copy className="w-5 h-5 text-slate-400" />
)}
</button>
</div>
</div>
</div>
<p className="text-slate-300 leading-relaxed">{result.explanation}</p>
</div>
{/* Implementation Guide */}
<div className="bg-gradient-to-r from-blue-900/20 to-purple-900/20 border border-blue-700/50 rounded-xl p-6">
<h3 className="text-xl font-bold mb-4 text-blue-400">Portfolio 123 Implementation Guide</h3>
<div className="space-y-4 text-slate-300">
<div>
<h4 className="font-semibold text-white mb-2">Step 1: Create Individual Factors</h4>
<p>Use the factor formulas above as starting points. You may need to adjust function names to match your Portfolio 123 version (e.g., ROE() vs Return_on_Equity).</p>
</div>
<div>
<h4 className="font-semibold text-white mb-2">Step 2: Build Your Ranking System</h4>
<p>Create a new ranking system combining these factors with the suggested weights. Start with the sample code structure and adapt the syntax to your Portfolio 123 environment.</p>
</div>
<div>
<h4 className="font-semibold text-white mb-2">Step 3: Test and Refine</h4>
<p>Backtest the ranking system and adjust weights based on performance. The suggested weights are starting points - optimize them for your specific goals and risk tolerance.</p>
</div>
<div>
<h4 className="font-semibold text-white mb-2">Note on Code Syntax</h4>
<p className="text-yellow-300">⚠️ The code provided is a best-effort approximation. Portfolio 123 function names and syntax may vary. Use this as a framework and adapt to your specific Portfolio 123 setup.</p>
</div>
</div>
</div>
</div>
)}
</div>
</div>
);
};
export default InvestorRankingGenerator;

