Abdullah6395 commited on
Commit
ce92321
·
verified ·
1 Parent(s): ff40857

Upload 15 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* 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
 
 
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
36
+ db/bitcoin_data.db filter=lfs diff=lfs merge=lfs -text
ChatBot.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_community.utilities import SQLDatabase
2
+ from langchain_tavily import TavilySearch
3
+ from langgraph.prebuilt import create_react_agent
4
+ from langchain_community.agent_toolkits import SQLDatabaseToolkit
5
+ from langchain.chat_models import init_chat_model
6
+ from dotenv import load_dotenv
7
+ from langchain.prompts import ChatPromptTemplate
8
+ from langgraph.graph import StateGraph,START,END
9
+ from typing import TypedDict
10
+ from langchain import hub
11
+ import os
12
+ load_dotenv()
13
+ mistralapi=os.environ['MISTRAL']
14
+ taviliy=os.environ['TAVILY']
15
+
16
+ llm=init_chat_model("ministral-8b-latest",model_provider="mistralai",api_key=mistralapi)
17
+
18
+ db=SQLDatabase.from_uri("sqlite:///db/bitcoin_data.db")
19
+ toolkit=SQLDatabaseToolkit(db=db,llm=llm)
20
+ sqltools=toolkit.get_tools()
21
+ table_info=db.get_table_info()
22
+ sqlprompt=hub.pull("langchain-ai/sql-agent-system-prompt")
23
+ sqlprompt=sqlprompt.format(dialect="SQLite", top_k=5)
24
+
25
+ class GraphState(TypedDict):
26
+ userinput:str
27
+ movewhere:str
28
+ aimessages:list[str]
29
+ query:str
30
+ finalanswer:str
31
+
32
+
33
+ def router(state:GraphState):
34
+ userinput=state["userinput"]
35
+ prompt=ChatPromptTemplate.from_messages([
36
+ ("system","You are assistant who have to decide what user need right now reponsd with 'News' or 'Analysis' or 'Research' or 'all' 'none' dont use any puctuation, symbols or extra text in the reponse. Remember when you respond with analysis we run sql queries on a database with bitcoin high low volume and rsi mcad etc respond this only when the user asks about statistical analysis on the bitcoin data. When you select Research we search internet for any financial oredictions or articles. You must first understand prompt and check which option is best for better responses. Respond with 'all' when i the query of user is diverse like getting some financial advice or require some extra info other than seraching old database. If none of the options is required or question is not about bitcoin or related terms or personalities respond 'none'"),
37
+ ("user",f"Here is the input from user '{userinput}'")
38
+ ])
39
+ chain=prompt | llm
40
+ response=chain.invoke({'userinput':userinput})
41
+ print(response.content)
42
+ state['movewhere']=response.content.lower()
43
+ return state
44
+
45
+ def querygen(state:GraphState):
46
+ userinput=state['userinput']
47
+ prompt=ChatPromptTemplate.from_messages([
48
+ ("system","You are a assistant who would generate questions for an agent which generates sql queries for data {datainfo}. Analyze the user input and generate the questions for that agent that gives maximum information that user need for better answer. You should ask only 5 statistical questions without heading just simple questions"),
49
+ ("user","Here is a prompt from user '{userinput}'")
50
+ ])
51
+ chain=prompt | llm
52
+ response=chain.invoke({"datainfo":table_info,'userinput':userinput})
53
+ state['query']=response.content
54
+ return state
55
+
56
+ def news(state:GraphState):
57
+ news_update=TavilySearch(
58
+ tavily_api_key=taviliy,
59
+ max_results=5,
60
+ topic="news"
61
+ )
62
+ userinput=state['userinput']
63
+ searchagent=create_react_agent(llm,tools=[news_update])
64
+ response=searchagent.invoke({"messages":[{"role":"user","content":userinput}]})
65
+ state['aimessages'].append(response['messages'][-1].content)
66
+ return state
67
+
68
+ def analysis(state:GraphState):
69
+ queries=state['query']
70
+ sqlagent=create_react_agent(llm,tools=sqltools,prompt=sqlprompt)
71
+ response=sqlagent.invoke({"messages":[{"role":"user","content":queries}]})
72
+ state['aimessages'].append(response['messages'][-1].content)
73
+ return state
74
+
75
+ def search(state:GraphState):
76
+ userinput=state['userinput']
77
+ finance_update=TavilySearch(
78
+ tavily_api_key=taviliy,
79
+ max_results=5,
80
+ topic="finance"
81
+ )
82
+ searchagent=create_react_agent(llm,tools=[finance_update])
83
+ response=searchagent.invoke({"messages":[{"role":"user","content":userinput}]})
84
+ state['aimessages'].append(response['messages'][-1].content)
85
+ return state
86
+
87
+ def finalnode(state:GraphState):
88
+ userinput=state['userinput']
89
+ aimessages=state['aimessages']
90
+ prompt=ChatPromptTemplate.from_messages([
91
+ ("system","You are an agent who have to write final comprehensive answer based on user query and the provided docs given by different AI agents here are some docs that might help {aimessages}"),
92
+ ("user","{userinput}")
93
+ ])
94
+ chain=prompt | llm
95
+ response=chain.invoke({"aimessages":aimessages,"userinput":userinput})
96
+ state['finalanswer']=response.content
97
+ return state
98
+
99
+ def runall(state:GraphState):
100
+ return state
101
+
102
+ def random(state:GraphState):
103
+ response=llm.invoke(state['userinput'])
104
+ state['finalanswer']=response.content
105
+ return state
106
+
107
+ builder=StateGraph(GraphState)
108
+ builder.add_node("decide",router)
109
+ builder.add_node("random",random)
110
+
111
+ builder.add_edge(START,"decide")
112
+ builder.add_conditional_edges("decide",lambda state:state['movewhere'],
113
+ {
114
+ "news":"news",
115
+ "analysis":"querygen",
116
+ "research":"search",
117
+ "none":"random",
118
+ "all":"runall"
119
+ })
120
+ builder.add_sequence([
121
+ ("runall",runall),
122
+ ("queerygenall",querygen),
123
+ ("analyzeall",analysis),
124
+ ("newsall",news),
125
+ ("searchall",search),
126
+ ("finalnodeall",finalnode)
127
+ ])
128
+ builder.add_sequence([("search",search),("finalsearch",finalnode)])
129
+ builder.add_sequence([("news",news),("finalnews",finalnode)])
130
+ builder.add_sequence([("querygen",querygen),("analyze",analysis),("finalanalyze",finalnode)])
131
+ builder.add_edge("random",END)
132
+
133
+ graph=builder.compile()
Data/Bitcoin_data.csv ADDED
The diff for this file is too large to render. See raw diff
 
