From 419ad7846ed90f9feffa2038ab474b147a67294b Mon Sep 17 00:00:00 2001 From: psyes9 Date: Tue, 12 Dec 2023 19:48:30 +0000 Subject: [PATCH] added daily graphing on click --- .../current_stock_holdings_day.cpython-38.pyc | Bin 0 -> 2156 bytes .../graph_stock_holdings_day.cpython-38.pyc | Bin 0 -> 1394 bytes backend/myapp/__pycache__/urls.cpython-38.pyc | Bin 713 -> 943 bytes backend/myapp/current_stock_holdings_day.py | 70 ++++++++++++++++++ backend/myapp/graph_stock_holdings_day.py | 35 +++++++++ backend/myapp/tester.py | 2 +- backend/myapp/urls.py | 4 + frontend/src/StockHoldings.js | 36 ++++++--- 8 files changed, 135 insertions(+), 12 deletions(-) create mode 100644 backend/myapp/__pycache__/current_stock_holdings_day.cpython-38.pyc create mode 100644 backend/myapp/__pycache__/graph_stock_holdings_day.cpython-38.pyc create mode 100644 backend/myapp/current_stock_holdings_day.py create mode 100644 backend/myapp/graph_stock_holdings_day.py diff --git a/backend/myapp/__pycache__/current_stock_holdings_day.cpython-38.pyc b/backend/myapp/__pycache__/current_stock_holdings_day.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2a32ca984db92e77c2543cfabaf60321b6fd295 GIT binary patch literal 2156 zcmai0&1)M+6rY)0?XEs8E0z++A?Q#_6pGbLC>y^%J{fVTBW0z4qw1Z&<1jDfjrX1p2X2G+Kf@i?%z9h#%o zE3}=bcpbIu6F3E}wy-LFnMC0lOX4U@7|fl73E_vk3Gn6|?Z|Pcq@A{OSBPe*VcfB(+j|^oMYc^3npU3bL?QNQ=^s#m< zoU;X8RApXAl3u0PULiV9uYYHx4Z4uUxRJ#-FJ@(atkHC1RhiTk?x^mEhb$2T7K)^! zC5wB2E`|B1yy1I&#+&QI!A=y6%B#_0GwL?idoE|msJg-3FmXNMM`3eg7_;3e-jFgL zY(BdLK?9ad=<6DSH-Y#_qUQ}rE>4MrK=(~fe8Hyel=I*+F*#4I7B)(wn9Tyx5 zX?rkq|mt|5rQa4{aL!V>j8;YEXZ`Gz)IUvEKk5P>Z1vJdJl z1(D|l$@1d4^2qvn^Zw_HkChWd;qIzCU@D*VA}%tv9CLQ)M+eEnAWE1jO>KI@eUF{! z_v3_WqJ!76lqIr^C^OW@6q76yogNFQDxZ22YgJV^bb|vnS!%>Q>iVJsHzb{yaSxn! zciHILBhDk<>@wl?bjWn_n_ZBM$lYd(@CIC}a!hZ!luezRvusvjBH?M9M@R6OP~(_D z{>;@Ay@_AfM04;k84xlU@Qd?A@-i$bXDM(8JJem)57gh#(dgFyhIgv6(IU#|v!Svf zi~tFC$skV<-fUH1IEFc;I1hr~h2Y~Afl=I;J`lHUu z7i-FlViqbhs~+O>MWswXgiz~RP&pnQgjD4pz3^D9%Sq)R ziJ?$NBDk^=zzU;WgQ0a*JGy@W^{OiRnoidbSSN-jUzwU!v*NreC*`c1Q)H{+g~dsB ztqFuw^}_97F zhrmdhMhzr2OmG2PMip0$0&W2B0KGvzG6}3W(4oDrI5j*+2)6#YnQPz*;X3`T0{<8W zRit}vxEn3@gov}GoJqVW>`owI>x=~cPKFZY47+~lh92X$;ehP03qEDf+O!Y`5j_al QvaXm!|FzKO>*kPu0gZ4zP5=M^ literal 0 HcmV?d00001 diff --git a/backend/myapp/__pycache__/graph_stock_holdings_day.cpython-38.pyc b/backend/myapp/__pycache__/graph_stock_holdings_day.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c88f964540ee653733647a68f944e1e61ce88bec GIT binary patch literal 1394 zcmZWp&2Jk;6rYdX^?Ku&gock)1#P8T$P%@oh)WekNECz+l!&wkRv>Ha8QbIRS7#;( zw$@x)2{=Roi6e*P*b8U=mbr4uzkn#=&AP5CF{^#^-h8}|-}~)8+}w;1j1T_&UVP;v z^p`VU9u$m^;MGGA9C4hY#LXnd8A%9sI!$TjC0?z2shB0nKWVc(5QEx-=7Fh=GR4Z3&0 z%(P2v$e9sFX2Ld|HT+!9cn>;$BOW*DB4c_9LXJi?e zW)(cfynTe!4|SwhAkx+bBu=CCBPIkM)E%`9(QtQJ}Wh@mrx1r39P$w)+$Q{^!p98uX@+5#t+4$#HT z10_ymajau-_>Pl?#d%?3cEV)JhN+OhK}hR=oEBPK{(E(GHF7DehwDH9?=^V!yC5d0 zLf_r`mMj7H3ZFw4E}#z_0ltLeUGx($?RWYsdE@~Obg{jzAnts2xAW!Q&Y{`?FI}o! zf2|Ms9}64R)1YLMLzR(P3`RwMBB0dJv1C!?0@!5K*jaFb^xks_8DXg^PM>1iE}xe< z7`Zy0qQ6=Hp%zN_g_*KkXVOgj_k=z&McMyCFqH!@PlG1StC{*Xb# za^BD8tStKz#mebGn__e{m=-B_bRGbdy>f1&y;N#5Dzb9_EeDVLE(0%k*2V!Q&la7D zFzcIeu2A#dURsP;s`o)z-~7}yTeGp~wv_9bCG)WjR;*cJMDyZQ?ZTFFjj)aB%9*T}*bpj%^Z~f2rqW8^Ub&Qz+n`i(By_U< z0#GQ{onrRoQ+2&@W*VK?}U<&&Z}HKtr4vR(mBjFls#ZItjgN##&^&I;#anX`N()GcRv<=iZ4 o=xV@L(76z+bmJFVopZRC75q3A`;PV6eK;W`=bjLrEgF&k04frN)&Kwi literal 0 HcmV?d00001 diff --git a/backend/myapp/__pycache__/urls.cpython-38.pyc b/backend/myapp/__pycache__/urls.cpython-38.pyc index f144b3c122dc46a5645f944bf357061117da2e51..a3dc8d1128d5063e1527288564f3dd8ae0476508 100644 GIT binary patch delta 458 zcmX@fx}IG-l$V!_0SNZ*s7TFYW?*;>;vfT%tOF1iFPW%qR?nKlk;@*%&d89$l){$7 znadT$1!lA7aOd(w@h~!^GNy2(GN*8+aP=|++1#nDDLha%Zz_8VAC%1xWD7vqf~j07 zLQuAFDo=_Ch@H+B#hW4;%%Cau666|9##<}}i6s*^$cu}mrn-PaO84EaWXQbGN!Pn zGN*8)aP~3-*<7itDcn#tPbzx~FOlCfy=7DkQ9 zJWPR%+>_&&3?{E<5|d{IS`#Inky%`lUzC{~52TW_<1_MeQZn<>i;LJM|6`JnVh5_Z o#a&vIQ;=9vl3J8kypo}a8z@%9J=uUcQA`NP 0} + + # Fetch live data for remaining stocks + live_data = {} + for ticker, shares in holdings.items(): + try: + stock = yf.Ticker(ticker) + stock_info = stock.info + + # Determine the correct fields based on the ticker + name_field = "longName" if ticker == "VUAG.L" else "shortName" + price_field = "previousClose" if ticker == "VUAG.L" else "currentPrice" + + # Fetch the relevant data + name = stock_info.get(name_field) + current_price = stock_info.get(price_field) or stock_info.get("previousClose") + average_cost = stock_info.get("previousClose") + total_investment = average_cost * shares + current_value = shares * current_price if current_price is not None else None + value_held = round((shares * current_price if current_price is not None else None),2) + + profit_loss_percentage = round((((current_value - total_investment) / total_investment * 100) if current_value is not None else None),2) + + + live_data[ticker] = { + "ticker": ticker, + "name": name, + "shares_held": round(shares,4), + "current_price": current_price, + "value_held": value_held, + "profit_loss_percentage": profit_loss_percentage + } + except Exception as e: + print(f"Error fetching data for {ticker}: {e}") + live_data[ticker] = { + "ticker": ticker, + "error": str(e) + } + + sorting_data = sorted(live_data.items(), key=lambda x: x[1].get('value_held', 0), reverse=True) + live_data = {k: v for k, v in sorting_data} + + return JsonResponse(live_data) \ No newline at end of file diff --git a/backend/myapp/graph_stock_holdings_day.py b/backend/myapp/graph_stock_holdings_day.py new file mode 100644 index 0000000..61b2a6a --- /dev/null +++ b/backend/myapp/graph_stock_holdings_day.py @@ -0,0 +1,35 @@ +import json +from django.http import JsonResponse +from django.conf import settings +from pathlib import Path +import yfinance as yf +import pytz +from datetime import datetime, timedelta + +# Your timezone, for example, 'UTC' +timezone = pytz.timezone('EST') + +def get_stock_history(request, ticker): + if not ticker: + return JsonResponse({"error": "Ticker symbol is required."}, status=400) + + stock = yf.Ticker(ticker) + # Fetch data for the last 24 hours with granular intervals (e.g., 5 minutes) + end_date = datetime.now(tz=timezone) + start_date = end_date - timedelta(days=1) + historical_prices = stock.history(start=start_date.strftime('%Y-%m-%d'), end=end_date.strftime('%Y-%m-%d'), interval="5m") + + # Fetch the previous day's closing price + previous_day_data = stock.history(period="2d", interval="1d") + if len(previous_day_data) < 2: + return JsonResponse({"error": "Previous day's data not available"}, status=404) + previous_close = previous_day_data['Close'].iloc[-2] + + # Convert data to the desired timezone and format for response + historical_values = [{ + "datetime": date.tz_convert(timezone).strftime('%Y-%m-%d %H:%M:%S'), + "value": row['Close'], + "value_paid": previous_close + } for date, row in historical_prices.iterrows()] + + return JsonResponse(historical_values, safe=False) diff --git a/backend/myapp/tester.py b/backend/myapp/tester.py index 066664f..4b778a1 100644 --- a/backend/myapp/tester.py +++ b/backend/myapp/tester.py @@ -1,4 +1,4 @@ import yfinance as yf -ticker = yf.Ticker("VUAG.L") +ticker = yf.Ticker("AAPL") print(ticker.info) \ No newline at end of file diff --git a/backend/myapp/urls.py b/backend/myapp/urls.py index 9a13706..165e33c 100644 --- a/backend/myapp/urls.py +++ b/backend/myapp/urls.py @@ -1,12 +1,16 @@ from django.urls import path from .current_stock_holdings import get_stock_holdings +from .current_stock_holdings_day import get_stock_holdings_day from .graph_stock_holdings import get_stock_history +from .graph_stock_holdings_day import get_stock_history from .historic_stock_holdings import get_historic_stock_holdings from .graph_all_holdings import get_portfolio_value urlpatterns = [ path('stock_holdings/', get_stock_holdings, name='stock_holdings'), + path('stock_holdings_day/', get_stock_holdings_day, name='stock_holdings_day'), path('graph_stock//', get_stock_history, name='graph_stock'), + path('graph_stock_day//', get_stock_history, name='graph_stock_day'), path('historic_holdings/', get_historic_stock_holdings, name='all_holdings'), path('graph_portfolio//', get_portfolio_value, name='graph_portfolio'), ] \ No newline at end of file diff --git a/frontend/src/StockHoldings.js b/frontend/src/StockHoldings.js index df8b092..2d3b149 100644 --- a/frontend/src/StockHoldings.js +++ b/frontend/src/StockHoldings.js @@ -6,16 +6,30 @@ function StockHoldings({ onStockSelect, timeFrame }) { // Function to fetch data from your API const fetchStockHoldings = async () => { - try { - const response = await fetch('http://localhost:8000/api/stock_holdings/'); - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + if (timeFrame === 'All') { + try { + const response = await fetch(`http://localhost:8000/api/stock_holdings/`); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + console.log(data); + setHoldings(Object.values(data)); + } catch (error) { + console.error('Fetching data failed:', error); + } + } else { + try { + const response = await fetch('http://localhost:8000/api/stock_holdings_day/'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + console.log(data); + setHoldings(Object.values(data)); + } catch (error) { + console.error('Fetching data failed:', error); } - const data = await response.json(); - console.log(data); // Check the structure of the fetched data - setHoldings(Object.values(data)); // Convert the object to an array and update state - } catch (error) { - console.error('Fetching data failed:', error); } }; @@ -30,7 +44,7 @@ function StockHoldings({ onStockSelect, timeFrame }) { fetchStockHoldings(); const interval = setInterval(fetchStockHoldings, 2000); return () => clearInterval(interval); - }, []); + }, [timeFrame]); // Function to load images const loadImage = async (ticker) => { @@ -70,7 +84,7 @@ function StockHoldings({ onStockSelect, timeFrame }) { fetchStockHoldings(); const interval = setInterval(fetchStockHoldings, 2000); return () => clearInterval(interval); - }, []); + }, [timeFrame]); return (