Alexo19 commited on
Commit
53f8b01
·
verified ·
1 Parent(s): 84be386

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}

backend/timeseries_analysis.py CHANGED
@@ -22,15 +22,15 @@ 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
-
26
  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',
30
  '30m': '30m', '1h': '1h', '4h': '4h',
31
- '1D': '1d', '1W': '1wk', '1M': '1mo'
 
32
  }
33
- interval = tf_map.get(timeframe, '1h')
34
 
35
  ticker = normalize_forex_symbol(symbol)
36
  data = yf.Ticker(ticker)
 
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',
29
  '30m': '30m', '1h': '1h', '4h': '4h',
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)
components/forex-selector.js ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class ForexSelector extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.attachShadow({ mode: 'open' });
5
+ this.shadowRoot.innerHTML = `
6
+ <style>
7
+ select, input {
8
+ background: rgba(30, 41, 59, 0.8);
9
+ border: 1px solid rgba(255, 255, 255, 0.1);
10
+ color: white;
11
+ padding: 0.5rem;
12
+ border-radius: 0.375rem;
13
+ width: 100%;
14
+ }
15
+ label {
16
+ display: block;
17
+ margin-bottom: 0.5rem;
18
+ font-size: 0.875rem;
19
+ color: #94a3b8;
20
+ }
21
+ .form-group {
22
+ margin-bottom: 1rem;
23
+ }
24
+ </style>
25
+ <div class="form-group">
26
+ <label for="forex-pair">Forex Pair</label>
27
+ <input id="forex-pair" type="text" placeholder="EURUSD" list="common-pairs">
28
+ <datalist id="common-pairs">
29
+ <option>EURUSD</option>
30
+ <option>GBPUSD</option>
31
+ <option>USDJPY</option>
32
+ <option>AUDUSD</option>
33
+ <option>USDCAD</option>
34
+ <option>XAUUSD</option>
35
+ <option>NAS100</option>
36
+ </datalist>
37
+ </div>
38
+ `;
39
+ }
40
+ }
41
+
42
+ customElements.define('forex-selector', ForexSelector);
index.html CHANGED
@@ -58,14 +58,15 @@
58
  <div>
59
  <label class="block text-sm font-medium mb-1">Exchange</label>
60
  <select class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 focus:ring-indigo-500 focus:border-indigo-500">
61
- <option value="crypto">Binance (Crypto)</option>
62
- <option value="forex">Forex</option>
63
  </select>
64
  </div>
65
  <div>
66
  <label class="block text-sm font-medium mb-1">Pair</label>
67
- <input type="text" id="pair-input" placeholder="BTCUSDT" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 focus:ring-indigo-500 focus:border-indigo-500">
68
- </div>
 
69
  <div>
70
  <label class="block text-sm font-medium mb-1">Timeframe</label>
71
  <select class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 focus:ring-indigo-500 focus:border-indigo-500">
@@ -116,5 +117,22 @@
116
  <span class="text-gray-400">Take Profit 2</span>
117
  <span id="tp2{"ok":false,"message":"terminated"}
118
  <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
119
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  </html>
 
58
  <div>
59
  <label class="block text-sm font-medium mb-1">Exchange</label>
60
  <select class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 focus:ring-indigo-500 focus:border-indigo-500">
61
+ <option value="crypto">Crypto (Binance)</option>
62
+ <option value="forex">Forex (yFinance)</option>
63
  </select>
64
  </div>
65
  <div>
66
  <label class="block text-sm font-medium mb-1">Pair</label>
67
+ <input type="text" id="pair-input" placeholder="BTCUSDT or EURUSD" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 focus:ring-indigo-500 focus:border-indigo-500">
68
+ <forex-selector class="mt-2 hidden"></forex-selector>
69
+ </div>
70
  <div>
71
  <label class="block text-sm font-medium mb-1">Timeframe</label>
72
  <select class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 focus:ring-indigo-500 focus:border-indigo-500">
 
117
  <span class="text-gray-400">Take Profit 2</span>
118
  <span id="tp2{"ok":false,"message":"terminated"}
119
  <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
120
+ <script src="components/forex-selector.js"></script>
121
+ <script>
122
+ document.addEventListener('DOMContentLoaded', () => {
123
+ const assetTypeSelect = document.querySelector('select');
124
+ const forexSelector = document.querySelector('forex-selector');
125
+
126
+ assetTypeSelect.addEventListener('change', (e) => {
127
+ if (e.target.value === 'forex') {
128
+ forexSelector.classList.remove('hidden');
129
+ document.getElementById('pair-input').placeholder = 'EURUSD';
130
+ } else {
131
+ forexSelector.classList.add('hidden');
132
+ document.getElementById('pair-input').placeholder = 'BTCUSDT';
133
+ }
134
+ });
135
+ });
136
+ </script>
137
+ </body>
138
  </html>
style.css CHANGED
@@ -1,8 +1,9 @@
 
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
4
  }
5
-
6
  h1 {
7
  font-size: 16px;
8
  margin-top: 0;
@@ -14,15 +15,20 @@ p {
14
  margin-bottom: 10px;
15
  margin-top: 5px;
16
  }
17
-
18
  .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
 
 
24
  }
25
 
 
 
 
 
26
  .card p:last-child {
27
  margin-bottom: 0;
28
  }
 
1
+
2
  body {
3
+ font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
+ background: linear-gradient(to bottom right, #1a1a2e, #16213e);
5
+ color: #e2e8f0;
6
  }
 
7
  h1 {
8
  font-size: 16px;
9
  margin-top: 0;
 
15
  margin-bottom: 10px;
16
  margin-top: 5px;
17
  }
 
18
  .card {
19
+ background: rgba(30, 41, 59, 0.8);
20
+ border: 1px solid rgba(255, 255, 255, 0.1);
21
+ border-radius: 12px;
22
+ padding: 1.5rem;
23
+ backdrop-filter: blur(10px);
24
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
25
+ transition: all 0.3s ease;
26
  }
27
 
28
+ .card:hover {
29
+ box-shadow: 0 10px 15px rgba(0, 0, 0, 0.2);
30
+ transform: translateY(-2px);
31
+ }
32
  .card p:last-child {
33
  margin-bottom: 0;
34
  }