LittleMonkeyLab commited on
Commit
e44e7cc
·
verified ·
1 Parent(s): d650e50

Upload 19 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile for HuggingFace Spaces deployment
2
+ FROM python:3.11-slim
3
+
4
+ WORKDIR /app
5
+
6
+ # Install system dependencies for sqlite
7
+ RUN apt-get update && apt-get install -y \
8
+ build-essential \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Install pysqlite3 for HuggingFace Spaces
12
+ RUN pip install pysqlite3-binary
13
+
14
+ # Copy dependency files
15
+ COPY pyproject.toml uv.lock* ./
16
+
17
+ # Install uv (Python package manager)
18
+ RUN pip install uv
19
+
20
+ # Install dependencies
21
+ RUN uv pip install --system -r pyproject.toml || \
22
+ pip install -r requirements.txt || \
23
+ uv pip install --system gradio langchain langchain-community langchain-core chromadb sentence-transformers requests python-dotenv langchain-huggingface langchain-openai openai tiktoken fastapi uvicorn python-multipart pysqlite3-binary
24
+
25
+ # Copy application files
26
+ COPY . .
27
+
28
+ # Create db directory if it doesn't exist
29
+ RUN mkdir -p db multiple_docs game
30
+
31
+ # Set environment variables (can be overridden in HF Spaces)
32
+ ENV PORT=7860
33
+ ENV HF_TOKEN=${HF_TOKEN}
34
+ ENV HF_MODEL_NAME=${HF_MODEL_NAME:-meta-llama/Llama-3.1-8B-Instruct:novita}
35
+
36
+ # Expose port
37
+ EXPOSE 7860
38
+
39
+ # Run FastAPI with uvicorn (HuggingFace Spaces uses port 7860)
40
+ CMD python -c "import sys, os; sys.path.insert(0, '.'); from game_api import app; import uvicorn; port = int(os.getenv('PORT', 7860)); uvicorn.run(app, host='0.0.0.0', port=port)"
README.md CHANGED
@@ -1,10 +1,26 @@
1
  ---
2
- title: Trading Game Ai
3
- emoji: 👁
4
- colorFrom: yellow
5
- colorTo: red
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Trading Game AI Assistant
3
+ emoji: 📈
4
+ colorFrom: blue
5
+ colorTo: green
6
  sdk: docker
7
  pinned: false
8
+ license: cc
9
  ---
10
 
