Alexo19 commited on
Commit
2554d9f
·
verified ·
1 Parent(s): 53f8b01

2️⃣ Prompt for DeepSite (supports Crypto + Forex)

Browse files

👉 Copy everything inside this box and paste it into DeepSite:
You are a senior full-stack AI engineer.

Build a production-ready project called **CryptoSignal-Sleuth** that works for **both crypto and forex**, not just Bitcoin.

Tech stack:
- Backend: FastAPI (Python 3)
- Frontend: React + TypeScript + Vite + TailwindCSS
- Models: Hugging Face (vision, OCR, sentiment, LLM reasoning)

The app will be deployed on **Hugging Face Spaces**.

====================================================
## 1. FEATURES

The app must do all of this:

1. Let the user **upload a screenshot** of a trading chart (crypto or forex):
- Run **vision + OCR** on the image.
- Extract basic info: trend (up/down/range), key levels, patterns if visible.
- Pass these cues into an LLM to generate a trading **signal**.

2. Let the user **analyze a market live** by sending:
```json
{
"symbol": "BTCUSDT" or "EURUSD",
"timeframe": "5m" or "15m" or "1h",
"asset_type": "crypto" or "forex"
}



Fetch OHLCV data.


Run technical indicators (EMA, RSI, MACD, ATR, support/resistance).


Optionally include sentiment.


Use an LLM to synthesize a final signal.




Provide a clean REST API + webhook so I can connect:


n8n


Discord bot


Telegram bot




====================================================
2. MARKETS: CRYPTO + FOREX
The app MUST support:
2.1 Crypto


Examples: BTCUSDT, ETHUSDT, SOLUSDT


Data source: Binance public klines (no key).


Implement a helper:


fetch_binance_klines(symbol: str, timeframe: str, limit: int = 200)




2.2 Forex


Examples: EURUSD, GBPUSD, USDJPY, XAUUSD, NAS100


Data source: use yfinance (or similar free source).


Implement helpers:


normalize_forex_symbol("EURUSD") -> "EURUSD=X"


fetch_yfinance_fx(symbol: str, timeframe: str, limit: int = 200)




2.3 Common wrapper
Create in backend/timeseries_analysis.py:


fetch_ohlcv(symbol: str, timeframe: str, asset_type: str = "crypto", limit: int = 200)


Logic:


If asset_type == "crypto" → call fetch_binance_klines.


If asset_type == "forex" → normalize symbol and call fetch_yfinance_fx.


Apply the same technical analysis (EMA, RSI, MACD, ATR, support/resistance, trend, momentum) to both crypto and forex.
====================================================
3. SIGNAL SCHEMA (VERY IMPORTANT)
All signals (image or market) MUST follow this JSON:
{
"direction": "long|short|neutral",
"entry_zone": [0.0, 0.0],
"stop_loss": 0.0,
"take_profit_levels": [0.0, 0.0, 0.0],
"timeframe_inferred": "1m|5m|15m|1h|4h|1d",
"confidence": 0,
"time_horizon": "intra-day|swing|position",
"explanation": "string",
"meta": {
"sources": [],
"sentiment": {}
}
}

Use Pydantic models so FastAPI enforces this structure.
====================================================
4. PROJECT STRUCTURE
Use this exact file structure:
app.py
backend/
config.py
main.py
models_registry.py
signal_engine.py
image_analysis.py
timeseries_analysis.py
sentiment_analysis.py
frontend/
index.html
package.json
tsconfig.json
vite.config.ts
postcss.config.js
tailwind.config.js
src/
index.css
main.tsx
App.tsx
lib/api.ts
pages/
Dashboard.tsx
Backtest.tsx
Settings.tsx
Docs.tsx
components/
Navbar.tsx
Sidebar.tsx
ChartUploadCard.tsx
PairSelector.tsx
SignalPanel.tsx
HistoryTable.tsx
ModelSettingsPanel.tsx
requirements.txt
Fill ALL of these files with real, working code.
====================================================
5. BACKEND DETAILS
5.1 Config
backend/config.py:


Pydantic settings class that loads:


HF_TOKEN


USE_INFERENCE_API (default "1")


INFERENCE_LLM_MODEL (default "Qwen/Qwen2.5-7B-Instruct")


LOCAL_LLM_MODEL (default "google/flan-t5-base")


FRONTEND_BASE_PATH (default "/")


API_BASE_URL (default "/")


WEBHOOK_API_KEY (optional)




5.2 Models Registry
backend/models_registry.py:


Functions using Hugging Face Inference API (with HF_TOKEN):


analyze_chart_image(image_bytes) -> dict


run_ocr(image_bytes) -> dict


analyze_sentiment(texts: list[str]) -> dict


llm_reason(prompt: str) -> str




5.3 Image Analysis
backend/image_analysis.py:


extract_chart_features(image_bytes) -> dict:


Use vision + OCR to infer:


trend: up/down/range


key levels


any visible pattern labels


possible timeframe if visible






5.4 Time-Series Analysis
backend/timeseries_analysis.py:


Implement:


fetch_ohlcv (crypto + forex wrapper as described above).


compute_technicals(ohlcv) -> dict:


EMA fast/slow


RSI


MACD


ATR


support/resistance


trend and momentum labels.






5.5 Sentiment Analysis
backend/sentiment_analysis.py:


Fetch recent crypto/forex headlines (e.g. with RSS or generic feed).


Run sentiment model.


Return {"bullish": x, "bearish": y, "neutral": z, "summary": "..."}


This is stored in meta["sentiment"].


5.6 Signal Engine
backend/signal_engine.py:
Implement:


generate_signal_from_image(image_bytes) -> dict


generate_signal_from_market(symbol: str, timeframe: str, asset_type: str, ohlcv, technicals) -> dict


Build a prompt for the LLM that includes:


asset_type (crypto or forex)


symbol


timeframe


recent price action


trend & momentum


volatility


sentiment summary


image cues (if using screenshot)


Ask the LLM to output a decision that maps cleanly into the Signal schema above.
5.7 Main FastAPI App
backend/main.py routes:


GET /api/health → { "status": "ok" }


GET /api/models → shows which HF models are active.


POST /api/analyze/screenshot


multipart/form-data, field name: file.


returns Signal JSON.




POST /api/analyze/market


JSON body:
{ "symbol": "EURUSD", "timeframe": "5m", "asset_type": "forex" }



returns Signal JSON.




POST /api/webhook/signal


optional header X-API-KEY == WEBHOOK_API_KEY.


accepts any valid Signal JSON and echoes it (for n8n integration).




5.8 app.py


Create FastAPI app.


Include backend router at /api.


Serve frontend static files from frontend/dist at /.


Use FRONTEND_BASE_PATH and API_BASE_URL if needed.


====================================================
6. FRONTEND (React + TypeScript + Vite + Tailwind)
Implement the frontend with a dark trading dashboard look.
6.1 API Client
frontend/src/lib/api.ts:


Base URL: import.meta.env.VITE_API_BASE_URL || "/api"


Functions:


uploadChart(file: File): Promise<SignalResponse>


getMarketSignal(symbol: string, timeframe: string, asset_type: "crypto"|"forex"): Promise<SignalResponse>


getModels()


postWebhookSignal(payload: any)




Define SignalResponse TypeScript interface using the Signal schema.
6.2 Components / Pages


Navbar + Sidebar layout.


Dashboard page:


ChartUploadCard → upload screenshot, show returned signal in SignalPanel.


PairSelector:


Input/select for symbol (BTCUSDT, ETHUSDT, EURUSD, GBPUSD, XAUUSD, etc.)


Select for timeframe.


Dropdown for asset_type ("crypto" or "forex").


Button → calls getMarketSignal.




SignalPanel displays the SignalResponse nicely (direction, entry zone, SL, TP1–3, confidence, explanation, sentiment).


HistoryTable → shows a list of signals from the current session.




Backtest:


Simple placeholder explaining that backtesting is coming later.




Settings:


Show data from /api/models.


Show current base URLs and some info text.




Docs:


Show example request/response for:


/api/analyze/market


/api/analyze/screenshot


/api/webhook/signal






====================================================
7. REQUIREMENTS + ENV
requirements.txt should include at least:


fastapi


uvicorn[standard]


python-multipart


pydantic


httpx or requests


numpy


pandas (if needed)


ta (or manual indicator math)


yfinance


feedparser (or similar)


huggingface-hub or transformers (if needed)


jinja2 (if needed)


Also output a .env.example with:


HF_TOKEN=


USE_INFERENCE_API=1


INFERENCE_LLM_MODEL=Qwen/Qwen2.5-7B-Instruct


LOCAL_LLM_MODEL=google/flan-t5-base


FRONTEND_BASE_PATH=/


API_BASE_URL=/api


WEBHOOK_API_KEY=


====================================================
8. SUMMARY
At the very end of your answer, add a short summary:


How to install and run locally:


pip install -r requirements.txt


cd frontend && npm install && npm run build


uvicorn app:app --host 0.0.0.0 --port 7860




How to deploy on Hugging Face Spaces with app.py as the entrypoint.


Generate the COMPLETE codebase with no TODOs or placeholders.

---

If you want next, I can help you with the **exact JSON body** to use in n8n, or with a **Discord bot command** like `/signal EURUSD 5m forex` that calls your new API.
::contentReference[oaicite:0]{index=0}

.env.example CHANGED
@@ -11,6 +11,4 @@ API_BASE_URL=/api
11
 
12
  # Security
13
  WEBHOOK_API_KEY=your_secure_api_key_here
14
- ```
15
-
16
- 6. For the frontend, let's create a basic setup:
 