Data/daily_bitcoin_price.csv ADDED
The diff for this file is too large to render. See raw diff
 
Data/modeldata.csv ADDED
@@ -0,0 +1 @@
 
 
1
+ open_time,open,high,low,close,volume,close_time,quote_asset_volume, number_of_trades, taker_buy_base_asset_volume,taker_buy_quote_asset_volume
Data/portfolio.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "amount":1000000,
3
+ "trades":[],
4
+ "tradesDone":[],
5
+ "PNL":0,
6
+ "bitcoin_holdings":0
7
+ }
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ RUN useradd -m -u 1000 user
4
+ USER user
5
+ ENV PATH="/home/user/.local/bin:$PATH"
6
+
7
+ WORKDIR /app
8
+
9
+ COPY --chown=user ./requirements.txt requirements.txt
10
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
11
+
12
+ COPY --chown=user . /app
13
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import onnxruntime as ort
2
+ import pickle
3
+ import joblib
4
+ import numpy as np
5
+ import json
6
+ import os
7
+ import requests
8
+ import pandas as pd
9
+ from flask import Flask,render_template,jsonify,request
10
+ import plotly.graph_objects as go
11
+ from livereload import Server
12
+ from dotenv import load_dotenv
13
+ from ta.momentum import RSIIndicator
14
+ from ta.trend import MACD, EMAIndicator
15
+ from ta.volatility import AverageTrueRange
16
+ import plotly.io as pio
17
+ import ChatBot as cb
18
+
19
+ load_dotenv()
20
+ api=os.environ['API_KEY']
21
+ head={
22
+ "x-cg-demo-api-key":api
23
+ }
24
+ params={
25
+ "vs_currency":"usd",
26
+ "days":1
27
+ }
28
+ lines=requests.get("https://api.coingecko.com/api/v3/coins/bitcoin/ohlc",params=params,headers=head).json()
29
+
30
+ def preprocess(lines):
31
+ cols=["open_time","open","high","low","close"]
32
+ data=pd.DataFrame(lines,columns=cols)
33
+ data['open_time']=pd.to_datetime(data['open_time'],unit='ms')
34
+ data['rsi']=RSIIndicator(close=data["close"],window=14,fillna=0).rsi()
35
+ macd=MACD(close=data["close"])
36
+ data["macd"]=macd.macd()
37
+ data['macd_signal']=macd.macd_signal()
38
+ data['ema_20']=EMAIndicator(close=data['close'],window=14,fillna=0).ema_indicator()
39
+ data['atr']=AverageTrueRange(high=data['high'],low=data['low'],close=data['close'],window=14).average_true_range()
40
+ data['weekday']=data['open_time'].dt.day_of_week
41
+ data['day_of_year']=data['open_time'].dt.day_of_year
42
+ data['hour']=data['open_time'].dt.hour
43
+ data['month_end']=data['open_time'].dt.is_month_end.astype(np.float32)
44
+ data['month_start']=data['open_time'].dt.is_month_start.astype(np.float32)
45
+ data['quarter_start']=data['open_time'].dt.is_quarter_start.astype(np.float32)
46
+ data["quarter_end"]=data['open_time'].dt.is_quarter_end.astype(np.float32)
47
+ data["year"]=data['open_time'].dt.year
48
+ data['month']=data['open_time'].dt.month
49
+ data['is_recent']=data['open_time'].dt.year>2023
50
+ data['is_recent']=data['is_recent'].astype(np.float64)
51
+ data=data[data["open_time"].dt.minute==0].reset_index(drop=True)
52
+ return data
53
+ data=preprocess(lines)
54
+
55
+ session=ort.InferenceSession("models/lstm_model.onnx")
56
+
57
+ with open("models/hourly_stat.pkl","rb") as f:
58
+ hourly_model=pickle.load(f)
59
+
60
+ with open("models/daily_stat.pkl","rb") as f:
61
+ daily_model=pickle.load(f)
62
+
63
+ input_scaler=joblib.load("models/input_scaler.pkl")
64
+
65
+ output_scaler=joblib.load("models/ouput_scaler.pkl")
66
+
67
+ with open("Data/news.json","r") as f:
68
+ news=json.load(f)
69
+
70
+ with open("Data/portfolio.json","r") as f:
71
+ portfolio=json.load(f)
72
+
73
+ def predict_onnx(data):
74
+ ourdata=data.drop(columns=['open_time'])
75
+ impfactor=np.linspace(0,1,15).reshape(15,1)
76
+ scaled=input_scaler.transform(ourdata)
77
+ X=np.append(scaled,impfactor,axis=1).reshape(1,15,20)
78
+ input_name = session.get_inputs()[0].name
79
+ output = session.run(None, {input_name: X.astype(np.float32)})
80
+ return pd.DataFrame({
81
+ "ds":data[-15:]['open_time']+pd.Timedelta(hours=1),
82
+ "x":output_scaler.inverse_transform(output[0][0].reshape(1,15)).reshape(15)
83
+ })
84
+ def precict_ml(data):
85
+ prediction=hourly_model.predict(data.rename(columns={"open_time":"ds","close":"previous_close"}).fillna(0))
86
+ return pd.DataFrame({
87
+ "ds":data['open_time']+pd.Timedelta(hours=1),
88
+ "y":prediction['yhat']
89
+ })
90
+ def plot_chart():
91
+ temp=pd.DataFrame()
92
+ batchsize=15
93
+ for i in range(0,len(data),batchsize):
94
+ input_data=data[len(data)-i-batchsize:len(data)-i].fillna(0)
95
+ if len(input_data)<batchsize:
96
+ prediction=predict_onnx(data[:15].fillna(0))[:-(batchsize-(len(data)-i))]
97
+ temp=pd.concat([prediction,temp])
98
+ break
99
+ prediction=predict_onnx(input_data)
100
+ temp=pd.concat([prediction,temp])
101
+ predicted=temp
102
+ mlprediction=precict_ml(data)
103
+ fig=go.Figure()
104
+ fig.add_trace(go.Candlestick(
105
+ x=data["open_time"],
106
+ open=data["open"],
107
+ high=data['high'],
108
+ low=data['low'],
109
+ close=data['close'],
110
+ name="liveprice"
111
+ ))
112
+ fig.add_trace(go.Scatter(
113
+ x=predicted['ds'],
114
+ y=predicted['x'],
115
+ name="lstm_prediction"
116
+ ))
117
+ fig.add_trace(go.Scatter(
118
+ x=mlprediction['ds'],
119
+ y=mlprediction['y'],
120
+ name="MlPrediction"
121
+ )
122
+ )
123
+ fig.update_layout(
124
+ xaxis=dict(
125
+ range=[data['open_time'].iloc[-15],data['open_time'].iloc[-1]],
126
+ rangeslider=dict(visible=False),
127
+ fixedrange=False
128
+ ),
129
+ paper_bgcolor='rgba(113, 78, 161, 0.5)',
130
+ plot_bgcolor='rgba(113, 78, 161, 0.5)',
131
+ font_color="white",
132
+ dragmode="pan"
133
+ )
134
+ return fig
135
+
136
+ def Predict20Days():
137
+ today=pd.to_datetime("today").normalize()
138
+ timerange=pd.date_range(start=today,end=today+pd.Timedelta(days=20),freq="d")
139
+ input_data=pd.DataFrame(timerange,columns=['ds'])
140
+ pred=daily_model.predict(input_data)
141
+ return {
142
+ "ds":timerange,
143
+ "y":pred['yhat']
144
+ }
145
+
146
+ def make_20_days_chart():
147
+ df=Predict20Days()
148
+ fig=go.Figure()
149
+ fig.add_trace(go.Scatter(
150
+ x=df['ds'],
151
+ y=df['y']
152
+ ))
153
+ fig.update_layout(
154
+ paper_bgcolor='rgba(113, 78, 161, 0.5)',
155
+ plot_bgcolor='rgba(113, 78, 161, 0.5)',
156
+ font_color="white",
157
+ dragmode="pan"
158
+ )
159
+ return fig
160
+
161
+ app=Flask(__name__)
162
+ app.config['TEMPLATES_AUTO_RELOAD'] = True
163
+ @app.route("/")
164
+ def front():
165
+ figure=plot_chart()
166
+ next20days=make_20_days_chart()
167
+ config={
168
+ "displayModeBar":False
169
+ }
170
+ plot=pio.to_html(figure,full_html=False,config=config)
171
+ plot2=pio.to_html(next20days,full_html=False,config=config)
172
+ return render_template("index.html",chart=plot,newsset=news,pred20=plot2)
173
+
174
+ @app.route("/update_chart")
175
+ def give_update():
176
+ global lines
177
+ global data
178
+ newlines=requests.get("https://api.coingecko.com/api/v3/coins/bitcoin/ohlc",params=params,headers=head).json()
179
+ lines.append(newlines)
180
+ data=preprocess(lines)
181
+ data=data.drop_duplicates()
182
+ predonnx=predict_onnx(data.iloc[-15:].fillna(0))
183
+ predml=precict_ml(data.iloc[[-1]])
184
+ return jsonify({
185
+ "x":[str(data['open_time'].iloc[-1]),str(predonnx['ds']),str(predml['ds'])],
186
+ "open":float(data['open'].iloc[-1]),
187
+ "high":float(data["high"].iloc[-1]),
188
+ "low":float(data['low'].iloc[-1]),
189
+ "close":float(data['close'].iloc[-1]),
190
+ "y":[float(predonnx['x']),float(predml['y'])]
191
+ })
192
+
193
+ @app.route("/get_response",methods=['POST'])
194
+ def chat():
195
+ res=request.get_json()
196
+ query=res['text']
197
+ inputinvoke={
198
+ "userinput":query,
199
+ "movewhere":"",
200
+ "aimessages":[],
201
+ "query":"",
202
+ "finalanswer":""
203
+ }
204
+ response=cb.graph.invoke(inputinvoke)
205
+ return jsonify(response=response['finalanswer'])
206
+ if __name__=="__main__":
207
+ server=Server(app.wsgi_app)
208
+ server.watch("templates/*.html")
209
+ server.serve(open_url_delay=True,port=8000)
210
+
211
+
db/bitcoin_data.db ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:46994e6de2be5be140de2d7391dfa5f955b26228954183b9c6138bb003e2eb10
3
+ size 10829824
models/daily_stat.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3830450ddbf7da2b6a487a63156d11524fb61fbbb3acc815c7da20a06a5a82a5
3
+ size 264600
models/hourly_stat.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0a4ac589ffced0ce751bc5fd9b70c0b9d95b2d99c9a5135d45ddaecbb1ab0277
3
+ size 11240526
models/input_scaler.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4609bf36aac5b361cd26ce883c87ec7890fcd90019c563159764e0bbf42ebcaf
3
+ size 1871
models/lstm_model.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:26160009c3b3db4579423a9bca33a517dc28e25848c4c4a006a7383fcedd8449
3
+ size 104079
models/ouput_scaler.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fa3b69b83f876def26db98b9c9c3cc60d11839aca37bdd800fdbf3c6e7c74f0a
3
+ size 975
requirements.txt ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ onnxruntime
2
+ pickle-mixin
3
+ joblib
4
+ numpy
5
+ jsonlib
6
+ requests
7
+ pandas
8
+ flask
9
+ plotly
10
+ livereload
11
+ python-dotenv
12
+ ta
13
+ langchain
14
+ langgraph
15
+ langchain_community
16
+ langchain_tavily
17
+ uvicorn
templates/index.html ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <script src="https://cdn.plot.ly/plotly-2.32.0.min.js"></script>
7
+ <title>Trading Analysis</title>
8
+ </head>
9
+ <style>
10
+ .page{
11
+ display: flex;
12
+ flex-direction: row;
13
+ }
14
+ .tab1{
15
+ flex: 0 0 70%;
16
+ height:100vh;
17
+ scrollbar-width: none;
18
+ overflow: auto;
19
+ }
20
+ .tab2{
21
+ flex: 0 0 30%;
22
+ height:100vh;
23
+ scrollbar-width: none;
24
+ border-left: 2px solid gray;
25
+ overflow: auto;
26
+ }
27
+ #news{
28
+ margin: 20px;
29
+ }
30
+ #header{
31
+ display: flex;
32
+ flex-direction: row;
33
+ justify-content: space-between;
34
+ }
35
+ #boticon{
36
+ position:relative;
37
+ border-radius: 20px;
38
+ width:100px;
39
+ height:40px;
40
+ top:2.5px;
41
+ border: none;
42
+ overflow: hidden;
43
+ z-index: 2;
44
+ font-weight: bolder;
45
+ background-color:white;
46
+ color:#1a1a1a;
47
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
48
+ }
49
+ #border{
50
+ position:absolute;
51
+ display: flex;
52
+ z-index: 0;
53
+ bottom: 5%;
54
+ right: 5%;
55
+ align-content: center;
56
+ justify-content: center;
57
+ border-radius: 20px;
58
+ width:105px;
59
+ height:45px;
60
+ background:linear-gradient(75deg,blue,red,greenyellow);
61
+ }
62
+ #boticon::before{
63
+ content:"";
64
+ position: absolute;
65
+ z-index:-1;
66
+ top:0;
67
+ left: -100%;
68
+ width:100px;
69
+ height:40px;
70
+ background:linear-gradient(75deg,blue,red,greenyellow);
71
+ transition: transform 1.5s ease;
72
+ transform: translateX(0);
73
+ }
74
+ #boticon:hover::before{
75
+ transform: translateX(100%);
76
+ }
77
+ #buy,#sell{
78
+ width:150px;
79
+ height:50px;
80
+ border-radius: 20px;
81
+ }
82
+ #buy{
83
+ background-color: rgb(21, 223, 21);
84
+ }
85
+ #sell{
86
+ background-color: red;
87
+ }
88
+ #buttons{
89
+ display: flex;
90
+ justify-content: space-around;
91
+ }
92
+ #menu{
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ margin-bottom: 20px;
97
+ }
98
+ #buysell{
99
+ display: flex;
100
+ flex-direction: column;
101
+ justify-content: space-around;
102
+ align-items: center;
103
+ height: 300px;
104
+ margin:50px;
105
+ background-color: rgba(70, 57, 96, 0.8);
106
+ border-radius: 20px;
107
+ box-shadow: 0 0 20px rgba(113, 78, 161, 0.6);
108
+ }
109
+ body{
110
+ background-color: rgba(57, 57, 96, 0.9);
111
+ }
112
+ a{
113
+ color:#66ccff;
114
+ }
115
+ a:hover{
116
+ color:#ffffff;
117
+ }
118
+ h2{
119
+ color:#c4b5fd;
120
+ text-align: center;
121
+ }
122
+ #description{
123
+ color:#f0f0f0;
124
+ }
125
+ #qty{
126
+ border:none;
127
+ background-color: inherit;
128
+ outline: none;
129
+ border-bottom: 2px solid black ;
130
+ }
131
+ #news{
132
+ border-radius: 10px;
133
+ box-shadow: 0 0 20px rgba(113, 78, 161, 0.5);
134
+ padding: 20px;
135
+ }
136
+ #news:hover{
137
+ box-shadow: 0 0 20px rgba(113, 64, 180, 0.8);
138
+ }
139
+ .livechart{
140
+ border-radius: 20px;
141
+ overflow: hidden;
142
+ margin:10px;
143
+ }
144
+ h3{
145
+ color:#f0f0f0;
146
+ }
147
+ #chatbot{
148
+ display: none;
149
+ flex-direction: column;
150
+ bottom:20%;
151
+ top:20%;
152
+ left:20%;
153
+ right:20%;
154
+ flex-direction: column;
155
+ justify-content: center;
156
+ align-items: center;
157
+ position:fixed;
158
+ border-radius: 20px;
159
+ background-color: black;
160
+ color:greenyellow;
161
+ box-shadow: 0 0 20px rgb(240, 185, 252);
162
+
163
+ }
164
+ #X{
165
+ position: absolute;
166
+ top:0px;
167
+ right:20px;
168
+ }
169
+ #X:hover{
170
+ border: 1px solid white;
171
+ }
172
+ #chatheading{
173
+ position: absolute;
174
+ top:30px;
175
+ }
176
+ #textbox{
177
+ position: absolute;
178
+ bottom: 10px;
179
+ left: 10px;
180
+ right:0px;
181
+ }
182
+ #inp{
183
+ width: 82%;
184
+ height: 30px;
185
+ border-radius: 20px;
186
+ padding: 7px;
187
+ font-size: xx-large;
188
+ }
189
+ #send{
190
+ border: 20px;
191
+ background-color: rgb(34, 191, 26);
192
+ border: 2px solid rgb(47, 166, 43);
193
+ color: black;
194
+ font-size: xx-large;
195
+ border-radius: 20px;
196
+ }
197
+ #send:active{
198
+ background-color: rgb(158, 255, 149);
199
+ }
200
+ .question,.response{
201
+ border-radius: 20px;
202
+ background-color: navy;
203
+ padding:20px;
204
+ display: inline-block;
205
+ }
206
+ .question{
207
+ align-self: flex-start;
208
+ }
209
+ .response{
210
+ align-self: flex-end;
211
+ }
212
+ #qapair{
213
+ display: flex;
214
+ flex-direction: column;
215
+ gap: 10px;
216
+ width: 100%;
217
+ padding: 20px;
218
+ overflow-y: auto;
219
+ max-height: 50%;
220
+ box-sizing: border-box;
221
+ }
222
+ </style>
223
+ <body>
224
+ <div class="bottom_page">
225
+ <div class="page">
226
+ <div class="tab1">
227
+ <h2>Live Price</h2>
228
+ <div class="livechart" id="stock_hourly_price">{{chart | safe}}</div>
229
+ <h2>20 Days Predicion</h2>
230
+ <div class="livechart" id="next20days">{{pred20 | safe}}</div>
231
+ <div class="portfolio">
232
+ <div id="buysell">
233
+ <h2>Buy Sell</h2>
234
+ <h3>Balance:{{amount}}</h3>
235
+ <h3>Coins:{{qty}}</h3>
236
+ <input type="text" id="qty" placeholder="Amount" style="margin-bottom:10px;color:white;">
237
+ <div id="buttons">
238
+ <button id="buy">Buy</button>
239
+ <button id="sell">Sell</button>
240
+ </div>
241
+ </div>
242
+ </div>
243
+ </div>
244
+ <div class="tab2">
245
+ <h2>News</h2>
246
+ {% for news in newsset %}
247
+ <div id="news">
248
+ <a href="{{newsset[news]['url']}}">{{newsset[news]['title']}}</a>
249
+ <div id="description">{{newsset[news]['snippet']}}</div>
250
+ </div>
251
+ {% endfor %}
252
+ </div>
253
+ </div>
254
+ <div id="border">
255
+ <button id="boticon">Chat AI </button>
256
+ </div>
257
+ </div>
258
+ <div id="chatbot">
259
+ <h2 id="X">X</h2>
260
+ <h1 id="chatheading">Hey Chat</h1>
261
+ <div id="qapair">
262
+ </div>
263
+ <div id="textbox">
264
+ <div>
265
+ <input type="radio" name="chattype" value="doc">Document
266
+ <input type="radio" name="chattype" value="news">Search
267
+ </div>
268
+ <input type="text" placeholder="Chat..." id="inp" autocomplete="off">
269
+ <button id="send" onclick="sendchat()">>>></button>
270
+ </div>
271
+ </div>
272
+
273
+ <script>
274
+ function fetchnew(){
275
+ fetch("/update_chart")
276
+ .then(res=>res.json())
277
+ .then(data=>{
278
+ Plotly,expandTraces("stock_hourly_price",{
279
+ x:[data.x[0],data.x[1],data.x[2]],
280
+ open:data.open[0],
281
+ high:data.high[0],
282
+ low:data.low[0],
283
+ close:data.close[0],
284
+ y:[data.y[0],data.y[1]]
285
+ }
286
+ ,{displayModeBar:false})
287
+ });
288
+ }
289
+ let icon=document.querySelector("#boticon")
290
+
291
+ let bottompage=document.querySelector(".bottom_page")
292
+
293
+ let bot=document.querySelector("#chatbot")
294
+
295
+ icon.addEventListener("click",()=>{
296
+ bottompage.style.opacity=0.2
297
+ chatbot.style.display="flex"
298
+ })
299
+
300
+ let cancel=document.querySelector("#X")
301
+
302
+ cancel.addEventListener("click",()=>{
303
+ bottompage.style.opacity=1
304
+ chatbot.style.display="none"
305
+ })
306
+ let inputfield=document.getElementById("inp")
307
+ let buton=document.getElementById("send")
308
+ buton.disabled=true;
309
+ buton.style.backgroundColor="grey"
310
+ inputfield.addEventListener('input',()=>{
311
+ if(inputfield.value.trim() !== ""){
312
+ buton.style.backgroundColor="rgb(34, 191, 26)"
313
+ buton.disabled=false
314
+ } else{
315
+ buton.style.backgroundColor="grey"
316
+ buton.disabled=true
317
+ }
318
+ })
319
+
320
+ function sendchat(){
321
+ let container=document.getElementById("qapair")
322
+ const qus=document.createElement("div")
323
+ const ans=document.createElement("div")
324
+ let text=inputfield.value
325
+ qus.className="question"
326
+ qus.innerHTML=text
327
+ container.appendChild(qus)
328
+ inputfield.value=""
329
+ fetch('/get_response',{
330
+ method:"POST",
331
+ headers: {
332
+ "Content-Type": "application/json"
333
+ },
334
+ body:JSON.stringify({text})
335
+ }).then(res=>res.json()).then(data=>{
336
+ ans.innerHTML=data.response
337
+ ans.className="response"
338
+ container.appendChild(ans)
339
+ })
340
+ }
341
+ setInterval(fetchnew,60*60*1000)
342
+ </script>
343
+ </body>
344
+ </html>