cryman38 commited on
Commit
84a6a31
·
verified ·
1 Parent(s): 1aba40d

Upload 18 files

Browse files
interface/dollar_cost_averaging_interface copy.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from modules.dollar_cost_averaging import dollar_cost_averaging
3
+
4
+ examples = [
5
+ [1000, 9000, 560, 20000]
6
+ ]
7
+ # Define the inputs
8
+ title = gr.Markdown("<h2 style='margin: 5px'>Dollar Cost Averaging Calculator</h2>")
9
+ first_purchase = gr.Markdown("<h3 class='h3_title'>FIRST PURCHASE</h3>")
10
+ old_price = gr.Number(label="Old Price", value=18150)
11
+ old_quantity = gr.Number(label="Quantity", value=95)
12
+ second_purchase = gr.Markdown("<h3 class='h3_title'>SECOND PURCHASE</h3>")
13
+ new_price = gr.Number(label="New Price", value=17705)
14
+ new_quantity = gr.Number(label="Quantity", value=0)
15
+
16
+ input = [old_price, old_quantity, new_price, new_quantity]
17
+ output = gr.HTML()
18
+ component_rows= [first_purchase, old_price, old_quantity, second_purchase, new_price, new_quantity]
19
+
20
+ # Define the update function
21
+ def update_output(*args):
22
+ return dollar_cost_averaging(*args)
interface/dollar_cost_averaging_interface.py CHANGED
@@ -2,20 +2,21 @@ import gradio as gr
2
  from modules.dollar_cost_averaging import dollar_cost_averaging
3
 
4
  examples = [
5
- [1000, 9000, 560, 20000]
6
  ]
 
7
  # Define the inputs
8
  title = gr.Markdown("<h2 style='margin: 5px'>Dollar Cost Averaging Calculator</h2>")
 
9
  first_purchase = gr.Markdown("<h3 class='h3_title'>FIRST PURCHASE</h3>")
10
  old_price = gr.Number(label="Old Price", value=18150)
11
  old_quantity = gr.Number(label="Quantity", value=95)
12
  second_purchase = gr.Markdown("<h3 class='h3_title'>SECOND PURCHASE</h3>")
13
- new_price = gr.Number(label="New Price", value=17705)
14
- new_quantity = gr.Number(label="Quantity", value=0)
15
 
16
- input = [old_price, old_quantity, new_price, new_quantity]
17
  output = gr.HTML()
18
- component_rows= [first_purchase, old_price, old_quantity, second_purchase, new_price, new_quantity]
19
 
20
  # Define the update function
21
  def update_output(*args):
 
2
  from modules.dollar_cost_averaging import dollar_cost_averaging
3
 
4
  examples = [
5
+ ["AAPL", 200, 9000, 560, 20000]
6
  ]
7
+
8
  # Define the inputs
9
  title = gr.Markdown("<h2 style='margin: 5px'>Dollar Cost Averaging Calculator</h2>")
10
+ stock_code = gr.Textbox(label="Stock Code", value="368590")
11
  first_purchase = gr.Markdown("<h3 class='h3_title'>FIRST PURCHASE</h3>")
12
  old_price = gr.Number(label="Old Price", value=18150)
13
  old_quantity = gr.Number(label="Quantity", value=95)
14
  second_purchase = gr.Markdown("<h3 class='h3_title'>SECOND PURCHASE</h3>")
15
+ new_quantity = gr.Slider(label="Quantity", value=0)
 
16
 
17
+ input = [stock_code, old_price, old_quantity, new_quantity]
18
  output = gr.HTML()
19
+ component_rows = [stock_code, first_purchase, old_price, old_quantity, second_purchase, new_quantity]
20
 
21
  # Define the update function
22
  def update_output(*args):