11
 
12
  # Security
13
  WEBHOOK_API_KEY=your_secure_api_key_here
14
+ ```
 
 
app.py CHANGED
@@ -22,6 +22,4 @@ app.mount(
22
  if __name__ == "__main__":
23
  import uvicorn
24
  uvicorn.run(app, host="0.0.0.0", port=7860)
25
- ```
26
-
27
- 4. Let's create the requirements.txt:
 
22
  if __name__ == "__main__":
23
  import uvicorn
24
  uvicorn.run(app, host="0.0.0.0", port=7860)
25
+ ```
 
 
backend/config.py CHANGED
@@ -8,7 +8,7 @@ class Settings(BaseSettings):
8
  INFERENCE_LLM_MODEL: str = "Qwen/Qwen2.5-7B-Instruct"
9
  LOCAL_LLM_MODEL: str = "google/flan-t5-base"
10
  FRONTEND_BASE_PATH: str = "/"
11
- API_BASE_URL: str = "/"
12
  WEBHOOK_API_KEY: Optional[str] = None
13
 
14
  class Config:
 
8
  INFERENCE_LLM_MODEL: str = "Qwen/Qwen2.5-7B-Instruct"
9
  LOCAL_LLM_MODEL: str = "google/flan-t5-base"
10
  FRONTEND_BASE_PATH: str = "/"
11
+ API_BASE_URL: str = "/api"
12
  WEBHOOK_API_KEY: Optional[str] = None
13
 
14
  class Config:
backend/main.py CHANGED
@@ -5,9 +5,11 @@ from fastapi.security import APIKeyHeader
5
  from typing import Optional
6
  import io
7
  from .config import get_settings
8
- from .signal_engine import generate_signal_from_image
9
- from .timeseries_analysis import fetch_klines, compute_technicals
 
10
  from .models_registry import model_registry
 
11
 
12
  app = FastAPI(title="CryptoSignal Sleuth Pro API")
13
 
@@ -46,7 +48,7 @@ async def market_analysis(
46
  timeframe: str = "1h"
47
  ):
48
  try:
49
- ohlcv = await fetch_klines(symbol, timeframe)
50
  technicals = compute_technicals(ohlcv)
51
  sentiment = await get_crypto_sentiment(symbol[:3])
52
 
@@ -66,6 +68,7 @@ async def webhook_handler(
66
  ):
67
  # Process webhook payload here
68
  return {"status": "received", "data": payload}
 
69
  @app.get("/api/health")
70
  async def health_check():
71
  return {"status": "ok"}
@@ -94,7 +97,6 @@ async def analyze_screenshot(
94
  image_bytes = await file.read()
95
  signal = await generate_signal_from_image(image_bytes, symbol or "BTCUSDT")
96
  return signal
97
- from pydantic import BaseModel
98
 
99
  class MarketRequest(BaseModel):
100
  symbol: str
@@ -117,7 +119,7 @@ async def analyze_market(request: MarketRequest):
117
  ohlcv=ohlcv,
118
  technicals=technicals
119
  )
120
- except Exception as e:
121
  raise HTTPException(500, detail=str(e))
122
 
123
  @app.post("/api/webhook/signal")
@@ -132,7 +134,4 @@ async def webhook_signal(
132
  # Log the signal
133
  print(f"Received signal: {payload}")
134
  return {"status": "received", "signal": payload}
135
- ```
136
- ___METADATA_START___
137
- {"repoId":"Alexo19/cryptosignal-sleuth-pro","isNew":false,"userName":"Alexo19"}
138
- ___METADATA_END___
 
