feat: implement comprehensive Technical Analysis fundamentals

- Add TECHNICAL_ANALYSIS_BASICS.md with complete indicator explanations
- Add TA_QUICK_REFERENCE.md for quick lookup
- Enhance AI analysis prompts with TA principles integration
- Improve JSON response structure with dedicated analysis sections
- Add cross-layout consensus analysis for higher confidence signals
- Include timeframe-specific risk assessment and position sizing
- Add educational content for RSI, MACD, EMAs, Stochastic RSI, VWAP, OBV
- Implement layout-specific analysis (AI vs DIY layouts)
- Add momentum, trend, and volume analysis separation
- Update README with TA documentation references
- Create implementation summary and test files
This commit is contained in:
mindesbunister
2025-07-18 11:45:58 +02:00
parent 5bd2f97c26
commit 1a7bdb4109
15 changed files with 1483 additions and 213 deletions

View File

@@ -63,26 +63,45 @@ export default function ScreenshotGallery({
return `${tf}m`
}
// Create sorted screenshot data with timeframes
// Helper function to detect layout from filename
const detectLayout = (filename: string) => {
if (filename.includes('_ai_')) return 'AI'
if (filename.includes('_diy_') || filename.includes('_Diy module_')) return 'DIY'
return 'Default'
}
// Create screenshot data with layout and timeframe information
const screenshotData = screenshots.map((screenshot, index) => {
const screenshotUrl = typeof screenshot === 'string'
? screenshot
: (screenshot as any)?.url || String(screenshot)
const filename = screenshotUrl.split('/').pop() || ''
const timeframe = timeframes[index] || extractTimeframeFromFilename(filename)
const layout = detectLayout(filename)
return {
screenshot,
screenshotUrl,
filename,
timeframe,
layout,
index,
sortOrder: timeframeToMinutes(timeframe)
}
})
// Sort by timeframe (smallest to largest)
const sortedData = screenshotData.sort((a, b) => a.sortOrder - b.sortOrder)
// Group screenshots by layout
const aiScreenshots = screenshotData
.filter(item => item.layout === 'AI')
.sort((a, b) => a.sortOrder - b.sortOrder)
const diyScreenshots = screenshotData
.filter(item => item.layout === 'DIY')
.sort((a, b) => a.sortOrder - b.sortOrder)
const defaultScreenshots = screenshotData
.filter(item => item.layout === 'Default')
.sort((a, b) => a.sortOrder - b.sortOrder)
// Helper function to format screenshot URL
const formatScreenshotUrl = (screenshot: string | any) => {
@@ -94,24 +113,24 @@ export default function ScreenshotGallery({
return `/api/image?file=${filename}`
}
return (
<>
{/* Gallery Grid */}
<div className="mt-6 p-4 bg-gradient-to-br from-purple-500/10 to-indigo-500/10 border border-purple-500/30 rounded-lg">
<div className="flex items-center justify-between mb-4">
<h4 className="text-lg font-bold text-white flex items-center">
<span className="w-6 h-6 bg-gradient-to-br from-purple-400 to-purple-600 rounded-lg flex items-center justify-center mr-2 text-sm">
📸
</span>
Chart Screenshots
</h4>
// Helper function to render a screenshot row
const renderScreenshotRow = (screenshots: any[], title: string, icon: string, bgGradient: string) => {
if (screenshots.length === 0) return null
return (
<div className="mb-6">
<div className="flex items-center justify-between mb-3">
<h5 className={`text-sm font-bold text-white flex items-center bg-gradient-to-r ${bgGradient} px-3 py-1 rounded-lg`}>
<span className="mr-2">{icon}</span>
{title}
</h5>
<div className="text-xs text-gray-400">
{sortedData.length} captured Click to enlarge
{screenshots.length} screenshot{screenshots.length !== 1 ? 's' : ''}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{sortedData.map((item, displayIndex) => {
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3">
{screenshots.map((item, displayIndex) => {
const imageUrl = formatScreenshotUrl(item.screenshot)
return (
@@ -124,7 +143,7 @@ export default function ScreenshotGallery({
<div className="aspect-video bg-gray-800 flex items-center justify-center relative">
<img
src={imageUrl}
alt={`${symbol} - ${item.timeframe} chart`}
alt={`${symbol} - ${item.timeframe} chart (${item.layout} Layout)`}
className="w-full h-full object-cover"
onError={(e: any) => {
const target = e.target as HTMLImageElement
@@ -168,6 +187,57 @@ export default function ScreenshotGallery({
})}
</div>
</div>
)
}
return (
<>
{/* Gallery Grid */}
<div className="mt-6 p-4 bg-gradient-to-br from-purple-500/10 to-indigo-500/10 border border-purple-500/30 rounded-lg">
<div className="flex items-center justify-between mb-4">
<h4 className="text-lg font-bold text-white flex items-center">
<span className="w-6 h-6 bg-gradient-to-br from-purple-400 to-purple-600 rounded-lg flex items-center justify-center mr-2 text-sm">
📸
</span>
Chart Screenshots
</h4>
<div className="text-xs text-gray-400">
{screenshotData.length} captured Click to enlarge
</div>
</div>
{/* AI Layout Row */}
{renderScreenshotRow(
aiScreenshots,
'AI Layout - RSI, EMAs, MACD',
'🤖',
'from-blue-500/30 to-cyan-500/30'
)}
{/* DIY Layout Row */}
{renderScreenshotRow(
diyScreenshots,
'DIY Module Layout - Stochastic RSI, VWAP, OBV',
'🔧',
'from-orange-500/30 to-yellow-500/30'
)}
{/* Default Layout Row (if any) */}
{renderScreenshotRow(
defaultScreenshots,
'Default Layout',
'📊',
'from-purple-500/30 to-indigo-500/30'
)}
{/* No Screenshots Message */}
{screenshotData.length === 0 && (
<div className="text-center py-8 text-gray-400">
<div className="text-3xl mb-2">📊</div>
<div className="text-sm">No screenshots available</div>
</div>
)}
</div>
{/* Enlarged Image Modal */}
{enlargedImage && (