interface/retirement_planning_interface.py CHANGED
@@ -9,14 +9,14 @@ examples = [
9
  # Define the input components
10
  title = gr.Markdown("<h2 style='margin: 5px'>Retirement Planning</h2>")
11
  title_profile = gr.Markdown("<h3 class='h3_title'>PROFILE</h3>")
12
- current_age = gr.Slider(label="Current Age (15-60 Years)", value=28, minimum=15, maximum=60, step=1)
13
  retirement_age = gr.Slider(label="Retirement Age (Upto 70 Years)", value=55, minimum=15, maximum=70, step=1)
14
  life_expectancy = gr.Slider(label="Life Expectancy (Upto 100 Years)", value=80, minimum=30, maximum=100, step=1)
15
  title_savings = gr.Markdown("<h3 class='h3_title'>SAVINGS</h3>")
16
  monthly_income_required = gr.Number(label="Monthly Income Required (CPP)", value=2000000)
17
  inflation_rate = gr.Number(label="Inflation Rate (%)", value=3)
18
  current_investment = gr.Number(label="Current Investment", value=10000000)
19
- monthly_investment = gr.Number(label="Monthly Investment", value=500000)
20
  annual_increase_in_monthly_investment = gr.Number(label="Annual Increase in Monthly Investment", value=0) # 추가된 입력
21
  reinvest_dividends = gr.Checkbox(label="Reinvest Dividends", value=True)
22
  title_growth = gr.Markdown("<h3 class='h3_title'>GROWTH</h3>")
 
9
  # Define the input components
10
  title = gr.Markdown("<h2 style='margin: 5px'>Retirement Planning</h2>")
11
  title_profile = gr.Markdown("<h3 class='h3_title'>PROFILE</h3>")
12
+ current_age = gr.Slider(label="Current Age (15-60 Years)", value=38, minimum=15, maximum=60, step=1)
13
  retirement_age = gr.Slider(label="Retirement Age (Upto 70 Years)", value=55, minimum=15, maximum=70, step=1)
14
  life_expectancy = gr.Slider(label="Life Expectancy (Upto 100 Years)", value=80, minimum=30, maximum=100, step=1)
15
  title_savings = gr.Markdown("<h3 class='h3_title'>SAVINGS</h3>")
16
  monthly_income_required = gr.Number(label="Monthly Income Required (CPP)", value=2000000)
17
  inflation_rate = gr.Number(label="Inflation Rate (%)", value=3)
18
  current_investment = gr.Number(label="Current Investment", value=10000000)
19
+ monthly_investment = gr.Number(label="Monthly Investment", value=1000000)
20
  annual_increase_in_monthly_investment = gr.Number(label="Annual Increase in Monthly Investment", value=0) # 추가된 입력
21
  reinvest_dividends = gr.Checkbox(label="Reinvest Dividends", value=True)
22
  title_growth = gr.Markdown("<h3 class='h3_title'>GROWTH</h3>")
interface/share_price_trend_interface.py CHANGED
@@ -1,5 +1,5 @@
1
  import gradio as gr
2
- from modules.share_price_trend import share_price_trend
3
 
4
  examples = [
5
  ["AAPL,GOOGL,MSFT", 90],
@@ -17,14 +17,14 @@ stock_codes = gr.Textbox(
17
  period = gr.Slider(
18
  label="Number of Days",
19
  value=90,
20
- maximum=3650
21
  )
22
 
23
  # Define output component
24
  input = [stock_codes, period]
25
- output = gr.HTML()
26
  component_rows = [[stock_codes], [period]]
27
 
28
  # Define the update function
29
  def update_output(*args):
30
- return share_price_trend(*args)
 
1
  import gradio as gr
2
+ from modules.share_price_trend import share_price_trend, gradio_interface
3
 
4
  examples = [
5
  ["AAPL,GOOGL,MSFT", 90],
 
17
  period = gr.Slider(
18
  label="Number of Days",
19
  value=90,
20
+ minimum=7
21
  )
22
 
23
  # Define output component
24
  input = [stock_codes, period]
25
+ output = gr.Plot()
26
  component_rows = [[stock_codes], [period]]
27
 
28
  # Define the update function
29
  def update_output(*args):
30
+ return gradio_interface(*args)
modules/dollar_cost_averaging copy.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from modules.utils import load_css
2
+
3
+ def calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
4
+ # 입력값을 숫자로 변환 (각 입력값이 None일 경우 0.0으로 설정)
5
+ old_avg_price = float(old_avg_price) if old_avg_price else 0.0
6
+ old_quantity = float(old_quantity) if old_quantity else 0.0
7
+ new_price = float(new_price) if new_price else 0.0
8
+ new_quantity = float(new_quantity) if new_quantity else 0.0
9
+
10
+ # 현재 투자 금액 계산 (이전 평균 가격 * 이전 수량)
11
+ current_investment = old_avg_price * old_quantity
12
+ # 추가 투자 금액 계산 (새 가격 * 새 수량)
13
+ additional_investment = new_price * new_quantity
14
+ # 총 투자 금액 계산 (현재 투자 금액 + 추가 투자 금액)
15
+ total_investment = current_investment + additional_investment
16
+ # 총 주식 수 계산 (이전 수량 + 새 수량)
17
+ total_quantity = old_quantity + new_quantity
18
+ # 새 평균 가격 계산 (총 투자 금액 / 총 주식 수)
19
+ new_avg_price = total_investment / total_quantity if total_quantity != 0 else 0.0
20
+ # 이전 수익률 계산 (이전 평균 가격을 기준으로)
21
+ old_return = (new_price / old_avg_price - 1) * 100 if old_avg_price != 0 else 0.0
22
+ # 새로운 수익률 계산 (새 가격 / 새 평균 가격 - 1) * 100
23
+ new_return = (new_price / new_avg_price - 1) * 100 if new_avg_price != 0 else 0.0
24
+
25
+ # 새 평균 가격, 총 수량, 총 투자 금액, 새로운 수익률, 추가 투자 금액, 이전 수익률 반환
26
+ return new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return
27
+
28
+ def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
29
+ css = load_css()
30
+
31
+ # 입력값을 숫자로 변환
32
+ old_avg_price = float(old_avg_price) if old_avg_price else 0.0
33
+ old_quantity = float(old_quantity) if old_quantity else 0.0
34
+ new_price = float(new_price) if new_price else 0.0
35
+ new_quantity = float(new_quantity) if new_quantity else 0.0
36
+
37
+ # 평균 가격, 총 수량, 총 투자 금액, 수익률 및 추가 투자 금액 계산
38
+ new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return = calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity)
39
+
40
+ # 수익률에 따른 클래스 설정
41
+ emoji_return = ""
42
+ new_return_class = ""
43
+ old_return_class = ""
44
+ if new_return > old_return:
45
+ emoji_return = "💧"
46
+ elif new_return < old_return:
47
+ emoji_return = "🔥"
48
+ else:
49
+ emoji_return = ""
50
+
51
+ if new_return > 0:
52
+ new_return_class = f"<span style='color: #4caf50;'>{new_return:+,.2f}%</span>"
53
+ elif new_return < 0:
54
+ new_return_class = f"<span style='color: #f44336;'>{new_return:,.2f}%</span>"
55
+ else:
56
+ new_return_class = f"<span><strong>0</strong></span>"
57
+
58
+ if old_return > 0:
59
+ old_return_class = f"<span style='color: #4caf50;'>{old_return:+,.2f}%</span>"
60
+ elif old_return < 0:
61
+ old_return_class = f"<span style='color: #f44336;'>{old_return:,.2f}%</span>"
62
+ else:
63
+ old_return_class = f"<span><strong>0</strong></span>"
64
+
65
+ # HTML 결과 생성
66
+ result_html = css + f"""
67
+ <div class="wrap-text">
68
+ <div>
69
+ <div style="margin-bottom: 1.5rem;">
70
+ <!-- 이전 수익률 표시 -->
71
+ <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Old Price</div>
72
+ <div style="font-size: 1.5rem; color: #1c75bc;">
73
+ <span style='color: #1678fb; font-weight: bold;'>{old_avg_price:,.0f}</span>
74
+ <span style='font-size: 1rem;'>{old_return_class}</span>
75
+ </div>
76
+ <hr style="margin: 1.5rem 0;">
77
+ </div>
78
+ </div>
79
+ <div>
80
+ <div style="margin-bottom: 1.5rem;">
81
+ <!-- 새로운 수익률 표시 -->
82
+ <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Average Price</div>
83
+ <div style="font-size: 1.5rem; color: #1c75bc;">
84
+ <span style='color: #1678fb; font-weight: bold;'>{new_avg_price:,.0f}</span>
85
+ <span style='font-size: 1rem;'>{new_return_class}</span>
86
+ </div>
87
+ <hr style="margin: 1.5rem 0;">
88
+ </div>
89
+ </div>
90
+ <div>
91
+ <div style="margin-bottom: 1.5rem;">
92
+ <!-- 추가 투자 금액 표시 -->
93
+ <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Additional Investment</div>
94
+ <div style="font-size: 1.5rem; font-weight: bold; color: #1c75bc;">
95
+ <span style='color: #1678fb'>{additional_investment:,.0f}</span>
96
+ </div>
97
+ <hr style="margin: 1.5rem 0;">
98
+ </div>
99
+ </div>
100
+
101
+ </div>
102
+ """
103
+ return result_html
modules/dollar_cost_averaging.py CHANGED
@@ -1,43 +1,47 @@
 
 
1
  from modules.utils import load_css
2
 
 
 
 
 
 
 
 
 
3
  def calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
4
- # 입력값을 숫자로 변환 (각 입력값이 None일 경우 0.0으로 설정)
5
  old_avg_price = float(old_avg_price) if old_avg_price else 0.0
6
  old_quantity = float(old_quantity) if old_quantity else 0.0
7
  new_price = float(new_price) if new_price else 0.0
8
  new_quantity = float(new_quantity) if new_quantity else 0.0
9
 
10
- # 현재 투자 금액 계산 (이전 평균 가격 * 이전 수량)
 
 
11
  current_investment = old_avg_price * old_quantity
12
- # 추가 투자 금액 계산 (새 가격 * 새 수량)
13
  additional_investment = new_price * new_quantity
14
- # 총 투자 금액 계산 (현재 투자 금액 + 추가 투자 금액)
15
  total_investment = current_investment + additional_investment
16
- # 총 주식 수 계산 (이전 수량 + 새 수량)
17
  total_quantity = old_quantity + new_quantity
18
- # 새 평균 가격 계산 (총 투자 금액 / 총 주식 수)
19
  new_avg_price = total_investment / total_quantity if total_quantity != 0 else 0.0
20
- # 이전 수익률 계산 (이전 평균 가격을 기준으로)
21
  old_return = (new_price / old_avg_price - 1) * 100 if old_avg_price != 0 else 0.0
22
- # 새로운 수익률 계산 (새 가격 / 새 평균 가격 - 1) * 100
23
  new_return = (new_price / new_avg_price - 1) * 100 if new_avg_price != 0 else 0.0
24
-
25
- # 새 평균 가격, 총 수량, 총 투자 금액, 새로운 수익률, 추가 투자 금액, 이전 수익률 반환
26
  return new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return
27
 
28
- def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
29
  css = load_css()
30
-
31
- # 입력값을 숫자로 변환
 
 
 
32
  old_avg_price = float(old_avg_price) if old_avg_price else 0.0
33
  old_quantity = float(old_quantity) if old_quantity else 0.0
34
- new_price = float(new_price) if new_price else 0.0
35
  new_quantity = float(new_quantity) if new_quantity else 0.0
36
 
37
- # 평균 가격, 총 수량, 총 투자 금액, 수익률 및 추가 투자 금액 계산
38
  new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return = calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity)
39
 
40
- # 수익률에 따른 클래스 설정
41
  emoji_return = ""
42
  new_return_class = ""
43
  old_return_class = ""
@@ -45,7 +49,7 @@ def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
45
  emoji_return = "💧"
46
  elif new_return < old_return:
47
  emoji_return = "🔥"
48
- else:
49
  emoji_return = ""
50
 
51
  if new_return > 0:
@@ -62,12 +66,19 @@ def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
62
  else:
63
  old_return_class = f"<span><strong>0</strong></span>"
64
 
65
- # HTML 결과 생성
66
  result_html = css + f"""
67
  <div class="wrap-text">
68
  <div>
69
  <div style="margin-bottom: 1.5rem;">
70
- <!-- 이전 수익률 표시 -->
 
 
 
 
 
 
 
 
71
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Old Price</div>
72
  <div style="font-size: 1.5rem; color: #1c75bc;">
73
  <span style='color: #1678fb; font-weight: bold;'>{old_avg_price:,.0f}</span>
@@ -75,10 +86,9 @@ def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
75
  </div>
76
  <hr style="margin: 1.5rem 0;">
77
  </div>
78
- </div>
79
- <div>
80
  <div style="margin-bottom: 1.5rem;">
81
- <!-- 새로운 수익률 표시 -->
82
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Average Price</div>
83
  <div style="font-size: 1.5rem; color: #1c75bc;">
84
  <span style='color: #1678fb; font-weight: bold;'>{new_avg_price:,.0f}</span>
@@ -89,7 +99,6 @@ def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
89
  </div>
90
  <div>
91
  <div style="margin-bottom: 1.5rem;">
92
- <!-- 추가 투자 금액 표시 -->
93
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Additional Investment</div>
94
  <div style="font-size: 1.5rem; font-weight: bold; color: #1c75bc;">
95
  <span style='color: #1678fb'>{additional_investment:,.0f}</span>
@@ -97,7 +106,6 @@ def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
97
  <hr style="margin: 1.5rem 0;">
98
  </div>
99
  </div>
100
-
101
  </div>
102
  """
103
  return result_html
 
1
+ import yfinance as yf
2
+ import FinanceDataReader as fdr
3
  from modules.utils import load_css
4
 
5
+ def get_stock_price(stock_code):
6
+ try:
7
+ df = fdr.DataReader(stock_code)
8
+ return df['Close'].iloc[-1]
9
+ except Exception as e:
10
+ # 에러 발생 시 0.0으로 설정하고, 오류 메시지를 반환
11
+ return None
12
+
13
  def calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
 
14
  old_avg_price = float(old_avg_price) if old_avg_price else 0.0
15
  old_quantity = float(old_quantity) if old_quantity else 0.0
16
  new_price = float(new_price) if new_price else 0.0
17
  new_quantity = float(new_quantity) if new_quantity else 0.0
18
 
19
+ if old_quantity == 0 and new_quantity == 0:
20
+ return 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
21
+
22
  current_investment = old_avg_price * old_quantity
 
23
  additional_investment = new_price * new_quantity
 
24
  total_investment = current_investment + additional_investment
 
25
  total_quantity = old_quantity + new_quantity
 
26
  new_avg_price = total_investment / total_quantity if total_quantity != 0 else 0.0
 
27
  old_return = (new_price / old_avg_price - 1) * 100 if old_avg_price != 0 else 0.0
 
28
  new_return = (new_price / new_avg_price - 1) * 100 if new_avg_price != 0 else 0.0
29
+
 
30
  return new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return
31
 
32
+ def dollar_cost_averaging(stock_code, old_avg_price, old_quantity, new_quantity):
33
  css = load_css()
34
+
35
+ # 주식 가격 가져오기
36
+ new_price = get_stock_price(stock_code)
37
+
38
+ new_price = float(new_price) if new_price else 0.0
39
  old_avg_price = float(old_avg_price) if old_avg_price else 0.0
40
  old_quantity = float(old_quantity) if old_quantity else 0.0
 
41
  new_quantity = float(new_quantity) if new_quantity else 0.0
42
 
 
43
  new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return = calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity)
44
 
 
45
  emoji_return = ""
46
  new_return_class = ""
47
  old_return_class = ""
 
49
  emoji_return = "💧"
50
  elif new_return < old_return:
51
  emoji_return = "🔥"
52
+ else:
53
  emoji_return = ""
54
 
55
  if new_return > 0:
 
66
  else:
67
  old_return_class = f"<span><strong>0</strong></span>"
68
 
 
69
  result_html = css + f"""
70
  <div class="wrap-text">
71
  <div>
72
  <div style="margin-bottom: 1.5rem;">
73
+ <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">New Price</div>
74
+ <div style="font-size: 1.5rem; color: #1c75bc;">
75
+ <span style='color: #1678fb; font-weight: bold;'>{new_price:,}</span>
76
+ </div>
77
+ <hr style="margin: 1.5rem 0;">
78
+ </div>
79
+ </div>
80
+ <div>
81
+ <div style="margin-bottom: 1.5rem;">
82
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Old Price</div>
83
  <div style="font-size: 1.5rem; color: #1c75bc;">
84
  <span style='color: #1678fb; font-weight: bold;'>{old_avg_price:,.0f}</span>
 
86
  </div>
87
  <hr style="margin: 1.5rem 0;">
88
  </div>
89
+ </div>
90
+ <div>
91
  <div style="margin-bottom: 1.5rem;">
 
92
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Average Price</div>
93
  <div style="font-size: 1.5rem; color: #1c75bc;">
94
  <span style='color: #1678fb; font-weight: bold;'>{new_avg_price:,.0f}</span>
 
99
  </div>
100
  <div>
101
  <div style="margin-bottom: 1.5rem;">
 
102
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Additional Investment</div>
103
  <div style="font-size: 1.5rem; font-weight: bold; color: #1c75bc;">
104
  <span style='color: #1678fb'>{additional_investment:,.0f}</span>
 
106
  <hr style="margin: 1.5rem 0;">
107
  </div>
108
  </div>
 
109
  </div>
110
  """
111
  return result_html
modules/rebalancing.py CHANGED
@@ -261,6 +261,6 @@ def rebalancing_tool(main_currency, holdings, cash_amount, allow_selling):
261
  portfolio_info = generate_portfolio_info(portfolio, total_value, main_currency)
262
  rebalancing_analysis = generate_rebalancing_analysis(portfolio, target_ratios, total_value, main_currency, cash_amount, allow_selling)
263
 
264
- return portfolio_info + rebalancing_analysis
265
  except Exception as e:
266
  return f"<p style='color: red;'>An error occurred: {e}</p>"
 
261
  portfolio_info = generate_portfolio_info(portfolio, total_value, main_currency)
262
  rebalancing_analysis = generate_rebalancing_analysis(portfolio, target_ratios, total_value, main_currency, cash_amount, allow_selling)
263
 
264
+ return rebalancing_analysis
265
  except Exception as e:
266
  return f"<p style='color: red;'>An error occurred: {e}</p>"
modules/share_price_trend.py CHANGED
@@ -1,7 +1,8 @@
1
  import io
2
- import matplotlib.pyplot as plt
3
- import FinanceDataReader as fdr
4
  import pandas as pd
 
 
 
5
  from concurrent.futures import ThreadPoolExecutor, as_completed
6
 
7
  def get_stock_prices(stock_code, days):
@@ -32,97 +33,35 @@ def share_price_trend(stock_codes, days):
32
  print(f"<p style='color: red;'>Failed to fetch data for {stock_code}: {e}</p>")
33
 
34
  if not stock_prices:
35
- return "<p style='color: red;'>No data available for the provided stock codes.</p>"
36
 
37
- plt.switch_backend('agg')
38
- plt.style.use('tableau-colorblind10')
39
 
40
- fig, ax = plt.subplots(figsize=(8, 4.5))
41
  for stock_code, prices in stock_prices.items():
42
  relative_prices = prices / prices.iloc[0]
43
- ax.plot(prices.index, relative_prices, label=stock_code.upper())
 
 
 
 
 
 
 
44
 
45
- # Remove the axes and ticks
46
- ax.spines['top'].set_visible(False)
47
- ax.spines['right'].set_visible(False)
48
- ax.spines['left'].set_visible(False)
49
- ax.spines['bottom'].set_visible(False)
50
-
51
- ax.xaxis.set_visible(False)
52
- ax.yaxis.set_visible(False)
 
 
 
53
 
54
- # Add grid for better readability
55
- ax.grid(True, which='both', linestyle='--', linewidth=0.5)
56
-
57
- ax.legend()
58
- plt.tight_layout()
59
-
60
- svg_graph = io.StringIO()
61
- plt.savefig(svg_graph, format='svg')
62
- svg_graph.seek(0)
63
- svg_data = svg_graph.getvalue()
64
- plt.close()
65
-
66
- svg_data = svg_data.replace('<svg ', '<svg width="100%" height="100%" ')
67
- svg_data = svg_data.replace('</svg>', '''
68
- <defs>
69
- <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
70
- <stop offset="0%" style="stop-color:rgb(173,216,230);stop-opacity:1" />
71
- <stop offset="100%" style="stop-color:rgb(0,191,255);stop-opacity:1" />
72
- </linearGradient>
73
- <filter id="dropshadow" height="130%">
74
- <feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
75
- <feOffset dx="2" dy="2" result="offsetblur"/>
76
- <feMerge>
77
- <feMergeNode/>
78
- <feMergeNode in="SourceGraphic"/>
79
- </feMerge>
80
- </filter>
81
- </defs>
82
- <style>
83
- @keyframes lineAnimation {
84
- from {
85
- stroke-dasharray: 0, 1000;
86
- }
87
- to {
88
- stroke-dasharray: 1000, 0;
89
- }
90
- }
91
- path {
92
- animation: lineAnimation 1s linear forwards;
93
- }
94
- </style>
95
- </svg>''')
96
-
97
- svg_data = svg_data.replace('stroke="#1f77b4"', 'stroke="url(#grad1)" filter="url(#dropshadow)"')
98
-
99
- html_table = "<h3>Stock Prices Data</h3><div class='table-container'><table>"
100
- html_table += "<thead><tr><th>Date</th>"
101
- for stock_code in stock_prices.keys():
102
- html_table += f"<th>{stock_code.upper()}</th>"
103
- html_table += "</tr></thead><tbody>"
104
-
105
- # Create a date range with only business days
106
- all_dates = pd.date_range(start=min(df.index.min() for df in stock_prices.values()), end=pd.to_datetime('today'), freq='B')
107
- all_dates = all_dates[::-1] # Reverse the order of dates
108
-
109
- for date in all_dates:
110
- html_table += f"<tr><td>{date.strftime('%Y-%m-%d')}</td>"
111
- for stock_code in stock_prices.keys():
112
- price = stock_prices[stock_code].get(date, None)
113
- if price is not None:
114
- html_table += f"<td>{price:,.2f}</td>"
115
- else:
116
- html_table += "<td>N/A</td>"
117
- html_table += "</tr>"
118
-
119
- html_table += "</tbody></table></div>"
120
-
121
- graph_html = f'<h3>Relative Stock Prices Over the Last {days} Days</h3>{svg_data}'
122
- return graph_html + html_table
123
 
124
- # Example usage
125
- # stock_codes = "AAPL,MSFT,GOOGL"
126
- # days = 30
127
- # result = share_price_trend(stock_codes, days)
128
- # print(result)
 
1
  import io
 
 
2
  import pandas as pd
3
+ import FinanceDataReader as fdr
4
+ import plotly.graph_objects as go
5
+ import gradio as gr
6
  from concurrent.futures import ThreadPoolExecutor, as_completed
7
 
8
  def get_stock_prices(stock_code, days):
 
33
  print(f"<p style='color: red;'>Failed to fetch data for {stock_code}: {e}</p>")
34
 
35
  if not stock_prices:
36
+ return "No data available for the provided stock codes."
37
 
38
+ fig = go.Figure()
 
39
 
 
40
  for stock_code, prices in stock_prices.items():
41
  relative_prices = prices / prices.iloc[0]
42
+ fig.add_trace(go.Scatter(
43
+ x=relative_prices.index,
44
+ y=relative_prices,
45
+ mode='lines',
46
+ name=stock_code.upper(),
47
+ hoverinfo='text',
48
+ hovertext=[f'{stock_code.upper()}: {date.strftime("%Y-%m-%d")}: {price:.2f}' for date, price in zip(prices.index, prices)]
49
+ ))
50
 
51
+ fig.update_layout(
52
+ title=f'Relative Stock Prices Over the Last {days} Days',
53
+ xaxis_title='Date',
54
+ yaxis_title='Relative Price',
55
+ showlegend=True,
56
+ xaxis=dict(showline=False, showgrid=False),
57
+ yaxis=dict(showline=False, showgrid=False),
58
+ hovermode='x',
59
+ margin=dict(l=0, r=0, t=0, b=0), # Adjust margins to ensure the plot fits well
60
+ autosize=True
61
+ )
62
 
63
+ return fig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ def gradio_interface(stock_codes, days):
66
+ fig = share_price_trend(stock_codes, days)
67
+ return gr.Plot(fig)