5
  from typing import Optional
6
  import io
7
  from .config import get_settings
8
+ from .signal_engine import generate_signal_from_image, generate_signal_from_market
9
+ from .timeseries_analysis import fetch_ohlcv, compute_technicals
10
+ from .sentiment_analysis import get_crypto_sentiment
11
  from .models_registry import model_registry
12
+ from pydantic import BaseModel
13
 
14
  app = FastAPI(title="CryptoSignal Sleuth Pro API")
15
 
 
48
  timeframe: str = "1h"
49
  ):
50
  try:
51
+ ohlcv = await fetch_ohlcv(symbol, timeframe)
52
  technicals = compute_technicals(ohlcv)
53
  sentiment = await get_crypto_sentiment(symbol[:3])
54
 
 
68
  ):
69
  # Process webhook payload here
70
  return {"status": "received", "data": payload}
71
+
72
  @app.get("/api/health")
73
  async def health_check():
74
  return {"status": "ok"}
 
97
  image_bytes = await file.read()
98
  signal = await generate_signal_from_image(image_bytes, symbol or "BTCUSDT")
99
  return signal
 
100
 
101
  class MarketRequest(BaseModel):
102
  symbol: str
 
119
  ohlcv=ohlcv,
120
  technicals=technicals
121
  )
122
+ except Exception as e:
123
  raise HTTPException(500, detail=str(e))