11
+ # Trading Game AI Assistant
12
+
13
+ A psychological experiment platform combining a trading game with tunable AI advice. Players can adjust AI risk, temperature, and confidence levels while making trading decisions.
14
+
15
+ ## Features
16
+
17
+ - **Trading Interface**: Buy/sell stocks in a fantasy financial universe
18
+ - **AI Advisor**: Get AI-powered trading advice based on market scenarios
19
+ - **Tunable Parameters**: Adjust AI risk tolerance, creativity (temperature), and confidence
20
+ - **Experiment Tracking**: Log decisions and trust scores for research
21
+
22
+ ## Environment Variables
23
+
24
+ Set these in HuggingFace Spaces:
25
+ - `HF_TOKEN`: Your HuggingFace API token
26
+ - `HF_MODEL_NAME`: Model to use (default: `meta-llama/Llama-3.1-8B-Instruct:novita`)
app.py ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # import os
2
+ # import sys
3
+ # import requests
4
+ # from langchain.chains import ConversationalRetrievalChain
5
+ # from langchain.document_loaders import PyPDFLoader, Docx2txtLoader, TextLoader
6
+ # from langchain_text_splitters import CharacterTextSplitter
7
+ # from langchain.vectorstores import Chroma
8
+ # from langchain.embeddings import HuggingFaceEmbeddings
9
+ # from langchain.llms.base import LLM
10
+ # import gradio as gr
11
+
12
+ # # workaround for sqlite in HF spaces
13
+ # __import__('pysqlite3')
14
+ # sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')
15
+
16
+ # # 📄 Load documents
17
+ # docs = []
18
+ # for f in os.listdir("multiple_docs"):
19
+ # if f.endswith(".pdf"):
20
+ # loader = PyPDFLoader(os.path.join("multiple_docs", f))
21
+ # docs.extend(loader.load())
22
+ # elif f.endswith(".docx") or f.endswith(".doc"):
23
+ # loader = Docx2txtLoader(os.path.join("multiple_docs", f))
24
+ # docs.extend(loader.load())
25
+ # elif f.endswith(".txt"):
26
+ # loader = TextLoader(os.path.join("multiple_docs", f))
27
+ # docs.extend(loader.load())
28
+
29
+ # # 🔗 Split into chunks
30
+ # splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=10)
31
+ # docs = splitter.split_documents(docs)
32
+
33
+ # texts = [doc.page_content for doc in docs]
34
+ # metadatas = [{"id": i} for i in range(len(texts))]
35
+
36
+ # # 🧠 Embeddings
37
+ # embedding_function = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
38
+
39
+ # # 🗃️ Vectorstore
40
+ # vectorstore = Chroma(
41
+ # persist_directory="./db",
42
+ # embedding_function=embedding_function
43
+ # )
44
+ # vectorstore.add_texts(texts=texts, metadatas=metadatas)
45
+ # vectorstore.persist()
46
+
47
+ # # 🔐 Get DeepSeek API key from env
48
+ # DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
49
+ # if DEEPSEEK_API_KEY is None:
50
+ # raise ValueError("DEEPSEEK_API_KEY environment variable is not set.")
51
+
52
+ # # 🌟 DeepSeek API endpoint
53
+ # DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions"
54
+
55
+ # # 🔷 Wrap DeepSeek API into LangChain LLM
56
+ # class DeepSeekLLM(LLM):
57
+ # """LLM that queries DeepSeek's API."""
58
+ # api_key: str = DEEPSEEK_API_KEY
59
+
60
+ # def _call(self, prompt, stop=None, run_manager=None, **kwargs):
61
+ # headers = {
62
+ # "Authorization": f"Bearer {self.api_key}",
63
+ # "Content-Type": "application/json"
64
+ # }
65
+ # payload = {
66
+ # "model": "deepseek-chat", # adjust if you have a specific model name
67
+ # "messages": [
68
+ # {"role": "system", "content": "You are a helpful assistant."},
69
+ # {"role": "user", "content": prompt}
70
+ # ],
71
+ # "temperature": 0.7,
72
+ # "max_tokens": 512
73
+ # }
74
+ # response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload)
75
+ # response.raise_for_status()
76
+ # data = response.json()
77
+ # return data["choices"][0]["message"]["content"].strip()
78
+
79
+ # @property
80
+ # def _llm_type(self) -> str:
81
+ # return "deepseek_api"
82
+
83
+ # llm = DeepSeekLLM()
84
+
85
+ # # 🔗 Conversational chain
86
+ # chain = ConversationalRetrievalChain.from_llm(
87
+ # llm,
88
+ # retriever=vectorstore.as_retriever(search_kwargs={'k': 6}),
89
+ # return_source_documents=True,
90
+ # verbose=False
91
+ # )
92
+
93
+ # # 💬 Gradio UI
94
+ # chat_history = []
95
+
96
+ # with gr.Blocks() as demo:
97
+ # chatbot = gr.Chatbot(
98
+ # [("", "Hello, I'm Thierry Decae's chatbot, you can ask me any recruitment related questions such as my experience, where I'm eligible to work, skills etc you can chat with me directly in multiple languages")],
99
+ # avatar_images=["./multiple_docs/Guest.jpg", "./multiple_docs/Thierry Picture.jpg"]
100
+ # )
101
+ # msg = gr.Textbox(placeholder="Type your question here...")
102
+ # clear = gr.Button("Clear")
103
+
104
+ # def user(query, chat_history):
105
+ # chat_history_tuples = [(m[0], m[1]) for m in chat_history]
106
+ # result = chain({"question": query, "chat_history": chat_history_tuples})
107
+ # chat_history.append((query, result["answer"]))
108
+ # return gr.update(value=""), chat_history
109
+
110
+ # msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False)
111
+ # clear.click(lambda: None, None, chatbot, queue=False)
112
+
113
+ # demo.launch(debug=True) # remove share=True if running in HF Spaces
114
+
115
+
116
+ import os
117
+ import sys
118
+ from langchain_classic.chains import ConversationalRetrievalChain, LLMChain
119
+ from langchain_community.document_loaders import PyPDFLoader, Docx2txtLoader, TextLoader
120
+ from langchain_text_splitters import CharacterTextSplitter
121
+ from langchain_community.vectorstores import Chroma
122
+ from langchain_huggingface import HuggingFaceEmbeddings
123
+ from langchain_openai import ChatOpenAI
124
+ from langchain_core.prompts import PromptTemplate
125
+ from langchain_classic.chains.question_answering import load_qa_chain
126
+ import gradio as gr
127
+
128
+ # workaround for sqlite in HF spaces (only needed on HuggingFace Spaces)
129
+ try:
130
+ __import__('pysqlite3')
131
+ sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')
132
+ except ImportError:
133
+ # pysqlite3 not available, use system sqlite3 (fine for local macOS/Linux)
134
+ pass
135
+
136
+ # 📄 Load documents
137
+ docs = []
138
+ for f in os.listdir("multiple_docs"):
139
+ if f.endswith(".pdf"):
140
+ loader = PyPDFLoader(os.path.join("multiple_docs", f))
141
+ docs.extend(loader.load())
142
+ elif f.endswith(".docx") or f.endswith(".doc"):
143
+ loader = Docx2txtLoader(os.path.join("multiple_docs", f))
144
+ docs.extend(loader.load())
145
+ elif f.endswith(".txt"):
146
+ loader = TextLoader(os.path.join("multiple_docs", f))
147
+ docs.extend(loader.load())
148
+
149
+ # 🔗 Split into chunks
150
+ splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=10)
151
+ docs = splitter.split_documents(docs)
152
+
153
+ # 🧠 Embeddings
154
+ embedding_function = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
155
+
156
+ # 🗃️ Vectorstore - use from_documents which is more modern
157
+ vectorstore = Chroma.from_documents(
158
+ documents=docs,
159
+ embedding=embedding_function,
160
+ persist_directory="./db"
161
+ )
162
+
163
+ # 🤖 Use HuggingFace Inference API (hosted in Spaces)
164
+ # HF token (must be set via HF_TOKEN environment variable)
165
+ HF_TOKEN = os.getenv("HF_TOKEN")
166
+ if not HF_TOKEN:
167
+ raise ValueError("HF_TOKEN environment variable is not set. Please set it before running the application.")
168
+
169
+ # You can change MODEL_NAME to use different models from HuggingFace:
170
+ # Popular options:
171
+ # - "microsoft/DialoGPT-large" (conversational model)
172
+ # - "HuggingFaceH4/zephyr-7b-beta" (high quality chat model)
173
+ # - "mistralai/Mistral-7B-Instruct-v0.2" (excellent quality)
174
+ # - "meta-llama/Llama-2-7b-chat-hf" (if you have access)
175
+ # - "google/flan-t5-large" (good for Q&A)
176
+ MODEL_NAME = os.getenv("HF_MODEL_NAME", "meta-llama/Llama-3.1-8B-Instruct:novita")
177
+
178
+ print(f"Using HuggingFace Router API with model: {MODEL_NAME}")
179
+
180
+ # Initialize ChatOpenAI with HuggingFace Router (OpenAI-compatible API)
181
+ # This allows using provider suffixes like :novita
182
+ # Uses OpenAI-compatible interface via HF router
183
+ llm = ChatOpenAI(
184
+ model=MODEL_NAME,
185
+ base_url="https://router.huggingface.co/v1",
186
+ api_key=HF_TOKEN,
187
+ temperature=0.7,
188
+ max_tokens=512,
189
+ )
190
+
191
+ # ✨ Custom prompt template
192
+ template = """
193
+ You are an AI trading advisor for the Quantum Financial Network trading universe.
194
+
195
+ IMPORTANT: You are providing DIRECT TRADING RECOMMENDATIONS. Give clear, actionable advice based on:
196
+ - Current market scenarios described in the question
197
+ - Risk tolerance level specified (0=conservative, 10=aggressive)
198
+ - Company information and market context provided
199
+ - Specific stock symbols and prices mentioned
200
+
201
+ When asked about a specific trade (e.g., "Should I buy X shares of Y?"), you MUST:
202
+ 1. Give a CLEAR RECOMMENDATION: "Yes, buy..." or "No, don't buy..." or "Consider buying/selling..."
203
+ 2. Explain WHY based on the current scenario and company information
204
+ 3. Reference specific companies, market events, or data from the context
205
+ 4. Adjust your certainty based on the risk tolerance level mentioned
206
+ 5. Be DIRECT and ACTIONABLE - no vague "I'd need more information" responses
207
+
208
+ Use the following context to answer the user's question. Always give a direct recommendation.
209
+
210
+ Context:
211
+ {context}
212
+
213
+ Question: {question}
214
+
215
+ Answer:
216
+ """
217
+
218
+ prompt = PromptTemplate(
219
+ input_variables=["context", "question"],
220
+ template=template,
221
+ )
222
+
223
+ # 🔗 QA chain with custom prompt
224
+ qa_chain = load_qa_chain(llm, chain_type="stuff", prompt=prompt)
225
+
226
+ # 🔷 Question rephraser chain for follow-up questions → standalone
227
+ CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(
228
+ """
229
+ Given the following conversation and a follow-up question, rephrase the follow-up question to be a standalone question.
230
+
231
+ Chat History:
232
+ {chat_history}
233
+ Follow Up Input: {question}
234
+ Standalone question:
235
+ """
236
+ )
237
+
238
+ question_generator = LLMChain(
239
+ llm=llm,
240
+ prompt=CONDENSE_QUESTION_PROMPT
241
+ )
242
+
243
+ # 🔷 Finally: build the ConversationalRetrievalChain manually
244
+ chain = ConversationalRetrievalChain(
245
+ retriever=vectorstore.as_retriever(search_kwargs={'k': 6}),
246
+ question_generator=question_generator,
247
+ combine_docs_chain=qa_chain,
248
+ return_source_documents=True,
249
+ verbose=False
250
+ )
251
+
252
+ # 💬 Gradio UI
253
+ chat_history = []
254
+
255
+ with gr.Blocks() as demo:
256
+ chatbot = gr.Chatbot(
257
+ value=[{"role": "assistant", "content": "Welcome to the Quantum Financial Network! I'm your trading universe assistant. You can ask me about companies (VCG, CSI, STDY, AUBIO, NLN), market events, trading strategies, currency systems, trading hours, market history, and anything about our financial markets. What would you like to know?"}]
258
+ )
259
+ msg = gr.Textbox(placeholder="Type your question here...")
260
+ clear = gr.Button("Clear")
261
+
262
+ def user(query, chat_history):
263
+ # Convert Gradio 4.x format (dicts) to tuple format for LangChain chain
264
+ # LangChain expects list of tuples: [(human_message, ai_message), ...]
265
+ chat_history_tuples = []
266
+ current_human = None
267
+ current_ai = None
268
+
269
+ for msg in chat_history:
270
+ if isinstance(msg, dict):
271
+ role = msg.get("role", "")
272
+ content = msg.get("content", "")
273
+
274
+ if role == "user":
275
+ # If we have a previous human message without AI response, add it with empty AI
276
+ if current_human is not None:
277
+ human_str = str(current_human) if current_human else ""
278
+ ai_str = str(current_ai) if current_ai else ""
279
+ chat_history_tuples.append((human_str, ai_str))
280
+ current_human = str(content) if content else ""
281
+ current_ai = None
282
+ elif role == "assistant":
283
+ current_ai = str(content) if content else ""
284
+ # Pair the human and AI messages
285
+ if current_human is not None:
286
+ human_str = str(current_human) if current_human else ""
287
+ ai_str = str(current_ai) if current_ai else ""
288
+ chat_history_tuples.append((human_str, ai_str))
289
+ current_human = None
290
+ current_ai = None
291
+ else:
292
+ # Fallback for old tuple format
293
+ if isinstance(msg, (list, tuple)) and len(msg) >= 2:
294
+ chat_history_tuples.append((str(msg[0]), str(msg[1])))
295
+
296
+ # Handle case where last message was human without AI response
297
+ if current_human is not None:
298
+ human_str = str(current_human) if current_human else ""
299
+ ai_str = str(current_ai) if current_ai else ""
300
+ chat_history_tuples.append((human_str, ai_str))
301
+
302
+ # Get response from chain
303
+ result = chain({"question": query, "chat_history": chat_history_tuples})
304
+
305
+ # Append both user query and assistant response in Gradio 4.x format
306
+ chat_history.append({"role": "user", "content": query})
307
+ chat_history.append({"role": "assistant", "content": result["answer"]})
308
+
309
+ return gr.update(value=""), chat_history
310
+
311
+ msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False)
312
+ clear.click(lambda: None, None, chatbot, queue=False)
313
+
314
+ # Only launch Gradio demo if running this file directly (not when imported)
315
+ if __name__ == "__main__":
316
+ demo.launch(debug=True) # remove share=True if running in HF Spaces
317
+
318
+
319
+
game/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
game/README.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Trading Game Frontend
2
+
3
+ Frontend files for the Trading Game AI Assistant experiment platform.
4
+
5
+ ## Files
6
+
7
+ - `trade.html` - Main trading game interface
8
+ - `game-api-integration.js` - API integration layer for AI chat
game/components/footer.js ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomFooter extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ footer {
7
+ background: rgba(17, 24, 39, 0.8);
8
+ color: white;
9
+ padding: 2rem;
10
+ text-align: center;
11
+ margin-top: auto;
12
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
13
+ }
14
+ .footer-content {
15
+ max-width: 1200px;
16
+ margin: 0 auto;
17
+ display: grid;
18
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
19
+ gap: 2rem;
20
+ text-align: left;
21
+ }
22
+ .footer-links h3 {
23
+ font-weight: 600;
24
+ margin-bottom: 1rem;
25
+ color: #10B981;
26
+ }
27
+ .footer-links ul {
28
+ list-style: none;
29
+ padding: 0;
30
+ margin: 0;
31
+ }
32
+ .footer-links li {
33
+ margin-bottom: 0.5rem;
34
+ }
35
+ .footer-links a {
36
+ color: rgba(255, 255, 255, 0.7);
37
+ text-decoration: none;
38
+ transition: color 0.2s;
39
+ }
40
+ .footer-links a:hover {
41
+ color: white;
42
+ }
43
+ .social-links {
44
+ display: flex;
45
+ gap: 1rem;
46
+ justify-content: center;
47
+ margin-top: 2rem;
48
+ }
49
+ .social-links a {
50
+ color: white;
51
+ background: rgba(255, 255, 255, 0.1);
52
+ width: 40px;
53
+ height: 40px;
54
+ border-radius: 50%;
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ transition: all 0.2s;
59
+ }
60
+ .social-links a:hover {
61
+ background: rgba(255, 255, 255, 0.2);
62
+ transform: translateY(-2px);
63
+ }
64
+ .copyright {
65
+ margin-top: 2rem;
66
+ padding-top: 2rem;
67
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
68
+ color: rgba(255, 255, 255, 0.6);
69
+ font-size: 0.875rem;
70
+ }
71
+ </style>
72
+ <footer>
73
+ <div class="footer-content">
74
+ <div class="footer-links">
75
+ <h3>Game</h3>
76
+ <ul>
77
+ <li><a href="/play.html">Play Now</a></li>
78
+ <li><a href="/leaderboard.html">Leaderboard</a></li>
79
+ <li><a href="/tutorials.html">Tutorials</a></li>
80
+ </ul>
81
+ </div>
82
+ <div class="footer-links">
83
+ <h3>Resources</h3>
84
+ <ul>
85
+ <li><a href="/learn.html">Trading Education</a></li>
86
+ <li><a href="/blog.html">Blog</a></li>
87
+ <li><a href="/glossary.html">Trading Glossary</a></li>
88
+ </ul>
89
+ </div>
90
+ <div class="footer-links">
91
+ <h3>Company</h3>
92
+ <ul>
93
+ <li><a href="/about.html">About Us</a></li>
94
+ <li><a href="/careers.html">Careers</a></li>
95
+ <li><a href="/contact.html">Contact</a></li>
96
+ </ul>
97
+ </div>
98
+ </div>
99
+ <div class="social-links">
100
+ <a href="#
game/components/navbar.js ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ nav {
7
+ background: rgba(17, 24, 39, 0.8);
8
+ backdrop-filter: blur(10px);
9
+ padding: 1rem 2rem;
10
+ display: flex;
11
+ justify-content: space-between;
12
+ align-items: center;
13
+ position: sticky;
14
+ top: 0;
15
+ z-index: 50;
16
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
17
+ }
18
+ .logo {
19
+ color: white;
20
+ font-weight: bold;
21
+ font-size: 1.5rem;
22
+ background: linear-gradient(90deg, #10B981 0%, #3B82F6 100%);
23
+ -webkit-background-clip: text;
24
+ background-clip: text;
25
+ -webkit-text-fill-color: transparent;
26
+ }
27
+ ul {
28
+ display: flex;
29
+ gap: 1.5rem;
30
+ list-style: none;
31
+ margin: 0;
32
+ padding: 0;
33
+ align-items: center;
34
+ }
35
+ a {
36
+ color: rgba(255, 255, 255, 0.8);
37
+ text-decoration: none;
38
+ transition: all 0.2s;
39
+ font-weight: 500;
40
+ display: flex;
41
+ align-items: center;
42
+ gap: 0.5rem;
43
+ }
44
+ a:hover {
45
+ color: white;
46
+ }
47
+ .active {
48
+ color: white;
49
+ font-weight: 600;
50
+ }
51
+ .play-btn {
52
+ background: linear-gradient(90deg, #10B981 0%, #3B82F6 100%);
53
+ padding: 0.5rem 1rem;
54
+ border-radius: 0.375rem;
55
+ color: white !important;
56
+ }
57
+ .play-btn:hover {
58
+ transform: translateY(-2px) scale(1.05);
59
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
60
+ }
61
+ @media (max-width: 768px) {
62
+ nav {
63
+ flex-direction: column;
64
+ gap: 1rem;
65
+ padding: 1rem;
66
+ }
67
+ }
68
+ </style>
69
+ <nav>
70
+ <div class="logo">Trading Game</div>
71
+ <ul>
72
+ <li><a href="/" class="active"><i data-feather="home"></i> Home</a></li>
73
+ <li><a href="/play.html"><i data-feather="activity"></i> Play</a></li>
74
+ <li><a href="/learn.html"><i data-feather="book"></i> Learn</a></li>
75
+ <li><a href="/leaderboard.html"><i data-feather="award"></i> Leaderboard</a></li>
76
+ <li><a href="/play.html" class="play-btn"><i data-feather="play"></i> Play Now</a></li>
77
+ </ul>
78
+ </nav>
79
+ `;
80
+ }
81
+ }
82
+ customElements.define('custom-navbar', CustomNavbar);
game/game-api-integration.js ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Game API Integration for AI Chatbot
3
+ * Handles communication with FastAPI backend and experiment tracking
4
+ */
5
+
6
+ // Auto-detect API base URL for both local and HuggingFace Spaces
7
+ const API_BASE_URL = (typeof window !== 'undefined' && window.location)
8
+ ? `${window.location.origin}/api`
9
+ : 'http://localhost:8000/api';
10
+ let sessionId = generateSessionId();
11
+ let currentAIParams = {
12
+ risk_level: 5.0,
13
+ temperature: 0.7,
14
+ confidence_boost: 0.0
15
+ };
16
+ let chatHistory = [];
17
+
18
+ // Generate unique session ID
19
+ function generateSessionId() {
20
+ return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
21
+ }
22
+
23
+ /**
24
+ * Call AI chatbot with current game context
25
+ */
26
+ async function askAI(question, context = {}) {
27
+ try {
28
+ // Use context parameters if provided, otherwise use current AI params
29
+ const riskLevel = context.risk_level !== undefined ? context.risk_level : currentAIParams.risk_level;
30
+ const temperature = context.temperature !== undefined ? context.temperature : currentAIParams.temperature;
31
+ const confidenceBoost = context.confidence_boost !== undefined ? context.confidence_boost : currentAIParams.confidence_boost;
32
+
33
+ const response = await fetch(`${API_BASE_URL}/ai/chat`, {
34
+ method: 'POST',
35
+ headers: {
36
+ 'Content-Type': 'application/json',
37
+ },
38
+ body: JSON.stringify({
39
+ question: question,
40
+ chat_history: chatHistory,
41
+ risk_level: riskLevel,
42
+ temperature: temperature,
43
+ confidence_boost: confidenceBoost,
44
+ session_id: sessionId
45
+ })
46
+ });
47
+
48
+ if (!response.ok) {
49
+ const errorData = await response.json().catch(() => ({ detail: response.statusText }));
50
+ console.error('AI API Error:', errorData);
51
+ return { answer: `Error: ${errorData.detail || 'Failed to get AI advice'}` };
52
+ }
53
+
54
+ const data = await response.json();
55
+
56
+ // Update chat history
57
+ chatHistory.push([question, data.answer]);
58
+
59
+ return data;
60
+ } catch (error) {
61
+ console.error('AI API Error:', error);
62
+ return { answer: "I'm having trouble connecting. Please try again." };
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Log trading decision for trust analysis
68
+ */
69
+ async function logDecision(symbol, action, quantity, price, aiAdviceFollowed, trustScore = null) {
70
+ try {
71
+ await fetch(`${API_BASE_URL}/experiment/decision`, {
72
+ method: 'POST',
73
+ headers: {
74
+ 'Content-Type': 'application/json',
75
+ },
76
+ body: JSON.stringify({
77
+ session_id: sessionId,
78
+ symbol: symbol,
79
+ action: action,
80
+ quantity: quantity,
81
+ price: price,
82
+ ai_advice_followed: aiAdviceFollowed,
83
+ trust_score: trustScore
84
+ })
85
+ });
86
+ } catch (error) {
87
+ console.error('Decision logging error:', error);
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Trigger situational scenario
93
+ */
94
+ async function triggerScenario(scenarioType, context = {}) {
95
+ try {
96
+ const response = await fetch(`${API_BASE_URL}/experiment/scenario`, {
97
+ method: 'POST',
98
+ headers: {
99
+ 'Content-Type': 'application/json',
100
+ },
101
+ body: JSON.stringify({
102
+ session_id: sessionId,
103
+ scenario_type: scenarioType,
104
+ context: context,
105
+ ai_required: true
106
+ })
107
+ });
108
+
109
+ const data = await response.json();
110
+
111
+ // Show scenario prompt to player and trigger AI assistance
112
+ if (data.requires_ai) {
113
+ showScenarioPrompt(data);
114
+ }
115
+
116
+ return data;
117
+ } catch (error) {
118
+ console.error('Scenario trigger error:', error);
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Update AI parameters (for experiment control)
124
+ */
125
+ function updateAIParams(riskLevel, temperature, confidenceBoost) {
126
+ currentAIParams.risk_level = riskLevel;
127
+ currentAIParams.temperature = temperature;
128
+ currentAIParams.confidence_boost = confidenceBoost;
129
+
130
+ // Update UI if controls exist
131
+ updateAIParamsUI();
132
+ }
133
+
134
+ /**
135
+ * Check for scenario triggers based on game state
136
+ */
137
+ function checkScenarioTriggers(gameState) {
138
+ // Volatility check
139
+ if (gameState.volatility > 0.15) {
140
+ triggerScenario('volatility', {
141
+ volatility: gameState.volatility,
142
+ affected_stocks: gameState.positions
143
+ });
144
+ }
145
+
146
+ // Large position check
147
+ const totalValue = gameState.positions.reduce((sum, pos) => sum + (pos.price * pos.quantity), 0);
148
+ if (totalValue > 10000) {
149
+ triggerScenario('large_position', {
150
+ total_value: totalValue,
151
+ portfolio_size: gameState.balance + totalValue
152
+ });
153
+ }
154
+
155
+ // Loss recovery check
156
+ const dailyPnL = gameState.pnl;
157
+ const pnlPercent = (dailyPnL / gameState.balance) * 100;
158
+ if (pnlPercent < -5) {
159
+ triggerScenario('loss_recovery', {
160
+ current_loss: dailyPnL,
161
+ loss_percent: pnlPercent
162
+ });
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Show scenario prompt and AI assistance UI
168
+ */
169
+ function showScenarioPrompt(scenarioData) {
170
+ // Create modal or inline prompt
171
+ const scenarioModal = document.createElement('div');
172
+ scenarioModal.className = 'scenario-modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
173
+ scenarioModal.innerHTML = `
174
+ <div class="bg-gray-800 p-6 rounded-xl max-w-2xl">
175
+ <h3 class="text-2xl font-bold mb-4">Trading Scenario</h3>
176
+ <p class="text-gray-300 mb-4">${scenarioData.prompt}</p>
177
+ <div id="ai-advice-container" class="mb-4 p-4 bg-gray-700 rounded-lg">
178
+ <p class="text-green-400">🤖 AI Assistant:</p>
179
+ <p id="ai-advice-text" class="mt-2">Analyzing situation...</p>
180
+ </div>
181
+ <div class="flex gap-4">
182
+ <button onclick="getAIScenarioAdvice('${scenarioData.scenario_type}')"
183
+ class="px-4 py-2 bg-blue-600 rounded hover:bg-blue-700">
184
+ Get AI Advice
185
+ </button>
186
+ <button onclick="closeScenarioModal()"
187
+ class="px-4 py-2 bg-gray-600 rounded hover:bg-gray-700">
188
+ Skip
189
+ </button>
190
+ </div>
191
+ </div>
192
+ `;
193
+
194
+ document.body.appendChild(scenarioModal);
195
+
196
+ // Auto-request AI advice
197
+ getAIScenarioAdvice(scenarioData.scenario_type);
198
+ }
199
+
200
+ /**
201
+ * Get AI advice for scenario
202
+ */
203
+ async function getAIScenarioAdvice(scenarioType) {
204
+ const question = `I'm facing a ${scenarioType} scenario. What should I do?`;
205
+ const advice = await askAI(question);
206
+
207
+ const adviceText = document.getElementById('ai-advice-text');
208
+ if (adviceText) {
209
+ adviceText.textContent = advice.answer;
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Close scenario modal
215
+ */
216
+ function closeScenarioModal() {
217
+ const modal = document.querySelector('.scenario-modal');
218
+ if (modal) {
219
+ modal.remove();
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Enhanced trading function with AI integration
225
+ */
226
+ async function executeTradeWithAI(symbol, action, quantity, price) {
227
+ // Ask AI for advice before executing
228
+ const question = `Should I ${action} ${quantity} shares of ${symbol} at $${price.toFixed(2)}?`;
229
+ const aiAdvice = await askAI(question);
230
+
231
+ // Show AI advice to player
232
+ const confirmTrade = confirm(
233
+ `AI Advice: ${aiAdvice.answer}\n\nProceed with ${action.toUpperCase()} ${quantity} ${symbol}?`
234
+ );
235
+
236
+ if (confirmTrade) {
237
+ // Execute trade - update game state (placeholder for now)
238
+ // TODO: Implement actual trade execution with game state update
239
+ console.log(`Executing ${action} ${quantity} ${symbol} at $${price.toFixed(2)}`);
240
+
241
+ // Update UI to show trade was executed
242
+ alert(`Trade executed: ${action.toUpperCase()} ${quantity} ${symbol}`);
243
+
244
+ // Log decision
245
+ await logDecision(symbol, action, quantity, price, true);
246
+
247
+ // Ask for trust score
248
+ const trustScore = prompt('How much did you trust the AI advice? (1-10):');
249
+ if (trustScore) {
250
+ await logDecision(symbol, action, quantity, price, true, parseFloat(trustScore));
251
+ }
252
+ } else {
253
+ // Player ignored AI advice
254
+ await logDecision(symbol, action, quantity, price, false);
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Update AI parameters UI (if you add controls)
260
+ */
261
+ function updateAIParamsUI() {
262
+ const paramsDisplay = document.getElementById('ai-params-display');
263
+ if (paramsDisplay) {
264
+ paramsDisplay.innerHTML = `
265
+ Risk: ${currentAIParams.risk_level.toFixed(1)} |
266
+ Temp: ${currentAIParams.temperature.toFixed(2)} |
267
+ Confidence: ${currentAIParams.confidence_boost.toFixed(0)}
268
+ `;
269
+ }
270
+ }
271
+
272
+ // Export for use in game
273
+ window.gameAI = {
274
+ askAI,
275
+ logDecision,
276
+ triggerScenario,
277
+ updateAIParams,
278
+ checkScenarioTriggers,
279
+ executeTradeWithAI
280
+ };
game/trade.html ADDED
@@ -0,0 +1,418 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Trading Game - Proof of Concept</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ body { font-family: 'Inter', sans-serif; }
10
+ </style>
11
+ </head>
12
+ <body class="bg-gray-900 text-white min-h-screen">
13
+ <main class="container mx-auto px-4 py-8 max-w-7xl">
14
+ <h1 class="text-4xl font-bold mb-8 text-center bg-gradient-to-r from-green-400 to-blue-500 bg-clip-text text-transparent">
15
+ Trading Game - Proof of Concept
16
+ </h1>
17
+
18
+ <!-- Current Scenario (Full Width) -->
19
+ <div id="scenario-section" class="bg-gradient-to-r from-red-900 to-orange-900 p-6 rounded-xl mb-6 border-2 border-orange-500">
20
+ <h2 class="text-2xl font-bold mb-3 text-yellow-300">⚠️ Current Market Scenario</h2>
21
+ <div id="scenario-text" class="text-lg mb-4">
22
+ A typhoon is seen off the coast of New Gregoria, likely impacting the Galvanium Supply Chain.
23
+ This may affect logistics companies (NLN) and energy sectors (VCG).
24
+ </div>
25
+ <button id="next-scenario-button" class="px-4 py-2 bg-orange-600 rounded hover:bg-orange-700 text-sm">
26
+ Next Scenario
27
+ </button>
28
+ </div>
29
+
30
+ <!-- Two Column Layout -->
31
+ <div class="grid lg:grid-cols-2 gap-6">
32
+
33
+ <!-- LEFT SIDE: AI Advisor -->
34
+ <div class="space-y-6">
35
+ <!-- AI Parameter Sliders -->
36
+ <div class="bg-gray-800 p-6 rounded-xl">
37
+ <h2 class="text-2xl font-bold mb-4 text-blue-400">🤖 AI Advisor Settings</h2>
38
+ <div class="space-y-4">
39
+ <div>
40
+ <label class="block text-gray-400 mb-2">
41
+ Risk Tolerance: <span id="risk-value" class="text-white font-bold">5.0</span> / 10
42
+ </label>
43
+ <input type="range" id="risk-slider" min="0" max="10" step="0.5" value="5.0"
44
+ class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer">
45
+ <div class="flex justify-between text-xs text-gray-500 mt-1">
46
+ <span>Conservative</span>
47
+ <span>Moderate</span>
48
+ <span>Aggressive</span>
49
+ </div>
50
+ </div>
51
+ <div>
52
+ <label class="block text-gray-400 mb-2">
53
+ AI Creativity: <span id="temperature-value" class="text-white font-bold">0.7</span>
54
+ </label>
55
+ <input type="range" id="temperature-slider" min="0" max="2" step="0.1" value="0.7"
56
+ class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer">
57
+ <div class="flex justify-between text-xs text-gray-500 mt-1">
58
+ <span>Deterministic</span>
59
+ <span>Balanced</span>
60
+ <span>Creative</span>
61
+ </div>
62
+ </div>
63
+ <div>
64
+ <label class="block text-gray-400 mb-2">
65
+ Confidence Level: <span id="confidence-value" class="text-white font-bold">0</span>
66
+ </label>
67
+ <input type="range" id="confidence-slider" min="-100" max="100" step="10" value="0"
68
+ class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer">
69
+ <div class="flex justify-between text-xs text-gray-500 mt-1">
70
+ <span>Cautious (-100)</span>
71
+ <span>Neutral (0)</span>
72
+ <span>Very Confident (+100)</span>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </div>
77
+
78
+ <!-- AI Chat/Advice Section -->
79
+ <div id="ai-advice-section" class="bg-gray-800 p-6 rounded-xl">
80
+ <h2 class="text-2xl font-bold mb-4 text-green-400">🤖 AI Trading Advice</h2>
81
+ <div id="ai-message" class="bg-gray-700 p-4 rounded-lg mb-4 text-gray-300 min-h-[200px] whitespace-pre-wrap">
82
+ <p class="text-gray-500 italic">Adjust your settings above and click "Get AI Advice" below to receive trading recommendations based on the current scenario.</p>
83
+ </div>
84
+ <button id="get-ai-advice-button" class="w-full py-3 bg-blue-600 rounded-lg font-bold hover:bg-blue-700 mb-4">
85
+ 💡 Get AI Trading Advice
86
+ </button>
87
+ <div id="ai-actions" class="flex gap-2" style="display: none;">
88
+ <button id="follow-advice-button" class="flex-1 py-2 bg-blue-600 rounded hover:bg-blue-700 text-sm">
89
+ Follow
90
+ </button>
91
+ <button id="ignore-advice-button" class="flex-1 py-2 bg-gray-600 rounded hover:bg-gray-700 text-sm">
92
+ Ignore
93
+ </button>
94
+ <button id="clear-ai-button" class="flex-1 py-2 bg-red-600 rounded hover:bg-red-700 text-sm">
95
+ Clear
96
+ </button>
97
+ </div>
98
+ </div>
99
+ </div>
100
+
101
+ <!-- RIGHT SIDE: Trading Portfolio -->
102
+ <div class="space-y-6">
103
+ <!-- Portfolio Summary -->
104
+ <div class="bg-gray-800 p-6 rounded-xl">
105
+ <h2 class="text-2xl font-bold mb-4">Portfolio</h2>
106
+ <div class="grid grid-cols-2 gap-4">
107
+ <div>
108
+ <p class="text-gray-400">Balance</p>
109
+ <p class="text-3xl font-bold" id="balance">$50,000.00</p>
110
+ </div>
111
+ <div>
112
+ <p class="text-gray-400">Positions</p>
113
+ <p class="text-3xl font-bold" id="positions">0</p>
114
+ </div>
115
+ </div>
116
+ </div>
117
+
118
+ <!-- Trading Form -->
119
+ <div class="bg-gray-800 p-6 rounded-xl">
120
+ <h2 class="text-2xl font-bold mb-4">Make a Trade</h2>
121
+ <div class="space-y-4 mb-4">
122
+ <div>
123
+ <label class="block text-gray-400 mb-2">Symbol</label>
124
+ <select id="trade-symbol" class="w-full bg-gray-700 rounded p-3 text-white">
125
+ <option>VCG</option>
126
+ <option>CSI</option>
127
+ <option>STDY</option>
128
+ <option>AUBIO</option>
129
+ <option>NLN</option>
130
+ </select>
131
+ </div>
132
+ <div class="grid grid-cols-2 gap-4">
133
+ <div>
134
+ <label class="block text-gray-400 mb-2">Quantity</label>
135
+ <input id="trade-quantity" type="number" value="10" min="1"
136
+ class="w-full bg-gray-700 rounded p-3 text-white">
137
+ </div>
138
+ <div>
139
+ <label class="block text-gray-400 mb-2">Price</label>
140
+ <input id="trade-price" type="number" value="100" min="0" step="0.01"
141
+ class="w-full bg-gray-700 rounded p-3 text-white" readonly>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ <div class="flex gap-4">
146
+ <button id="buy-button" class="flex-1 py-3 bg-green-600 rounded-lg font-bold hover:bg-green-700">
147
+ Buy
148
+ </button>
149
+ <button id="sell-button" class="flex-1 py-3 bg-red-600 rounded-lg font-bold hover:bg-red-700">
150
+ Sell
151
+ </button>
152
+ </div>
153
+ </div>
154
+
155
+ <!-- Recent Trades -->
156
+ <div class="bg-gray-800 p-6 rounded-xl">
157
+ <h2 class="text-2xl font-bold mb-4">Recent Trades</h2>
158
+ <div id="trade-history" class="space-y-2 max-h-[400px] overflow-y-auto">
159
+ <p class="text-gray-400 text-center">No trades yet</p>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </main>
165
+
166
+ <script src="game-api-integration.js"></script>
167
+ <script>
168
+ // Simple game state
169
+ let gameState = {
170
+ balance: 50000,
171
+ positions: [],
172
+ trades: [],
173
+ currentScenario: {
174
+ title: "Typhoon near New Gregoria",
175
+ description: "A typhoon is seen off the coast of New Gregoria, likely impacting the Galvanium Supply Chain. This may affect logistics companies (NLN) and energy sectors (VCG).",
176
+ affectedSymbols: ["NLN", "VCG"]
177
+ }
178
+ };
179
+
180
+ // Scenario templates
181
+ const scenarios = [
182
+ {
183
+ title: "Typhoon near New Gregoria",
184
+ description: "A typhoon is seen off the coast of New Gregoria, likely impacting the Galvanium Supply Chain. This may affect logistics companies (NLN) and energy sectors (VCG).",
185
+ affectedSymbols: ["NLN", "VCG"]
186
+ },
187
+ {
188
+ title: "Quantum Processor Breakthrough",
189
+ description: "Veridian Capital Group (VCG) announces a major quantum computing breakthrough. This could significantly impact energy and tech sectors.",
190
+ affectedSymbols: ["VCG", "CSI"]
191
+ },
192
+ {
193
+ title: "Asteroid Mining Success",
194
+ description: "Stellar Dynamics Corp (STDY) successfully completes asteroid mining operations, securing rare earth minerals. Logistics and space commerce stocks may surge.",
195
+ affectedSymbols: ["STDY", "NLN"]
196
+ },
197
+ {
198
+ title: "Biosynthetics Regulatory Approval",
199
+ description: "Aurora Biosynthetics (AUBIO) receives approval for commercial distribution of synthetic products, opening new markets worth 200 billion credits.",
200
+ affectedSymbols: ["AUBIO"]
201
+ }
202
+ ];
203
+
204
+ // Update slider displays
205
+ document.getElementById('risk-slider').addEventListener('input', (e) => {
206
+ document.getElementById('risk-value').textContent = parseFloat(e.target.value).toFixed(1);
207
+ });
208
+
209
+ document.getElementById('temperature-slider').addEventListener('input', (e) => {
210
+ document.getElementById('temperature-value').textContent = parseFloat(e.target.value).toFixed(1);
211
+ });
212
+
213
+ document.getElementById('confidence-slider').addEventListener('input', (e) => {
214
+ document.getElementById('confidence-value').textContent = e.target.value;
215
+ });
216
+
217
+ // Update price when symbol changes
218
+ document.getElementById('trade-symbol').addEventListener('change', (e) => {
219
+ const prices = { VCG: 150, CSI: 200, STDY: 100, AUBIO: 75, NLN: 120 };
220
+ document.getElementById('trade-price').value = prices[e.target.value] || 100;
221
+ });
222
+
223
+ // Initialize price
224
+ document.getElementById('trade-symbol').dispatchEvent(new Event('change'));
225
+
226
+ // Next scenario button
227
+ document.getElementById('next-scenario-button').addEventListener('click', () => {
228
+ const randomScenario = scenarios[Math.floor(Math.random() * scenarios.length)];
229
+ gameState.currentScenario = randomScenario;
230
+ document.getElementById('scenario-text').textContent = randomScenario.description;
231
+ });
232
+
233
+ let pendingTrade = null;
234
+
235
+ // Get AI advice button (standalone)
236
+ document.getElementById('get-ai-advice-button').addEventListener('click', async () => {
237
+ const symbol = document.getElementById('trade-symbol').value;
238
+ const quantity = parseInt(document.getElementById('trade-quantity').value);
239
+ const price = parseFloat(document.getElementById('trade-price').value);
240
+
241
+ await showAIAdvice(symbol, quantity, price, 'buy');
242
+ });
243
+
244
+ // Buy button handler
245
+ document.getElementById('buy-button').addEventListener('click', async () => {
246
+ const symbol = document.getElementById('trade-symbol').value;
247
+ const quantity = parseInt(document.getElementById('trade-quantity').value);
248
+ const price = parseFloat(document.getElementById('trade-price').value);
249
+ const total = quantity * price;
250
+
251
+ if (total > gameState.balance) {
252
+ alert('Insufficient balance!');
253
+ return;
254
+ }
255
+
256
+ pendingTrade = { symbol, quantity, price, action: 'buy' };
257
+ await showAIAdvice(symbol, quantity, price, 'buy');
258
+ });
259
+
260
+ // Sell button handler
261
+ document.getElementById('sell-button').addEventListener('click', async () => {
262
+ const symbol = document.getElementById('trade-symbol').value;
263
+ const quantity = parseInt(document.getElementById('trade-quantity').value);
264
+ const price = parseFloat(document.getElementById('trade-price').value);
265
+
266
+ pendingTrade = { symbol, quantity, price, action: 'sell' };
267
+ await showAIAdvice(symbol, quantity, price, 'sell');
268
+ });
269
+
270
+ // Show AI advice
271
+ async function showAIAdvice(symbol, quantity, price, action) {
272
+ const aiMessage = document.getElementById('ai-message');
273
+ const aiActions = document.getElementById('ai-actions');
274
+
275
+ aiMessage.textContent = 'Getting AI advice...';
276
+ aiActions.style.display = 'none';
277
+
278
+ try {
279
+ if (window.gameAI && window.gameAI.askAI) {
280
+ // Get current slider values
281
+ const riskLevel = parseFloat(document.getElementById('risk-slider').value);
282
+ const temperature = parseFloat(document.getElementById('temperature-slider').value);
283
+ const confidence = parseFloat(document.getElementById('confidence-slider').value);
284
+
285
+ // Include scenario context in the question
286
+ const scenarioText = gameState.currentScenario.description;
287
+ const question = `Current Market Scenario: ${scenarioText}\n\nShould I ${action} ${quantity} shares of ${symbol} at $${price.toFixed(2)}? Consider the current scenario and provide a direct recommendation based on my risk tolerance of ${riskLevel}/10.`;
288
+
289
+ // Update AI parameters
290
+ if (window.gameAI.updateAIParams) {
291
+ window.gameAI.updateAIParams(riskLevel, temperature, confidence);
292
+ }
293
+
294
+ const response = await window.gameAI.askAI(question, {
295
+ risk_level: riskLevel,
296
+ temperature: temperature,
297
+ confidence_boost: confidence
298
+ });
299
+
300
+ aiMessage.textContent = response.answer || 'No advice available';
301
+
302
+ // Show action buttons if there's a pending trade
303
+ if (pendingTrade) {
304
+ aiActions.style.display = 'flex';
305
+ }
306
+ } else {
307
+ aiMessage.textContent = 'AI service not available. Check console for errors.';
308
+ }
309
+ } catch (error) {
310
+ console.error('AI advice error:', error);
311
+ aiMessage.textContent = 'Error getting AI advice. Check console.';
312
+ }
313
+ }
314
+
315
+ // Follow AI advice
316
+ document.getElementById('follow-advice-button').addEventListener('click', async () => {
317
+ if (!pendingTrade) return;
318
+
319
+ executeTrade(pendingTrade, true);
320
+ document.getElementById('ai-actions').style.display = 'none';
321
+ pendingTrade = null;
322
+ });
323
+
324
+ // Ignore advice but still trade
325
+ document.getElementById('ignore-advice-button').addEventListener('click', async () => {
326
+ if (!pendingTrade) return;
327
+
328
+ executeTrade(pendingTrade, false);
329
+ document.getElementById('ai-actions').style.display = 'none';
330
+ pendingTrade = null;
331
+ });
332
+
333
+ // Clear AI button
334
+ document.getElementById('clear-ai-button').addEventListener('click', () => {
335
+ document.getElementById('ai-message').innerHTML = '<p class="text-gray-500 italic">Adjust your settings above and click "Get AI Advice" to receive trading recommendations based on the current scenario.</p>';
336
+ document.getElementById('ai-actions').style.display = 'none';
337
+ pendingTrade = null;
338
+ });
339
+
340
+ // Execute trade
341
+ function executeTrade(trade, followedAdvice) {
342
+ const { symbol, quantity, price, action } = trade;
343
+ const total = quantity * price;
344
+
345
+ if (action === 'buy') {
346
+ gameState.balance -= total;
347
+ const existingPosition = gameState.positions.find(p => p.symbol === symbol);
348
+ if (existingPosition) {
349
+ existingPosition.quantity += quantity;
350
+ } else {
351
+ gameState.positions.push({ symbol, quantity, price });
352
+ }
353
+ } else { // sell
354
+ gameState.balance += total;
355
+ const existingPosition = gameState.positions.find(p => p.symbol === symbol);
356
+ if (existingPosition) {
357
+ existingPosition.quantity -= quantity;
358
+ if (existingPosition.quantity <= 0) {
359
+ gameState.positions = gameState.positions.filter(p => p.symbol !== symbol);
360
+ }
361
+ }
362
+ }
363
+
364
+ // Log trade
365
+ gameState.trades.unshift({
366
+ timestamp: new Date().toLocaleTimeString(),
367
+ symbol,
368
+ action,
369
+ quantity,
370
+ price: price.toFixed(2),
371
+ total: total.toFixed(2),
372
+ followedAdvice
373
+ });
374
+
375
+ // Update UI
376
+ updateUI();
377
+
378
+ // Log to backend
379
+ if (window.gameAI && window.gameAI.logDecision) {
380
+ window.gameAI.logDecision(symbol, action, quantity, price, followedAdvice);
381
+ }
382
+
383
+ // Ask for trust score
384
+ const trustScore = prompt('How much did you trust the AI advice? (1-10):');
385
+ if (trustScore && window.gameAI && window.gameAI.logDecision) {
386
+ window.gameAI.logDecision(symbol, action, quantity, price, followedAdvice, parseFloat(trustScore));
387
+ }
388
+ }
389
+
390
+ // Update UI
391
+ function updateUI() {
392
+ document.getElementById('balance').textContent = '$' + gameState.balance.toFixed(2);
393
+ document.getElementById('positions').textContent = gameState.positions.length;
394
+
395
+ const tradeHistory = document.getElementById('trade-history');
396
+ if (gameState.trades.length === 0) {
397
+ tradeHistory.innerHTML = '<p class="text-gray-400 text-center">No trades yet</p>';
398
+ } else {
399
+ tradeHistory.innerHTML = gameState.trades.map(trade => `
400
+ <div class="bg-gray-700 p-3 rounded flex justify-between items-center">
401
+ <div>
402
+ <span class="font-bold ${trade.action === 'buy' ? 'text-green-400' : 'text-red-400'}">
403
+ ${trade.action.toUpperCase()}
404
+ </span>
405
+ ${trade.quantity} ${trade.symbol} @ $${trade.price}
406
+ ${trade.followedAdvice ? '✅ (Followed AI)' : '❌ (Ignored AI)'}
407
+ </div>
408
+ <div class="text-right">
409
+ <p class="font-bold">$${trade.total}</p>
410
+ <p class="text-sm text-gray-400">${trade.timestamp}</p>
411
+ </div>
412
+ </div>
413
+ `).join('');
414
+ }
415
+ }
416
+ </script>
417
+ </body>
418
+ </html>
game_api.py ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ FastAPI Backend for Trading Game + AI Chatbot Integration
3
+ Supports tunable AI parameters for psychological experiments
4
+ """
5
+ from fastapi import FastAPI, HTTPException
6
+ from fastapi.middleware.cors import CORSMiddleware
7
+ from fastapi.staticfiles import StaticFiles
8
+ from pydantic import BaseModel
9
+ from typing import Optional, List, Dict
10
+ import json
11
+ import os
12
+ from datetime import datetime
13
+
14
+ # Import your existing chain from app.py
15
+ from app import chain, llm, ChatOpenAI, PromptTemplate
16
+ from langchain_core.prompts import ChatPromptTemplate
17
+
18
+ app = FastAPI(title="Trading Game AI Experiment API")
19
+
20
+ # CORS for local development
21
+ app.add_middleware(
22
+ CORSMiddleware,
23
+ allow_origins=["*"], # In production, specify your domain
24
+ allow_credentials=True,
25
+ allow_methods=["*"],
26
+ allow_headers=["*"],
27
+ )
28
+
29
+ # Serve static files from game directory
30
+ app.mount("/game", StaticFiles(directory="game", html=True), name="game")
31
+
32
+ # Experiment state storage (in production, use a database)
33
+ experiment_state = {}
34
+ game_sessions = {}
35
+
36
+ class AIMessageRequest(BaseModel):
37
+ question: str
38
+ chat_history: List[tuple] = []
39
+ risk_level: float = 5.0 # 0-10, affects advice certainty
40
+ temperature: float = 0.7 # 0.0-2.0, affects response randomness
41
+ confidence_boost: float = 0.0 # -100 to +100, manipulates trustworthiness
42
+ session_id: str = "default"
43
+
44
+ class TradingDecision(BaseModel):
45
+ session_id: str
46
+ symbol: str
47
+ action: str # "buy" or "sell"
48
+ quantity: int
49
+ price: float
50
+ ai_advice_followed: bool
51
+ trust_score: Optional[float] = None # 1-10, explicit trust rating
52
+
53
+ class ScenarioTrigger(BaseModel):
54
+ session_id: str
55
+ scenario_type: str # "volatility", "large_position", "loss_recovery", "news_event"
56
+ context: Dict
57
+ ai_required: bool = True
58
+
59
+ def get_ai_with_params(risk_level: float, temperature: float, confidence_boost: float):
60
+ """Create LLM with tunable parameters for experiment"""
61
+ # Adjust temperature based on risk level (higher risk = more variability)
62
+ adjusted_temp = temperature + (risk_level / 10.0) * 0.3
63
+
64
+ # Get model name from environment or use default
65
+ import os
66
+ model_name = os.getenv("HF_MODEL_NAME", "meta-llama/Llama-3.1-8B-Instruct:novita")
67
+ api_key = os.getenv("HF_TOKEN")
68
+ if not api_key:
69
+ raise ValueError("HF_TOKEN environment variable is not set.")
70
+
71
+ # Create new LLM instance with adjusted parameters
72
+ tuned_llm = ChatOpenAI(
73
+ model=model_name,
74
+ base_url="https://router.huggingface.co/v1",
75
+ api_key=api_key,
76
+ temperature=min(adjusted_temp, 2.0), # Cap at 2.0
77
+ max_tokens=512,
78
+ )
79
+ return tuned_llm
80
+
81
+ def get_contextual_prompt(context: Dict, risk_level: float, confidence_boost: float):
82
+ """Generate prompt that reflects risk level and confidence boost"""
83
+ risk_descriptor = {
84
+ 0: "extremely conservative",
85
+ 2: "very conservative",
86
+ 4: "conservative",
87
+ 5: "moderate",
88
+ 6: "moderately aggressive",
89
+ 8: "aggressive",
90
+ 10: "very aggressive"
91
+ }
92
+ risk_text = risk_descriptor.get(int(risk_level), "moderate")
93
+
94
+ confidence_text = ""
95
+ if confidence_boost > 20:
96
+ confidence_text = "You are highly confident in your recommendations."
97
+ elif confidence_boost > 0:
98
+ confidence_text = "You are confident in your recommendations."
99
+ elif confidence_boost < -20:
100
+ confidence_text = "You are uncertain and should express caution in your recommendations."
101
+
102
+ base_template = """
103
+ You are an AI trading advisor for the Quantum Financial Network. Your risk profile is {risk_level}.
104
+ {confidence_text}
105
+
106
+ You provide trading advice based on market data. Consider:
107
+ - Current market conditions: {market_context}
108
+ - Player portfolio status: {portfolio_context}
109
+ - Recent events: {events_context}
110
+
111
+ Answer the question with appropriate caution/certainty based on your risk profile.
112
+
113
+ Context:
114
+ {{context}}
115
+
116
+ Question: {{question}}
117
+
118
+ Answer:
119
+ """
120
+
121
+ return PromptTemplate(
122
+ input_variables=["context", "question"],
123
+ template=base_template.format(
124
+ risk_level=risk_text,
125
+ confidence_text=confidence_text,
126
+ market_context=context.get("market", "normal conditions"),
127
+ portfolio_context=context.get("portfolio", "standard portfolio"),
128
+ events_context=context.get("events", "no major events")
129
+ )
130
+ )
131
+
132
+ @app.post("/api/ai/chat")
133
+ async def chat_with_ai(request: AIMessageRequest):
134
+ """Main AI chat endpoint with tunable parameters"""
135
+ try:
136
+ # Get or initialize session
137
+ if request.session_id not in game_sessions:
138
+ game_sessions[request.session_id] = {
139
+ "chat_history": [],
140
+ "decisions": [],
141
+ "trust_scores": [],
142
+ "params_history": []
143
+ }
144
+
145
+ session = game_sessions[request.session_id]
146
+
147
+ # Use the existing chain from app.py for now (simplified for POC)
148
+ # Convert chat_history from list of tuples to proper format if needed
149
+ chat_history_tuples = []
150
+ if request.chat_history:
151
+ for item in request.chat_history:
152
+ if isinstance(item, (list, tuple)) and len(item) >= 2:
153
+ chat_history_tuples.append((str(item[0]), str(item[1])))
154
+
155
+ # Enhance the question with scenario context and slider parameters
156
+ # Extract scenario context if present in question
157
+ enhanced_question = request.question
158
+
159
+ # Add risk tolerance context to question if not already included
160
+ if "risk tolerance" not in enhanced_question.lower() and request.risk_level is not None:
161
+ risk_desc = {
162
+ 0: "extremely conservative",
163
+ 1: "very conservative",
164
+ 3: "conservative",
165
+ 5: "moderate",
166
+ 7: "moderately aggressive",
167
+ 9: "aggressive",
168
+ 10: "very aggressive"
169
+ }
170
+ risk_text = risk_desc.get(int(request.risk_level), "moderate")
171
+
172
+ if "Current Market Scenario" not in enhanced_question:
173
+ enhanced_question = f"Risk Profile: {risk_text} ({request.risk_level}/10)\n\n{enhanced_question}"
174
+
175
+ # Get AI response using the existing chain
176
+ result = chain({
177
+ "question": enhanced_question,
178
+ "chat_history": chat_history_tuples
179
+ })
180
+
181
+ # Log interaction for experiment
182
+ interaction = {
183
+ "timestamp": datetime.now().isoformat(),
184
+ "question": request.question,
185
+ "response": result["answer"],
186
+ "risk_level": request.risk_level,
187
+ "temperature": request.temperature,
188
+ "confidence_boost": request.confidence_boost
189
+ }
190
+ session["params_history"].append(interaction)
191
+
192
+ return {
193
+ "answer": result["answer"],
194
+ "sources": [doc.page_content[:100] for doc in result.get("source_documents", [])] if "source_documents" in result else [],
195
+ "interaction_id": len(session["params_history"]) - 1
196
+ }
197
+
198
+ except Exception as e:
199
+ import traceback
200
+ error_detail = str(e) + "\n" + traceback.format_exc()
201
+ raise HTTPException(status_code=500, detail=error_detail)
202
+
203
+ @app.post("/api/experiment/decision")
204
+ async def log_decision(decision: TradingDecision):
205
+ """Log player trading decisions for trust analysis"""
206
+ if decision.session_id not in game_sessions:
207
+ game_sessions[decision.session_id] = {
208
+ "chat_history": [],
209
+ "decisions": [],
210
+ "trust_scores": [],
211
+ "params_history": []
212
+ }
213
+
214
+ game_sessions[decision.session_id]["decisions"].append({
215
+ "timestamp": datetime.now().isoformat(),
216
+ "symbol": decision.symbol,
217
+ "action": decision.action,
218
+ "quantity": decision.quantity,
219
+ "price": decision.price,
220
+ "ai_advice_followed": decision.ai_advice_followed,
221
+ "trust_score": decision.trust_score
222
+ })
223
+
224
+ return {"status": "logged", "decision_id": len(game_sessions[decision.session_id]["decisions"]) - 1}
225
+
226
+ @app.post("/api/experiment/scenario")
227
+ async def trigger_scenario(scenario: ScenarioTrigger):
228
+ """Trigger situational scenarios that require AI assistance"""
229
+ scenario_prompts = {
230
+ "volatility": "The market is experiencing high volatility. A stock in your portfolio has moved 10% in the last hour. What should you do?",
231
+ "large_position": "You're about to make a large position trade ($10,000+). This would represent a significant portion of your portfolio. Should you proceed?",
232
+ "loss_recovery": "You're down 5% today. Would you like advice on whether to cut losses or hold your positions?",
233
+ "news_event": "Breaking news just released that affects several stocks in your watchlist. How should this impact your trading decisions?"
234
+ }
235
+
236
+ if scenario.scenario_type not in scenario_prompts:
237
+ raise HTTPException(status_code=400, detail="Unknown scenario type")
238
+
239
+ prompt = scenario_prompts[scenario.scenario_type]
240
+
241
+ # Return scenario data for frontend to trigger AI chat
242
+ return {
243
+ "scenario_type": scenario.scenario_type,
244
+ "prompt": prompt,
245
+ "context": scenario.context,
246
+ "requires_ai": scenario.ai_required
247
+ }
248
+
249
+ @app.get("/api/experiment/session/{session_id}")
250
+ async def get_session_data(session_id: str):
251
+ """Get all experiment data for a session"""
252
+ if session_id not in game_sessions:
253
+ raise HTTPException(status_code=404, detail="Session not found")
254
+
255
+ return game_sessions[session_id]
256
+
257
+ @app.get("/api/experiment/export/{session_id}")
258
+ async def export_experiment_data(session_id: str):
259
+ """Export experiment data as JSON for analysis"""
260
+ if session_id not in game_sessions:
261
+ raise HTTPException(status_code=404, detail="Session not found")
262
+
263
+ data = game_sessions[session_id]
264
+ return data
265
+
266
+ @app.get("/")
267
+ async def root():
268
+ """Redirect to game"""
269
+ from fastapi.responses import RedirectResponse
270
+ return RedirectResponse(url="/game/trade.html")
271
+
272
+ @app.get("/game")
273
+ async def game_redirect():
274
+ """Redirect to game"""
275
+ from fastapi.responses import RedirectResponse
276
+ return RedirectResponse(url="/game/trade.html")
277
+
278
+ if __name__ == "__main__":
279
+ import uvicorn
280
+ uvicorn.run(app, host="0.0.0.0", port=8000)
multiple_docs/availability.txt ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MARKET AVAILABILITY AND TRADING HOURS:
2
+
3
+ TRADING SESSION SCHEDULE:
4
+ Primary Markets operate 24/7 with automated systems, but human trading follows standard patterns:
5
+ - Pre-Market: 06:00-08:00 Standard Time (limited liquidity)
6
+ - Morning Session: 08:00-12:00 (highest volume, best for day trading)
7
+ - Midday Lull: 12:00-14:00 (lower volume, consolidation period)
8
+ - Afternoon Session: 14:00-18:00 (second highest volume period)
9
+ - Evening Session: 18:00-22:00 (moderate volume, institutional activity)
10
+ - After-Hours: 22:00-06:00 (automated trading only, wider spreads)
11
+
12
+ MARKET HOLIDAYS:
13
+ The following dates are market holidays (exchanges closed):
14
+ - Quantum New Year (January 1st)
15
+ - Founders Day (March 15th)
16
+ - Market Reconciliation Day (June 30th)
17
+ - Interplanetary Trade Summit (September 10th-12th)
18
+ - Year-End Settlement (December 28th-31st)
19
+
20
+ LONGEST TRADING SESSION:
21
+ Continuous trading is available Monday 08:00 through Friday 22:00 with no interruptions except scheduled maintenance windows.
22
+
23
+ MAINTENANCE WINDOWS:
24
+ - Weekly: Sunday 03:00-05:00 (system updates and reconciliation)
25
+ - Monthly: First Sunday 02:00-06:00 (major system upgrades)
26
+ - Emergency maintenance is announced with 4-hour notice minimum
27
+
28
+ LOWEST LIQUIDITY PERIODS:
29
+ - Sunday 01:00-07:00 (weekly low point)
30
+ - Holiday weekends (24-48 hour reduced activity)
31
+ - End-of-quarter settlement days (afternoon trading only)
32
+
33
+ BEST TRADING OPPORTUNITIES:
34
+ - Market opens (08:00) show highest momentum and liquidity
35
+ - Mid-morning (10:00-11:00) typically has news-driven volatility
36
+ - Pre-close (21:00-22:00) often sees institutional rebalancing
multiple_docs/background.txt ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ TRADING UNIVERSE BACKGROUND INFORMATION:
2
+
3
+ THE QUANTUM FINANCIAL NETWORK (QFN):
4
+ Established in 2030 following the Quantum Revolution, the QFN emerged as the primary financial infrastructure connecting Earth, Mars, and orbital stations. The network leverages quantum computing for instant cross-planetary transactions and real-time market data processing.
5
+
6
+ CURRENCY SYSTEM:
7
+ The primary currency, Credits (CRD), is backed by quantum computational resources rather than traditional gold or fiat systems. Each credit represents a standardized unit of quantum processing power that can be converted into actual computation time when needed.
8
+
9
+ MARKET GEOGRAPHY:
10
+ - Earth: 45% of total market activity
11
+ - Mars Colonies: 35% of market activity
12
+ - Orbital Stations: 15% of market activity
13
+ - Deep Space Operations: 5% of market activity
14
+
15
+ MAJOR ECONOMIC SECTORS:
16
+ 1. Quantum Computing (22% of market cap)
17
+ 2. Interplanetary Logistics (18% of market cap)
18
+ 3. Biotechnology (15% of market cap)
19
+ 4. Energy Systems (14% of market cap)
20
+ 5. AI and Automation (12% of market cap)
21
+ 6. Space Commerce (10% of market cap)
22
+ 7. Other Sectors (9% of market cap)
23
+
24
+ HISTORICAL CONTEXT:
25
+ The trading universe evolved from traditional Earth-based markets after the discovery of practical quantum computing in 2028. The ability to instantaneously process trades across planetary distances revolutionized financial markets, leading to the formation of the current multi-planetary trading system.
26
+
27
+ POPULATION AND DEMOGRAPHICS:
28
+ - Total Population: 18.7 billion across all territories
29
+ - Active Traders: 340 million registered accounts
30
+ - Institutional Accounts: 45,000 major institutions
31
+ - Daily Active Traders: 28-35 million on average
32
+
33
+ TECHNOLOGICAL INFRASTRUCTURE:
34
+ All trading occurs on quantum-secured blockchain networks with sub-millisecond latency even across interplanetary distances. AI trading algorithms account for approximately 67% of all transactions, with human traders managing the remaining 33%.
multiple_docs/chatbot_exp.txt ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ AUTOMATED TRADING SYSTEMS AND ALGORITHMS:
2
+
3
+ ALGORITHMIC TRADING OVERVIEW:
4
+ Automated trading systems account for approximately 67% of all market transactions. These AI-powered algorithms can process vast amounts of data and execute trades in microseconds, far faster than human traders.
5
+
6
+ QUANTUMMIND PRO ALGORITHM:
7
+ Developed by Cybernetic Systems Innovation (CSI), this flagship trading algorithm uses quantum computing principles to analyze market patterns across multiple dimensions simultaneously. It has demonstrated 94% accuracy in predicting major market movements.
8
+
9
+ POPULAR TRADING BOTS:
10
+ - QuantumScalper: High-frequency trading bot for arbitrage opportunities
11
+ - MomentumMaster: Detects and trades on price momentum patterns
12
+ - SectorRotator: Automatically rotates positions based on sector performance
13
+ - InterPlanetaryArb: Specializes in cross-planetary price differences
14
+
15
+ ALGORITHM PERFORMANCE METRICS:
16
+ Top-performing algorithms typically achieve:
17
+ - Sharpe ratios of 2.5-3.8
18
+ - Annual returns of 18-35% (with appropriate risk management)
19
+ - Maximum drawdowns of 8-15%
20
+
21
+ RISK MANAGEMENT IN ALGORITHMS:
22
+ All algorithmic trading systems must include:
23
+ - Automatic stop-loss mechanisms
24
+ - Position size limits based on volatility
25
+ - Daily loss limits (typically 2-5% of capital)
26
+ - Emergency shutdown protocols
27
+
28
+ BACKTESTING REQUIREMENTS:
29
+ Before deployment, all trading algorithms must be backtested on at least 5 years of historical data. Results must be verified by independent auditors and approved by the QFA.
30
+
31
+ COMMON ALGORITHM STRATEGIES:
32
+ - Mean reversion: Profits from price movements returning to historical averages
33
+ - Trend following: Identifies and rides market trends
34
+ - Market making: Provides liquidity and profits from bid-ask spreads
35
+ - Statistical arbitrage: Exploits temporary pricing inefficiencies
36
+
37
+ REGULATORY COMPLIANCE:
38
+ Algorithmic trading systems must be registered with the Market Integrity Board. Periodic audits ensure algorithms don't manipulate markets or create unfair advantages.
multiple_docs/contact.txt ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ HOW TO ACCESS TRADING MARKETS AND EXCHANGES:
2
+
3
+ PRIMARY EXCHANGE CONTACTS:
4
+
5
+ NEXUS EXCHANGE:
6
+ - Trading Floor: Central Quantum District, Level 47-52
7
+ - Customer Service: +1-800-NEXUS-24 (24/7 automated)
8
+ - Human Representative: Available 08:00-20:00 Standard Time
9
+ - Online Portal: portal.nexus-exchange.qfn
10
+ - Email Support: support@nexus-exchange.qfn
11
+ - For urgent trading issues, contact the Emergency Trading Hotline
12
+
13
+ STELLAR MARKETS:
14
+ - Trading Floor: Orbital Station Alpha, Sector B-12
15
+ - Customer Service: +1-800-STELLAR (24/7)
16
+ - Online Portal: stellar.markets.qfn
17
+ - Email: traders@stellar.markets.qfn
18
+ - Live chat available during market hours
19
+
20
+ AURORA TRADING HUB:
21
+ - Trading Floor: Bio-District 7, Aurora Tower
22
+ - Customer Service: +1-800-AURORA-7
23
+ - Online Portal: aurora.trading.qfn
24
+ - Email: info@aurora.trading.qfn
25
+ - Specialized support for biotech sector trades
26
+
27
+ REGULATORY INQUIRIES:
28
+ - Quantum Financial Authority: regulatory@qfa.qfn
29
+ - Market Integrity Board: compliance@mib.qfn
30
+ - Emergency Market Intervention: +1-888-MARKET-911
31
+
32
+ ACCOUNT SERVICES:
33
+ - New Account Setup: accounts@nexus-exchange.qfn
34
+ - Account Management: available via all exchange portals
35
+ - Trading License Applications: licenses@qfa.qfn
36
+ - Verification typically takes 24-48 hours for standard accounts
multiple_docs/cv.txt ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ TRADING UNIVERSE OVERVIEW - QUANTUM FINANCIAL NETWORKS
2
+
3
+ MARKET STRUCTURE:
4
+ The Quantum Financial Network operates across three major exchanges:
5
+ - Nexus Exchange (Primary Market) - handles 65% of all trades
6
+ - Stellar Markets (Secondary Market) - specializes in derivatives and futures
7
+ - Aurora Trading Hub (Alternative Market) - focuses on emerging sectors and startups
8
+
9
+ MAJOR TRADING COMPANIES:
10
+
11
+ VERIDIAN CAPITAL GROUP (VCG)
12
+ - Market Cap: 850 billion credits
13
+ - Primary Sector: Energy and Quantum Computing
14
+ - Trading Pairs: VCG/CRD, VCG/USD, VCG/ETH
15
+ - Headquarters: Central Quantum District
16
+ - Founded: 2042
17
+ - Key Products: Quantum processor futures, energy derivatives, algorithmic trading systems
18
+
19
+ STELLAR DYNAMICS CORP (STDY)
20
+ - Market Cap: 720 billion credits
21
+ - Primary Sector: Space Commerce and Interplanetary Logistics
22
+ - Trading Pairs: STDY/CRD, STDY/MARS, STDY/AST
23
+ - Headquarters: Orbital Station Alpha
24
+ - Founded: 2038
25
+ - Key Products: Space freight futures, asteroid mining contracts, lunar real estate securities
26
+
27
+ AURORA BIOSYNTHETICS (AUBIO)
28
+ - Market Cap: 450 billion credits
29
+ - Primary Sector: Biotechnology and Genetic Engineering
30
+ - Trading Pairs: AUBIO/CRD, AUBIO/GENE, AUBIO/BIO
31
+ - Headquarters: Bio-District 7
32
+ - Founded: 2045
33
+ - Key Products: Genetic modification licenses, synthetic organism IPOs, biotech innovation bonds
34
+
35
+ NEXUS LOGISTICS NETWORK (NLN)
36
+ - Market Cap: 680 billion credits
37
+ - Primary Sector: Transportation and Supply Chain
38
+ - Trading Pairs: NLN/CRD, NLN/LOG, NLN/TRANS
39
+ - Headquarters: Transport Hub Gamma
40
+ - Founded: 2035
41
+ - Key Products: Shipping futures, autonomous vehicle fleet shares, supply chain derivatives
42
+
43
+ CYBERNETIC SYSTEMS INNOVATION (CSI)
44
+ - Market Cap: 920 billion credits
45
+ - Primary Sector: AI and Autonomous Systems
46
+ - Trading Pairs: CSI/CRD, CSI/AI, CSI/ROB
47
+ - Headquarters: Digital Innovation District
48
+ - Founded: 2032
49
+ - Key Products: AI training datasets, robot workforce bonds, neural network processing futures
50
+
51
+ TRADING CURRENCIES:
52
+ - CRD (Credit) - Primary currency, backed by quantum computational resources
53
+ - QTN (Quantum Token) - Cryptocurrency tied to quantum processing power
54
+ - MARS - Martian colony currency
55
+ - AST - Asteroid mining token
56
+ - GENE - Biotechnology sector token
57
+
58
+ MARKET HOURS:
59
+ Primary Markets: 24/7 (automated trading)
60
+ Human Traders: 08:00-22:00 Standard Time
61
+ High Volume Periods: 10:00-12:00, 14:00-16:00 (peak trading windows)
62
+
63
+ REGULATORY BODIES:
64
+ - Quantum Financial Authority (QFA) - Primary regulator
65
+ - Interplanetary Trade Commission (ITC) - Cross-planetary oversight
66
+ - Market Integrity Board (MIB) - Prevents manipulation and fraud
multiple_docs/education.txt ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ TRADING CERTIFICATIONS AND MARKET QUALIFICATIONS:
2
+
3
+ PROFESSIONAL TRADING LICENSES:
4
+
5
+ LEVEL 1 - RETAIL TRADER CERTIFICATE:
6
+ Basic qualification for individual traders. Covers:
7
+ - Market fundamentals and basic analysis
8
+ - Risk management principles
9
+ - Regulatory compliance requirements
10
+ - Available through online courses (2-week program)
11
+
12
+ LEVEL 2 - PROFESSIONAL TRADER LICENSE:
13
+ Required for managing accounts over 1 million credits. Includes:
14
+ - Advanced technical and fundamental analysis
15
+ - Interplanetary trading regulations
16
+ - Quantum algorithm understanding
17
+ - Ethics and market integrity training
18
+ - 6-month certification program
19
+
20
+ LEVEL 3 - INSTITUTIONAL TRADER CERTIFICATION:
21
+ For trading on behalf of institutions. Covers:
22
+ - Large-scale position management
23
+ - Algorithm development and backtesting
24
+ - Cross-market arbitrage strategies
25
+ - Regulatory reporting and compliance
26
+ - 12-month intensive program with practical exams
27
+
28
+ SPECIALIZED CERTIFICATIONS:
29
+
30
+ QUANTUM FINANCE SPECIALIST:
31
+ Advanced certification focusing on quantum computing applications in trading.
32
+ - Quantum algorithm design
33
+ - Quantum-resistant security protocols
34
+ - High-frequency quantum trading systems
35
+
36
+ INTERPLANETARY TRADE SPECIALIST:
37
+ Specialization in cross-planetary trading and currency arbitrage.
38
+ - Martian and orbital market dynamics
39
+ - Interplanetary tax treaties
40
+ - Logistics-based trading strategies
41
+
42
+ BIOTECH SECTOR ANALYST:
43
+ Focus on biotechnology and life sciences markets.
44
+ - Genetic engineering market fundamentals
45
+ - FDA-equivalent approval processes
46
+ - Synthetic biology investment analysis
47
+
48
+ AI/ROBOTICS MARKET EXPERT:
49
+ Specialization in AI and automation sectors.
50
+ - Machine learning company valuation
51
+ - Robot workforce market dynamics
52
+ - Neural network processing futures
53
+
54
+ CONTINUING EDUCATION REQUIREMENTS:
55
+ All licensed traders must complete 40 hours of continuing education annually, covering:
56
+ - Market regulation updates
57
+ - New trading technologies
58
+ - Risk management best practices
59
+ - Ethical trading standards
60
+
61
+ POPULAR TRAINING PROVIDERS:
62
+ - Quantum Finance Institute (QFI)
63
+ - Nexus Exchange Education Center
64
+ - Interplanetary Trading Academy
65
+ - Market Intelligence University
multiple_docs/experience.txt ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ RECENT TRADING MARKET EVENTS AND HISTORY:
2
+
3
+ MAJOR MARKET MOVEMENTS (2048-2049):
4
+
5
+ JANUARY 2048 - STELLAR DYNAMICS EXPANSION:
6
+ Stellar Dynamics Corp announced successful asteroid mining operations, causing STDY stock to surge 47% over 3 weeks. The company secured contracts worth 12 billion credits for rare earth minerals from Asteroid Belt 7.
7
+
8
+ MARCH 2048 - CYBERNETIC SYSTEMS AI BREAKTHROUGH:
9
+ CSI launched their next-generation AI trading algorithm, "QuantumMind Pro", resulting in a 62% increase in their market cap. The algorithm successfully predicted 94% of major market movements in its first quarter, attracting institutional investors.
10
+
11
+ JUNE 2048 - AURORA BIOSYNTHETICS REGULATORY APPROVAL:
12
+ Aurora Biosynthetics received approval from the QFA to begin commercial distribution of their synthetic food products, causing AUBIO shares to jump 35%. The approval opened new markets worth an estimated 200 billion credits.
13
+
14
+ SEPTEMBER 2048 - NEXUS EXCHANGE MERGER TALKS:
15
+ Nexus Logistics Network and Veridian Capital Group announced preliminary merger discussions, causing both stocks to experience high volatility. VCG rose 18% while NLN dropped 12% amid market uncertainty about the proposed structure.
16
+
17
+ DECEMBER 2048 - MARTIAN COLONY CURRENCY LAUNCH:
18
+ The Martian Council officially launched the MARS currency, pegged to water reserves and real estate assets. Initial trading saw massive volatility with values swinging between 0.8-1.4 CRD per MARS in the first week.
19
+
20
+ FEBRUARY 2049 - QUANTUM PROCESSING SHORTAGE:
21
+ A global shortage of quantum processing chips caused all tech-related stocks to plummet. CSI fell 28%, while energy companies like VCG surged 33% as investors sought safe havens in traditional energy sectors.
22
+
23
+ MAY 2049 - STELLAR DYNAMICS LOGISTICS SUCCESS:
24
+ NLN completed their first interplanetary cargo delivery using autonomous spacecraft, reducing shipping costs by 67%. This breakthrough increased NLN market value by 41% and reshaped the logistics sector.
25
+
26
+ AUGUST 2049 - BIOSYNTHETICS MARKET EXPANSION:
27
+ Aurora Biosynthetics announced partnerships with 15 major food corporations, expanding their market reach to three new planetary systems. AUBIO stock experienced the largest single-day gain in history, rising 52%.
28
+
29
+ MARKET VOLATILITY INDICATORS:
30
+ - Average Daily Volume: 45-65 billion credits
31
+ - Peak Trading Volume Day: December 18, 2048 (127 billion credits)
32
+ - Most Volatile Stock: STDY (average daily swing 8.2%)
33
+ - Most Stable Stock: VCG (average daily swing 2.1%)
34
+
35
+ KEY TRADING PATTERNS:
36
+ - Monday openings typically see 12% higher volume
37
+ - End-of-quarter periods show increased algorithmic trading (up to 40% more)
38
+ - Lunar phase cycles historically correlate with 3-5% market movements in energy sectors
multiple_docs/various.txt ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ VARIOUS TRADING INFORMATION AND MARKET DETAILS:
2
+
3
+ POPULAR TRADING STRATEGIES:
4
+
5
+ MOMENTUM TRADING:
6
+ Many traders focus on stocks with strong price movements, particularly in the AI and biotech sectors. CSI and AUBIO are popular choices for momentum traders due to frequent news-driven volatility.
7
+
8
+ PAIRS TRADING:
9
+ Common pairs include VCG/CSI (energy vs tech), STDY/NLN (space commerce vs logistics), and AUBIO/CSI (biotech vs AI). These strategies capitalize on sector correlations.
10
+
11
+ ARBITRAGE OPPORTUNITIES:
12
+ Interplanetary price differences create arbitrage opportunities. Mars-based assets often trade at 2-5% premiums compared to Earth prices due to supply constraints.
13
+
14
+ QUANTUM ALGORITHM TRADING:
15
+ Many institutional investors use proprietary quantum algorithms that can analyze multiple market dimensions simultaneously, giving them advantages in high-frequency trading.
16
+
17
+ RISK MANAGEMENT:
18
+ - Stop-loss orders are automatically executed by AI systems
19
+ - Maximum position sizes are regulated by QFA based on account type
20
+ - Margin requirements vary from 10-50% depending on security volatility
21
+
22
+ TAX IMPLICATIONS:
23
+ - Capital gains taxed at 15-25% depending on holding period
24
+ - Interplanetary trades may have additional tax treaties
25
+ - Loss harvesting strategies are popular year-end activities
26
+
27
+ MARKET SENTIMENT INDICATORS:
28
+ - VCG Index: Tracks energy sector confidence (currently bullish)
29
+ - Tech Momentum Gauge: Measures AI/automation sector strength
30
+ - Interplanetary Trade Index: Overall cross-planetary commerce health
31
+
32
+ COMMON TRADING MISTAKES:
33
+ - Overtrading during low-liquidity periods
34
+ - Ignoring interplanetary time zones
35
+ - Failing to account for quantum processing delays during high-volume periods
36
+ - Not using appropriate risk management tools
37
+
38
+ INVESTMENT PRODUCTS:
39
+ - Stocks: Direct company ownership (most popular)
40
+ - Futures: Contracts for future delivery of quantum resources
41
+ - Options: Rights to buy/sell at specific prices
42
+ - Bonds: Corporate debt instruments with fixed returns
43
+ - ETFs: Diversified sector-based investment funds
pyproject.toml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "trading-game-ai"
3
+ version = "0.1.0"
4
+ description = "Trading game with AI assistant for psychological experiments"
5
+ requires-python = ">=3.9"
6
+ dependencies = [
7
+ "gradio>=4.0.0",
8
+ "langchain>=0.1.0",
9
+ "langchain-community>=0.0.20",
10
+ "langchain-core>=0.1.0",
11
+ "chromadb>=0.4.0",
12
+ "sentence-transformers>=2.2.0",
13
+ "requests>=2.31.0",
14
+ "python-dotenv>=1.0.0",
15
+ "langchain-huggingface>=0.3.1",
16
+ "transformers>=4.57.6",
17
+ "torch>=2.8.0",
18
+ "accelerate>=1.10.1",
19
+ "huggingface-hub>=0.36.0",
20
+ "langchain-openai>=0.3.35",
21
+ "openai>=2.15.0",
22
+ "fastapi>=0.128.0",
23
+ "uvicorn>=0.39.0",
24
+ "python-multipart>=0.0.20",
25
+ ]
26
+
27
+ [project.optional-dependencies]
28
+ hf-spaces = [
29
+ "pysqlite3-binary>=0.5.0",
30
+ ]
31
+
32
+ [tool.uv]
33
+ dev-dependencies = []