124
 
125
  @app.post("/api/webhook/signal")
 
134
  # Log the signal
135
  print(f"Received signal: {payload}")
136
  return {"status": "received", "signal": payload}
137
+ ```
 
 
 
backend/models_registry.py CHANGED
@@ -28,7 +28,7 @@ class ModelRegistry:
28
 
29
  async def run_ocr(self, image_bytes: bytes) -> Dict[str, Any]:
30
  if should_use_inference_api():
31
- response = self_client.image_to_text(image=image_bytes)
32
  return {"text": response}
33
  else:
34
  # Simple fallback
 
28
 
29
  async def run_ocr(self, image_bytes: bytes) -> Dict[str, Any]:
30
  if should_use_inference_api():
31
+ response = self.client.image_to_text(image=image_bytes)
32
  return {"text": response}
33
  else:
34
  # Simple fallback
backend/signal_engine.py CHANGED
@@ -2,7 +2,7 @@
2
  from typing import Dict, Any
3
  import json
4
  from .image_analysis import extract_chart_features
5
- from .timeseries_analysis import fetch_klines, compute_technicals
6
  from .sentiment_analysis import get_crypto_sentiment
7
  from .models_registry import model_registry
8
 
@@ -12,7 +12,7 @@ async def generate_signal_from_image(image_bytes: bytes, symbol: str = "BTCUSDT"
12
 
13
  # Get technical analysis
14
  timeframe = chart_features.get("timeframe", "1h")
15
- ohlcv = await fetch_klines(symbol, timeframe)
16
  technicals = compute_technicals(ohlcv)
17
 
18
  # Get sentiment analysis
@@ -64,6 +64,7 @@ Provide your response in this exact JSON format:
64
  "sentiment": {{}}
65
  }}
66
  }}"""
 
67
  async def generate_signal_from_market(
68
  symbol: str,
69
  timeframe: str,
@@ -84,11 +85,13 @@ async def generate_signal_from_market(
84
 
85
  # Prepare LLM prompt
86
  prompt = build_market_prompt(technicals, sentiment, symbol, timeframe, asset_type)
87
- # Get LLM reasoning
 
88
  llm_response = await model_registry.llm_reason(prompt)
89
 
90
  # Parse response into structured format
91
  return parse_llm_response(llm_response, {}, technicals, sentiment)
 
92
  def build_market_prompt(
93
  technicals: Dict,
94
  sentiment: Dict,
@@ -98,6 +101,7 @@ def build_market_prompt(
98
  ) -> str:
99
  asset_type_str = "cryptocurrency" if asset_type == "crypto" else "forex"
100
  return f"""Analyze this {asset_type_str} trading situation and provide a professional trading signal in JSON format:
 
101
  Technical Indicators ({timeframe} timeframe):
102
  - Trend: {technicals['trend']}
103
  - Momentum: {technicals['momentum']}
@@ -129,7 +133,7 @@ Provide your response in this exact JSON format:
129
  }}"""
130
 
131
  def parse_llm_response(response: str, chart_features: Dict, technicals: Dict, sentiment: Dict) -> Dict[str, Any]:
132
- try:
133
  data = json.loads(response.strip())
134
  if not isinstance(data, dict):
135
  raise ValueError("Invalid response format")
 
2
  from typing import Dict, Any
3
  import json
4
  from .image_analysis import extract_chart_features
5
+ from .timeseries_analysis import fetch_ohlcv, compute_technicals
6
  from .sentiment_analysis import get_crypto_sentiment
7
  from .models_registry import model_registry
8
 
 
12
 
13
  # Get technical analysis
14
  timeframe = chart_features.get("timeframe", "1h")
15
+ ohlcv = await fetch_ohlcv(symbol, timeframe)
16
  technicals = compute_technicals(ohlcv)
17
 
18
  # Get sentiment analysis
 
64
  "sentiment": {{}}
65
  }}
66
  }}"""
67
+
68
  async def generate_signal_from_market(
69
  symbol: str,
70
  timeframe: str,
 
85
 
86
  # Prepare LLM prompt
87
  prompt = build_market_prompt(technicals, sentiment, symbol, timeframe, asset_type)
88
+
89
+ # Get LLM reasoning
90
  llm_response = await model_registry.llm_reason(prompt)
91
 
92
  # Parse response into structured format
93
  return parse_llm_response(llm_response, {}, technicals, sentiment)
94
+
95
  def build_market_prompt(
96
  technicals: Dict,
97
  sentiment: Dict,
 
101
  ) -> str:
102
  asset_type_str = "cryptocurrency" if asset_type == "crypto" else "forex"
103
  return f"""Analyze this {asset_type_str} trading situation and provide a professional trading signal in JSON format:
104
+
105
  Technical Indicators ({timeframe} timeframe):
106
  - Trend: {technicals['trend']}
107
  - Momentum: {technicals['momentum']}
 
133
  }}"""
134
 
135
  def parse_llm_response(response: str, chart_features: Dict, technicals: Dict, sentiment: Dict) -> Dict[str, Any]:
136
+ try:
137
  data = json.loads(response.strip())
138
  if not isinstance(data, dict):
139
  raise ValueError("Invalid response format")
backend/timeseries_analysis.py CHANGED
@@ -22,7 +22,8 @@ async def fetch_binance_klines(symbol: str, timeframe: str, limit: int = 200) ->
22
  response = requests.get(BINANCE_API_URL, params=params)
23
  response.raise_for_status()
24
  return response.json()
25
- def fetch_yfinance_fx(symbol: str, timeframe: str, limit: int = 200) -> List[List[Any]]:
 
26
  """Fetch forex data using yfinance"""
27
  tf_map = {
28
  '1m': '1m', '5m': '5m', '15m': '15m',
@@ -30,7 +31,7 @@ def fetch_yfinance_fx(symbol: str, timeframe: str, limit: int = 200) -> List[Lis
30
  '1D': '1d', '1W': '1wk', '1M': '1mo',
31
  '1d': '1d', '4h': '4h' # Add common aliases
32
  }
33
- interval = tf_map.get(timeframe, '1h')
34
 
35
  ticker = normalize_forex_symbol(symbol)
36
  data = yf.Ticker(ticker)
@@ -56,9 +57,10 @@ async def fetch_ohlcv(
56
  if asset_type == "crypto":
57
  return await fetch_binance_klines(symbol, timeframe, limit)
58
  elif asset_type == "forex":
59
- return fetch_yfinance_fx(symbol, timeframe, limit)
60
  else:
61
  raise ValueError("Unsupported asset_type. Must be 'crypto' or 'forex'")
 
62
  def compute_technicals(ohlcv: List[List[Any]]) -> Dict[str, Any]:
63
  # Convert to pandas DataFrame
64
  df = pd.DataFrame(ohlcv, columns=["timestamp", "open", "high", "low", "close", "volume"])
 
22
  response = requests.get(BINANCE_API_URL, params=params)
23
  response.raise_for_status()
24
  return response.json()
25
+
26
+ async def fetch_yfinance_fx(symbol: str, timeframe: str, limit: int = 200) -> List[List[Any]]:
27
  """Fetch forex data using yfinance"""
28
  tf_map = {
29
  '1m': '1m', '5m': '5m', '15m': '15m',
 
31
  '1D': '1d', '1W': '1wk', '1M': '1mo',
32
  '1d': '1d', '4h': '4h' # Add common aliases
33
  }
34
+ interval = tf_map.get(timeframe, '1h')
35
 
36
  ticker = normalize_forex_symbol(symbol)
37
  data = yf.Ticker(ticker)
 
57
  if asset_type == "crypto":
58
  return await fetch_binance_klines(symbol, timeframe, limit)
59
  elif asset_type == "forex":
60
+ return await fetch_yfinance_fx(symbol, timeframe, limit)
61
  else:
62
  raise ValueError("Unsupported asset_type. Must be 'crypto' or 'forex'")
63
+
64
  def compute_technicals(ohlcv: List[List[Any]]) -> Dict[str, Any]:
65
  # Convert to pandas DataFrame
66
  df = pd.DataFrame(ohlcv, columns=["timestamp", "open", "high", "low", "close", "volume"])
requirements.txt CHANGED
@@ -11,6 +11,4 @@ huggingface-hub==0.15.1
11
  transformers==4.29.2
12
  python-dotenv==1.0.0
13
  yfinance==0.2.28
14
- ```
15
-
16
- 5. Let's create the .env.example file:
 
11
  transformers==4.29.2
12
  python-dotenv==1.0.0
13
  yfinance==0.2.28
14
+ ```