cryman38 commited on
Commit
883500e
·
verified ·
1 Parent(s): abb433d

Upload 16 files

Browse files
app.py CHANGED
@@ -1,186 +1,69 @@
1
  import gradio as gr
2
  from interface.rebalancing_interface import (
3
- main_currency, holdings, cash_amount, cash_ratio,
4
  input as rebalancing_inputs,
5
  output as rebalancing_output,
 
6
  examples as rebalancing_examples,
7
- update_output as rebalancing_update_output
8
  )
9
  from interface.share_price_trend_interface import (
10
- stock_codes, period,
11
  input as share_price_trend_inputs,
12
  output as share_price_trend_output,
 
13
  examples as share_price_trend_examples,
14
- update_output as share_price_trend_update_output
15
  )
16
  from interface.dollar_cost_averaging_interface import (
17
- old_price, old_quantity, new_price, new_quantity,
18
  input as dollar_cost_averaging_inputs,
19
  output as dollar_cost_averaging_output,
20
- examples as dollar_cost_averaging_examples,
21
- update_output as dollar_cost_averaging_update_output
 
22
  )
23
  from interface.retirement_planning_interface import (
24
- current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, current_investment, monthly_investment, annual_increase_in_monthly_investment, reinvest_dividends, pre_retirement_roi, pre_retirement_dividend_yield, post_retirement_roi, post_retirement_dividend_yield,
25
  input as retirement_planning_inputs,
26
- output as retirement_output,
 
27
  examples as retirement_planning_examples,
28
- update_output as retirement_update_output
29
  )
30
  from interface.about_interface import render_about_tab
31
- from modules.utils import clear_buttons, submit_buttons
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  with gr.Blocks(css='style.css') as demo:
34
  with gr.Column(elem_id="col-container"):
35
  with gr.Tabs():
36
- with gr.TabItem("RE-BALANCING"):
37
- with gr.Row():
38
- with gr.Column():
39
- with gr.Row():
40
- main_currency.render()
41
-
42
- with gr.Row():
43
- holdings.render()
44
- with gr.Row():
45
- cash_amount.render()
46
- cash_ratio.render()
47
-
48
- # Add buttons and handlers
49
- clear_button = clear_buttons(
50
- rebalancing_inputs,
51
- rebalancing_update_output,
52
- rebalancing_output
53
- )
54
- submit_button = submit_buttons(
55
- rebalancing_inputs,
56
- rebalancing_update_output,
57
- rebalancing_output
58
- )
59
- gr.Examples(
60
- examples=rebalancing_examples,
61
- cache_examples=False,
62
- inputs=rebalancing_inputs
63
- )
64
- with gr.Column():
65
- rebalancing_output.render()
66
-
67
- # for input_component in rebalancing_inputs:
68
- # input_component.change(
69
- # fn=rebalancing_update_output,
70
- # inputs=rebalancing_inputs,
71
- # outputs=rebalancing_output
72
- # )
73
-
74
- with gr.TabItem("SHARE PRICE TREND"):
75
- with gr.Row():
76
- with gr.Column():
77
- with gr.Row():
78
- stock_codes.render()
79
- with gr.Row():
80
- period.render()
81
-
82
- # Add buttons and handlers
83
- submit_button = submit_buttons(
84
- share_price_trend_inputs,
85
- share_price_trend_update_output,
86
- share_price_trend_output
87
- )
88
- gr.Examples(
89
- examples=share_price_trend_examples,
90
- cache_examples=False,
91
- inputs=share_price_trend_inputs
92
- )
93
- with gr.Column():
94
- share_price_trend_output.render()
95
-
96
- # for input_component in share_price_trend_inputs:
97
- # input_component.change(
98
- # fn=share_price_trend_update_output,
99
- # inputs=share_price_trend_inputs,
100
- # outputs=share_price_trend_output
101
- # )
102
-
103
- with gr.TabItem("DOLLAR-COST AVERAGING"):
104
- with gr.Row():
105
- with gr.Column():
106
- # gr.Markdown("FIRST PURCHASE")
107
- with gr.Row():
108
- old_price.render()
109
- old_quantity.render()
110
- # with gr.Accordion("SECOND PURCHASE", open=True):
111
- with gr.Row():
112
- new_price.render()
113
- new_quantity.render()
114
-
115
- # Add buttons and handlers
116
- # submit_button = submit_buttons(
117
- # dollar_cost_averaging_inputs,
118
- # dollar_cost_averaging_update_output,
119
- # dollar_cost_averaging_output
120
- # )
121
- gr.Examples(
122
- examples=dollar_cost_averaging_examples,
123
- cache_examples=False,
124
- inputs=dollar_cost_averaging_inputs
125
- )
126
- with gr.Column():
127
- dollar_cost_averaging_output.render()
128
-
129
- for input_component in dollar_cost_averaging_inputs:
130
- input_component.change(
131
- fn=dollar_cost_averaging_update_output,
132
- inputs=dollar_cost_averaging_inputs,
133
- outputs=dollar_cost_averaging_output
134
- )
135
-
136
- with gr.TabItem("RETIREMENT PLANNING"):
137
- with gr.Row():
138
- with gr.Column():
139
- with gr.Accordion("PROFILE", open=True):
140
- with gr.Row():
141
- current_age.render()
142
- retirement_age.render()
143
- life_expectancy.render()
144
- with gr.Row():
145
- monthly_income_required.render()
146
- inflation_rate.render()
147
-
148
- with gr.Accordion("SAVINGS", open=True):
149
- with gr.Row():
150
- current_investment.render()
151
- monthly_investment.render()
152
- annual_increase_in_monthly_investment.render()
153
- reinvest_dividends.render()
154
-
155
- with gr.Accordion("GROWTH", open=True):
156
- with gr.Row():
157
- pre_retirement_roi.render()
158
- pre_retirement_dividend_yield.render()
159
- with gr.Row():
160
- post_retirement_roi.render()
161
- post_retirement_dividend_yield.render()
162
-
163
- # Add buttons and handlers
164
- # submit_button = submit_buttons(
165
- # retirement_planning_inputs,
166
- # retirement_update_output,
167
- # retirement_output
168
- # )
169
- gr.Examples(
170
- examples=retirement_planning_examples,
171
- cache_examples=False,
172
- inputs=retirement_planning_inputs
173
- )
174
- with gr.Column():
175
- retirement_output.render()
176
-
177
- for input_component in retirement_planning_inputs:
178
- input_component.change(
179
- fn=retirement_update_output,
180
- inputs=retirement_planning_inputs,
181
- outputs=retirement_output
182
- )
183
-
184
  render_about_tab()
185
 
 
 
 
 
 
 
 
 
 
 
186
  demo.launch(share=True)
 
1
  import gradio as gr
2
  from interface.rebalancing_interface import (
 
3
  input as rebalancing_inputs,
4
  output as rebalancing_output,
5
+ update_output as rebalancing_update_output,
6
  examples as rebalancing_examples,
7
+ component_rows as rebalancing_component_rows
8
  )
9
  from interface.share_price_trend_interface import (
 
10
  input as share_price_trend_inputs,
11
  output as share_price_trend_output,
12
+ update_output as share_price_trend_update_output,
13
  examples as share_price_trend_examples,
14
+ component_rows as share_price_trend_component_rows
15
  )
16
  from interface.dollar_cost_averaging_interface import (
 
17
  input as dollar_cost_averaging_inputs,
18
  output as dollar_cost_averaging_output,
19
+ update_output as dollar_cost_averaging_update_output,
20
+ examples as dollar_cost_averaging_examples,
21
+ component_rows as dollar_cost_averaging_component_rows
22
  )
23
  from interface.retirement_planning_interface import (
 
24
  input as retirement_planning_inputs,
25
+ output as retirement_planning_output,
26
+ update_output as retirement_update_output,
27
  examples as retirement_planning_examples,
28
+ component_rows as retirement_planning_component_rows,
29
  )
30
  from interface.about_interface import render_about_tab
31
+ from modules.utils import create_tab
32
+
33
+ tabs_configuration = [
34
+ ("RE-BALANCING", rebalancing_inputs, rebalancing_output, rebalancing_update_output, rebalancing_examples, rebalancing_component_rows),
35
+ ("SHARE PRICE TREND", share_price_trend_inputs, share_price_trend_output, share_price_trend_update_output, share_price_trend_examples, share_price_trend_component_rows),
36
+ ("DOLLAR-COST AVERAGING", dollar_cost_averaging_inputs, dollar_cost_averaging_output, dollar_cost_averaging_update_output, dollar_cost_averaging_examples, dollar_cost_averaging_component_rows),
37
+ ("RETIREMENT PLANNING", retirement_planning_inputs, retirement_planning_output, retirement_update_output, retirement_planning_examples, retirement_planning_component_rows),
38
+ ]
39
+
40
+ def initial_load(*args):
41
+ idx = 0
42
+ rebalancing_results = rebalancing_update_output(*args[idx:idx+len(rebalancing_inputs)])
43
+ idx += len(rebalancing_inputs)
44
+ share_price_trend_results = share_price_trend_update_output(*args[idx:idx+len(share_price_trend_inputs)])
45
+ idx += len(share_price_trend_inputs)
46
+ dollar_cost_averaging_results = dollar_cost_averaging_update_output(*args[idx:idx+len(dollar_cost_averaging_inputs)])
47
+ idx += len(dollar_cost_averaging_inputs)
48
+ retirement_results = retirement_update_output(*args[idx:])
49
+
50
+ return (rebalancing_results, share_price_trend_results, dollar_cost_averaging_results, retirement_results)
51
 
52
  with gr.Blocks(css='style.css') as demo:
53
  with gr.Column(elem_id="col-container"):
54
  with gr.Tabs():
55
+ for tab in tabs_configuration:
56
+ create_tab(*tab)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  render_about_tab()
58
 
59
+ demo.load(
60
+ initial_load,
61
+ inputs=rebalancing_inputs + share_price_trend_inputs + dollar_cost_averaging_inputs + retirement_planning_inputs,
62
+ outputs=[
63
+ rebalancing_output,
64
+ share_price_trend_output,
65
+ dollar_cost_averaging_output,
66
+ retirement_planning_output
67
+ ]
68
+ )
69
  demo.launch(share=True)
interface/dollar_cost_averaging_interface.py CHANGED
@@ -1,24 +1,22 @@
1
  import gradio as gr
2
- from modules.dollar_cost_averaging import gradio_dollar_cost_averaging, load_css
3
-
4
- def dollar_cost_averaging_interface_fn(old_avg_price, old_quantity, new_price, new_quantity):
5
- result = gradio_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity)
6
- css = load_css()
7
- return css + result
8
 
9
  examples = [
10
  [7857, 7000, 5708, 7000],
11
  [1000, 9000, 560, 20000]
12
  ]
13
  # Define the inputs
 
14
  old_price = gr.Textbox(label="Old Price", value="")
15
  old_quantity = gr.Textbox(label="Quantity", value="")
 
16
  new_price = gr.Textbox(label="New Price", value="")
17
  new_quantity = gr.Textbox(label="Quantity", value="")
18
 
19
  input = [old_price, old_quantity, new_price, new_quantity]
20
  output = gr.HTML()
 
21
 
22
  # Define the update function
23
- def update_output(old_avg_price, old_quantity, new_price, new_quantity):
24
- return dollar_cost_averaging_interface_fn(old_avg_price, old_quantity, new_price, new_quantity)
 
1
  import gradio as gr
2
+ from modules.dollar_cost_averaging import dollar_cost_averaging
 
 
 
 
 
3
 
4
  examples = [
5
  [7857, 7000, 5708, 7000],
6
  [1000, 9000, 560, 20000]
7
  ]
8
  # Define the inputs
9
+ first_purchase = gr.Markdown("<h3 class='input_title'>FIRST PURCHASE</h3>")
10
  old_price = gr.Textbox(label="Old Price", value="")
11
  old_quantity = gr.Textbox(label="Quantity", value="")
12
+ second_purchase = gr.Markdown("<h3 class='input_title'>SECOND PURCHASE</h3>")
13
  new_price = gr.Textbox(label="New Price", value="")
14
  new_quantity = gr.Textbox(label="Quantity", value="")
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/rebalancing_interface.py CHANGED
@@ -1,13 +1,7 @@
1
  import gradio as gr
2
- from modules.rebalancing import rebalancing_tool, load_css
3
- from modules.utils import get_currency_codes
4
 
5
- def rebalancing_interface_fn(main_currency, holdings, cash_amount, cash_ratio):
6
- result = rebalancing_tool(main_currency, holdings, cash_amount, cash_ratio)
7
- css = load_css()
8
- return css + result
9
-
10
- currency_codes = get_currency_codes()
11
  examples = [
12
  ["KRW", "458730 KRW 580 8,\n368590 KRW 80 2", 507977, 0],
13
  ["KRW", "SCHD USD 500 8,\nQQQ USD 200 2", 0, 15]
@@ -20,15 +14,17 @@ main_currency = gr.Dropdown(
20
  value="KRW",
21
  # info="Assets converted to main currency."
22
  )
 
23
  holdings = gr.Textbox(
24
  label="Holdings",
25
  lines=2,
26
  # info="Format: [ ticker currency quantity weight, ... ]",
27
- placeholder="e.g., SCHD USD 500 8, QQQ USD 200 2"
 
28
  )
29
  cash_amount = gr.Number(
30
  label="Cash",
31
- value="",
32
  # info="MAIN CURRENCY CASH"
33
  )
34
  cash_ratio = gr.Slider(
@@ -40,7 +36,8 @@ cash_ratio = gr.Slider(
40
 
41
  input = [main_currency, holdings, cash_amount, cash_ratio]
42
  output = gr.HTML()
 
43
 
44
  # Define the update function
45
- def update_output(main_currency, holdings, cash_amount, cash_ratio):
46
- return rebalancing_interface_fn(main_currency, holdings, cash_amount, cash_ratio)
 
1
  import gradio as gr
2
+ from modules.rebalancing import rebalancing_tool
3
+ from modules.utils import currency_codes
4
 
 
 
 
 
 
 
5
  examples = [
6
  ["KRW", "458730 KRW 580 8,\n368590 KRW 80 2", 507977, 0],
7
  ["KRW", "SCHD USD 500 8,\nQQQ USD 200 2", 0, 15]
 
14
  value="KRW",
15
  # info="Assets converted to main currency."
16
  )
17
+ title_pf = gr.Markdown("""<h3 class='input_title'>Your Portfolio Holdings</h3>""")
18
  holdings = gr.Textbox(
19
  label="Holdings",
20
  lines=2,
21
  # info="Format: [ ticker currency quantity weight, ... ]",
22
+ placeholder="e.g., SCHD USD 500 8, QQQ USD 200 2",
23
+ value="458730 KRW 580 8,\n368590 KRW 80 2"
24
  )
25
  cash_amount = gr.Number(
26
  label="Cash",
27
+ value=507977,
28
  # info="MAIN CURRENCY CASH"
29
  )
30
  cash_ratio = gr.Slider(
 
36
 
37
  input = [main_currency, holdings, cash_amount, cash_ratio]
38
  output = gr.HTML()
39
+ component_rows = [[main_currency], title_pf, [holdings], cash_amount, cash_ratio]
40
 
41
  # Define the update function
42
+ def update_output(*args):
43
+ return rebalancing_tool(*args)
interface/retirement_planning_interface.py CHANGED
@@ -1,45 +1,40 @@
1
  import gradio as gr
2
- from modules.utils import load_css
3
  from modules.retirement_planning import retirement_planning
4
 
5
- def retirement_planning_interface_fn(
6
- current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, current_investment, monthly_investment, annual_increase_in_monthly_investment, reinvest_dividends, pre_retirement_roi, pre_retirement_dividend_yield, post_retirement_roi, post_retirement_dividend_yield
7
- ):
8
- result = retirement_planning(
9
- current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, current_investment, monthly_investment, annual_increase_in_monthly_investment, reinvest_dividends, pre_retirement_roi, pre_retirement_dividend_yield, post_retirement_roi, post_retirement_dividend_yield
10
- )
11
- css = load_css()
12
- return css + result
13
-
14
  # Define examples for retirement planning
15
  examples = [
16
- [38, 55, 85, 2000000, 3.0, 10000000, 500000, 50000, True, 8, 3.3, 8, 3.3],
17
- [15, 45, 90, 3000000, 3.0, 15000000, 700000, 70000, False, 8.0, 3.0, 7.0, 3.0],
18
- [50, 55, 95, 3000000, 4.0, 1000000000, 0, 0, True, 6.0, 3.5, 5.5, 3.2]
19
  ]
20
 
21
  # Define the input components
 
22
  current_age = gr.Slider(label="Current Age (15-60 Years)", value=15, minimum=15, maximum=60, step=1)
23
  retirement_age = gr.Slider(label="Retirement Age (Upto 70 Years)", value=55, minimum=15, maximum=70, step=1)
24
  life_expectancy = gr.Slider(label="Life Expectancy (Upto 100 Years)", value=80, minimum=30, maximum=100, step=1)
 
25
  monthly_income_required = gr.Number(label="Monthly Income Required In Retirement Years (CPP)", value=2000000)
26
  inflation_rate = gr.Number(label="Expected Inflation Rate (%)", value=3)
27
  current_investment = gr.Number(label="Current Investment", value=10000000)
28
  monthly_investment = gr.Number(label="Monthly Investment", value=500000)
29
  annual_increase_in_monthly_investment = gr.Number(label="Annual Increase in Monthly Investment", value=0) # 추가된 입력
30
  reinvest_dividends = gr.Checkbox(label="Reinvest Dividends", value=True)
 
31
  pre_retirement_roi = gr.Number(label="Expected Return On Investment (Pre-retirement) (%)", value=8)
32
- pre_retirement_dividend_yield = gr.Number(label="Expected Dividend Yield (Pre-retirement) (%)", value=3.3)
33
  post_retirement_roi = gr.Number(label="Expected Return On Investment (Post-retirement) (%)", value=8)
 
34
  post_retirement_dividend_yield = gr.Number(label="Expected Dividend Yield (Post-retirement) (%)", value=3.3)
35
 
36
- input = [current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, current_investment, monthly_investment, annual_increase_in_monthly_investment, reinvest_dividends, pre_retirement_roi, pre_retirement_dividend_yield, post_retirement_roi, post_retirement_dividend_yield]
37
  output = gr.HTML()
 
 
 
 
 
38
 
39
  # Define the update function
40
- def update_output(
41
- current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, current_investment, monthly_investment, annual_increase_in_monthly_investment, reinvest_dividends, pre_retirement_roi, pre_retirement_dividend_yield, post_retirement_roi, post_retirement_dividend_yield
42
- ):
43
- return retirement_planning_interface_fn(
44
- current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, current_investment, monthly_investment, annual_increase_in_monthly_investment, reinvest_dividends, pre_retirement_roi, pre_retirement_dividend_yield, post_retirement_roi, post_retirement_dividend_yield
45
- )
 
1
  import gradio as gr
 
2
  from modules.retirement_planning import retirement_planning
3
 
 
 
 
 
 
 
 
 
 
4
  # Define examples for retirement planning
5
  examples = [
6
+ [38, 55, 85, 2000000, 3.0, 10000000, 500000, 50000, True, 8, 8, 3.3, 3.3],
7
+ [15, 45, 90, 3000000, 3.0, 15000000, 700000, 70000, False, 8.0, 7, 3.0, 3.0],
8
+ [50, 55, 95, 3000000, 4.0, 1000000000, 0, 0, True, 6.0, 5.5, 3.5, 3.2]
9
  ]
10
 
11
  # Define the input components
12
+ title_profile = gr.Markdown("<h3 class='input_title'>PROFILE</h3>")
13
  current_age = gr.Slider(label="Current Age (15-60 Years)", value=15, minimum=15, maximum=60, step=1)
14
  retirement_age = gr.Slider(label="Retirement Age (Upto 70 Years)", value=55, minimum=15, maximum=70, step=1)
15
  life_expectancy = gr.Slider(label="Life Expectancy (Upto 100 Years)", value=80, minimum=30, maximum=100, step=1)
16
+ title_savings = gr.Markdown("<h3 class='input_title'>SAVINGS</h3>")
17
  monthly_income_required = gr.Number(label="Monthly Income Required In Retirement Years (CPP)", value=2000000)
18
  inflation_rate = gr.Number(label="Expected Inflation Rate (%)", value=3)
19
  current_investment = gr.Number(label="Current Investment", value=10000000)
20
  monthly_investment = gr.Number(label="Monthly Investment", value=500000)
21
  annual_increase_in_monthly_investment = gr.Number(label="Annual Increase in Monthly Investment", value=0) # 추가된 입력
22
  reinvest_dividends = gr.Checkbox(label="Reinvest Dividends", value=True)
23
+ title_growth = gr.Markdown("<h3 class='input_title'>GROWTH</h3>")
24
  pre_retirement_roi = gr.Number(label="Expected Return On Investment (Pre-retirement) (%)", value=8)
 
25
  post_retirement_roi = gr.Number(label="Expected Return On Investment (Post-retirement) (%)", value=8)
26
+ pre_retirement_dividend_yield = gr.Number(label="Expected Dividend Yield (Pre-retirement) (%)", value=3.3)
27
  post_retirement_dividend_yield = gr.Number(label="Expected Dividend Yield (Post-retirement) (%)", value=3.3)
28
 
29
+ input = [current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, current_investment, monthly_investment, annual_increase_in_monthly_investment, reinvest_dividends, pre_retirement_roi, post_retirement_roi, pre_retirement_dividend_yield, post_retirement_dividend_yield]
30
  output = gr.HTML()
31
+ component_rows = [
32
+ title_profile, [current_age, retirement_age, life_expectancy],[monthly_income_required, inflation_rate],
33
+ title_savings, [current_investment, monthly_investment, annual_increase_in_monthly_investment], [reinvest_dividends],
34
+ title_growth, [pre_retirement_roi, post_retirement_roi], [pre_retirement_dividend_yield, post_retirement_dividend_yield]
35
+ ]
36
 
37
  # Define the update function
38
+ def update_output(*args):
39
+ return retirement_planning(*args)
40
+
 
 
 
interface/share_price_trend_interface.py CHANGED
@@ -1,13 +1,6 @@
1
  import gradio as gr
2
- from modules.utils import load_css
3
  from modules.share_price_trend import share_price_trend
4
 
5
- # Define the function that processes the inputs and returns the result
6
- def share_price_trend_interface_fn(stock_codes, period):
7
- result = share_price_trend(stock_codes, period)
8
- css = load_css()
9
- return css + result
10
-
11
  examples = [
12
  ["AAPL,GOOGL,MSFT", 90],
13
  ["SCHD,QQQ", 365]
@@ -20,15 +13,17 @@ stock_codes = gr.Textbox(
20
  placeholder="e.g., AAPL,GOOGL,MSFT",
21
  value="SCHD,QQQ"
22
  )
23
- period = gr.Number(
24
  label="Number of Days",
25
- value=90
 
26
  )
27
 
28
  # Define output component
29
  input = [stock_codes, period]
30
  output = gr.HTML()
 
31
 
32
  # Define the update function
33
- def update_output(stock_codes, period):
34
- return share_price_trend_interface_fn(stock_codes, period)
 
1
  import gradio as gr
 
2
  from modules.share_price_trend import share_price_trend
3
 
 
 
 
 
 
 
4
  examples = [
5
  ["AAPL,GOOGL,MSFT", 90],
6
  ["SCHD,QQQ", 365]
 
13
  placeholder="e.g., AAPL,GOOGL,MSFT",
14
  value="SCHD,QQQ"
15
  )
16
+ period = gr.Slider(
17
  label="Number of Days",
18
+ value=90,
19
+ maximum=3650
20
  )
21
 
22
  # Define output component
23
  input = [stock_codes, period]
24
  output = gr.HTML()
25
+ component_rows = [[stock_codes], [period]]
26
 
27
  # Define the update function
28
+ def update_output(*args):
29
+ return share_price_trend(*args)
modules/dollar_cost_averaging.py CHANGED
@@ -1,6 +1,6 @@
1
  from modules.utils import load_css
2
 
3
- def 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
@@ -25,7 +25,7 @@ def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
25
  # 새 평균 가격, 총 수량, 총 투자 금액, 새로운 수익률, 추가 투자 금액, 이전 수익률 반환
26
  return new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return
27
 
28
- def gradio_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
29
  css = load_css()
30
 
31
  # 입력값을 숫자로 변환
@@ -35,7 +35,7 @@ def gradio_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_qua
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 = dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity)
39
 
40
  # 수익률에 따른 클래스 설정
41
  new_return_class = ""
@@ -56,7 +56,7 @@ def gradio_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_qua
56
 
57
  # HTML 결과 생성
58
  result_html = css + f"""
59
- <div class="wrap-text" style="box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.1); border-radius: 0.5rem; padding: 3rem; position: relative; width: 100%; padding: 1.5rem;">
60
  <div>
61
  <div style="margin-bottom: 1.5rem;">
62
  <!-- 이전 수익률 표시 -->
 
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
 
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
  # 입력값을 숫자로 변환
 
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
  new_return_class = ""
 
56
 
57
  # HTML 결과 생성
58
  result_html = css + f"""
59
+ <div class="wrap-text">
60
  <div>
61
  <div style="margin-bottom: 1.5rem;">
62
  <!-- 이전 수익률 표시 -->
modules/rebalancing.py CHANGED
@@ -10,52 +10,64 @@ from modules.utils import load_css, get_currency_symbol, format_quantity
10
 
11
  # 주어진 입력을 구문 분석하여 주식 보유량, 현금 금액 및 현금 비율을 계산하는 함수
12
  def parse_input(holdings, cash_amount, cash_ratio):
13
- lines = holdings.strip().split(',')
14
- stock_inputs = []
15
- total_target_weight = 0
16
-
17
- for line in lines:
18
- parts = line.split()
19
- if len(parts) == 4:
20
- stock_code, currency_code, quantity_expr, target_weight_expr = parts
21
- quantity = math.floor(eval(quantity_expr.replace(' ', '')))
22
- target_weight = eval(target_weight_expr.replace(' ', ''))
23
- target_ratio = (1 - cash_ratio / 100) * target_weight
24
- stock_inputs.append((currency_code, stock_code, quantity, target_weight, target_ratio))
25
- total_target_weight += target_weight
26
-
27
- cash_amount = math.floor(cash_amount) if cash_amount else 0
28
- main_currency_cash_inputs = {'amount': cash_amount, 'target_weight': cash_ratio / 100.0}
29
-
30
- stock_total_weight = total_target_weight
31
-
32
- for i in range(len(stock_inputs)):
33
- stock_inputs[i] = (stock_inputs[i][0], stock_inputs[i][1], stock_inputs[i][2], stock_inputs[i][3], (1 - main_currency_cash_inputs['target_weight']) * stock_inputs[i][3] / stock_total_weight)
34
-
35
- return stock_inputs, main_currency_cash_inputs
 
 
 
36
 
37
  # 주어진 통화 코드와 메인 통화 간의 환율을 가져오는 함수
38
  def get_portfolio_exchange_rate(currency_code, main_currency):
39
- if currency_code.lower() == main_currency.lower():
40
- return 1.0
41
-
42
- ticker = f"{currency_code.upper()}{main_currency.upper()}=X"
43
- data = yf.download(ticker, period='1d', progress=False) # progress=False 추가
44
- if not data.empty:
45
- return data['Close'].iloc[0]
46
- else:
47
- raise ValueError("Failed to retrieve exchange rate data.")
 
 
 
48
 
49
  # 주어진 주식 코드와 통화 코드에 대해 환율을 반영한 주식 가격을 가져오는 함수
50
  def get_portfolio_exchange_reflected_stock_price(stock_code, currency_code, main_currency):
51
- new_price = get_portfolio_current_stock_price(stock_code)
52
- exchange_rate = get_portfolio_exchange_rate(currency_code, main_currency)
53
- return math.floor(new_price * exchange_rate)
 
 
 
54
 
55
  # 주어진 주식 코드의 현재 주식 가격을 가져오는 함수
56
  def get_portfolio_current_stock_price(stock_code):
57
- df = fdr.DataReader(stock_code)
58
- return df['Close'].iloc[-1]
 
 
 
59
 
60
  # 주어진 주식 입력 및 현금 입력을 바탕으로 포트폴리오를 구축하는 함수
61
  def build_portfolio(stock_inputs, main_currency_cash_inputs, main_currency):
@@ -86,16 +98,12 @@ def get_portfolio_rebalancing_info(portfolio, target_weights, main_currency_cash
86
 
87
  # 포트폴리오 정보 생���
88
  portfolio_info = css + f"""
89
- <div class="wrap-text" style="box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.1); border-radius: 0.5rem; padding: 3rem; position: relative; width: 100%; padding: 1.5rem;">
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;">Market Value</div>
94
- <span style='font-size: 1.5rem; font-weight: bold; color: #1678fb'>{currency_symbol}{total_value:,.0f}</span>
95
- As of {current_time}
96
- </div>
97
  </div>
98
- </div>
99
  """
100
 
101
  # 현재 비율 및 가치를 계산
@@ -106,8 +114,6 @@ def get_portfolio_rebalancing_info(portfolio, target_weights, main_currency_cash
106
  current_weights['CASH'] = (main_currency_cash_inputs['amount'] / total_value) * 100
107
  current_values['CASH'] = main_currency_cash_inputs['amount']
108
 
109
- # 현재 비율을 기준으로 주식을 내림차순으로 정렬
110
- # sorted_stocks = sorted(current_weights.items(), key=lambda x: x[1], reverse=True)
111
  sorted_stocks = current_weights.items()
112
 
113
  # 현재 보유량 및 가치 섹션 표시
@@ -163,10 +169,8 @@ def get_portfolio_rebalancing_info(portfolio, target_weights, main_currency_cash
163
  currency_totals[currency]['weight'] += current_value / total_value
164
 
165
  currency_totals['CASH'] = {'amount': main_currency_cash_inputs['amount'], 'weight': main_currency_cash_inputs['amount'] / total_value}
166
- # sorted_currencies = sorted(currency_totals.items(), key=lambda x: x[1]['weight'], reverse=True)
167
  sorted_currencies = currency_totals.items()
168
 
169
-
170
  # 통화별 요약 테이블 생성
171
  currency_table = "<h3>Your Portfolio by Currency</h3><div class='table-container wrap-text'><table>"
172
  currency_table += "<thead><tr><th>Currency</th><th>Total Weight (%)</th><th>Total Value</th></tr></thead><tbody>"
@@ -225,7 +229,7 @@ def get_portfolio_rebalancing_info(portfolio, target_weights, main_currency_cash
225
  f"</tr>"
226
  )
227
 
228
- result_message += "</tbody></table></div>"
229
 
230
  return result_message
231
 
@@ -237,4 +241,4 @@ def rebalancing_tool(main_currency, holdings, cash_amount, cash_ratio):
237
  result = get_portfolio_rebalancing_info(portfolio, target_weights, main_currency_cash_inputs, main_currency)
238
  return result
239
  except Exception as e:
240
- return str(e)
 
10
 
11
  # 주어진 입력을 구문 분석하여 주식 보유량, 현금 금액 및 현금 비율을 계산하는 함수
12
  def parse_input(holdings, cash_amount, cash_ratio):
13
+ try:
14
+ lines = holdings.strip().split(',')
15
+ stock_inputs = []
16
+ total_target_weight = 0
17
+
18
+ for line in lines:
19
+ parts = line.split()
20
+ if len(parts) == 4:
21
+ stock_code, currency_code, quantity_expr, target_weight_expr = parts
22
+ quantity = math.floor(eval(quantity_expr.replace(' ', '')))
23
+ target_weight = eval(target_weight_expr.replace(' ', ''))
24
+ target_ratio = (1 - cash_ratio / 100) * target_weight
25
+ stock_inputs.append((currency_code, stock_code, quantity, target_weight, target_ratio))
26
+ total_target_weight += target_weight
27
+
28
+ cash_amount = math.floor(cash_amount) if cash_amount else 0
29
+ main_currency_cash_inputs = {'amount': cash_amount, 'target_weight': cash_ratio / 100.0}
30
+
31
+ stock_total_weight = total_target_weight
32
+
33
+ for i in range(len(stock_inputs)):
34
+ stock_inputs[i] = (stock_inputs[i][0], stock_inputs[i][1], stock_inputs[i][2], stock_inputs[i][3], (1 - main_currency_cash_inputs['target_weight']) * stock_inputs[i][3] / stock_total_weight)
35
+
36
+ return stock_inputs, main_currency_cash_inputs
37
+ except Exception as e:
38
+ raise ValueError(f"Input parsing error: {e}")
39
 
40
  # 주어진 통화 코드와 메인 통화 간의 환율을 가져오는 함수
41
  def get_portfolio_exchange_rate(currency_code, main_currency):
42
+ try:
43
+ if currency_code.lower() == main_currency.lower():
44
+ return 1.0
45
+
46
+ ticker = f"{currency_code.upper()}{main_currency.upper()}=X"
47
+ data = yf.download(ticker, period='1d', progress=False)
48
+ if not data.empty:
49
+ return data['Close'].iloc[0]
50
+ else:
51
+ raise ValueError("Failed to retrieve exchange rate data.")
52
+ except Exception as e:
53
+ raise ValueError(f"Exchange rate retrieval error: {e}")
54
 
55
  # 주어진 주식 코드와 통화 코드에 대해 환율을 반영한 주식 가격을 가져오는 함수
56
  def get_portfolio_exchange_reflected_stock_price(stock_code, currency_code, main_currency):
57
+ try:
58
+ new_price = get_portfolio_current_stock_price(stock_code)
59
+ exchange_rate = get_portfolio_exchange_rate(currency_code, main_currency)
60
+ return math.floor(new_price * exchange_rate)
61
+ except Exception as e:
62
+ raise ValueError(f"Exchange reflected stock price error: {e}")
63
 
64
  # 주어진 주식 코드의 현재 주식 가격을 가져오는 함수
65
  def get_portfolio_current_stock_price(stock_code):
66
+ try:
67
+ df = fdr.DataReader(stock_code)
68
+ return df['Close'].iloc[-1]
69
+ except Exception as e:
70
+ raise ValueError(f"Current stock price retrieval error: {e}")
71
 
72
  # 주어진 주식 입력 및 현금 입력을 바탕으로 포트폴리오를 구축하는 함수
73
  def build_portfolio(stock_inputs, main_currency_cash_inputs, main_currency):
 
98
 
99
  # 포트폴리오 정보 생���
100
  portfolio_info = css + f"""
101
+ <div class="wrap-text">
102
  <div>
103
+ <!-- 전체 평가금액 표시 -->
104
+ <span style='font-size: 2rem; font-weight: bold; color: #1678fb; letter-spacing: 1px;'>{currency_symbol}{total_value:,.0f}</span>
105
+ As of {current_time}
 
 
 
106
  </div>
 
107
  """
108
 
109
  # 현재 비율 및 가치를 계산
 
114
  current_weights['CASH'] = (main_currency_cash_inputs['amount'] / total_value) * 100
115
  current_values['CASH'] = main_currency_cash_inputs['amount']
116
 
 
 
117
  sorted_stocks = current_weights.items()
118
 
119
  # 현재 보유량 및 가치 섹션 표시
 
169
  currency_totals[currency]['weight'] += current_value / total_value
170
 
171
  currency_totals['CASH'] = {'amount': main_currency_cash_inputs['amount'], 'weight': main_currency_cash_inputs['amount'] / total_value}
 
172
  sorted_currencies = currency_totals.items()
173
 
 
174
  # 통화별 요약 테이블 생성
175
  currency_table = "<h3>Your Portfolio by Currency</h3><div class='table-container wrap-text'><table>"
176
  currency_table += "<thead><tr><th>Currency</th><th>Total Weight (%)</th><th>Total Value</th></tr></thead><tbody>"
 
229
  f"</tr>"
230
  )
231
 
232
+ result_message += "</tbody></table></div> </div>"
233
 
234
  return result_message
235
 
 
241
  result = get_portfolio_rebalancing_info(portfolio, target_weights, main_currency_cash_inputs, main_currency)
242
  return result
243
  except Exception as e:
244
+ return f"An error occurred: {e}"
modules/retirement_planning.py CHANGED
@@ -3,7 +3,6 @@ import csv
3
  from io import StringIO
4
  import matplotlib.pyplot as plt
5
  import io
6
-
7
  from modules.utils import load_css
8
 
9
  def retirement_planning(
@@ -17,8 +16,8 @@ def retirement_planning(
17
  annual_increase_in_monthly_investment=None, # 추가된 입력
18
  reinvest_dividends=None,
19
  pre_retirement_roi=None,
20
- pre_retirement_dividend_yield=None,
21
  post_retirement_roi=None,
 
22
  post_retirement_dividend_yield=None
23
  ):
24
  # NoneType일 때 0으로 처리
@@ -135,15 +134,14 @@ def retirement_planning(
135
  plt.close(fig)
136
  svg_data = svg_output.getvalue()
137
  svg_base64 = base64.b64encode(svg_data.encode('utf-8')).decode('utf-8')
 
 
138
 
139
  # 은퇴 계획에 대한 HTML 결과 생성
140
  result_html = css + f"""
141
- <div class="wrap-text" style="box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.1); border-radius: 0.5rem; padding: 3rem; position: relative; width: 100%; padding: 1.5rem;">
142
  <div>
143
- <div style="margin-bottom: 1.5rem;">
144
- <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;"></div>
145
- <img src="data:image/svg+xml;base64,{svg_base64}" alt="Retirement Plan Graph" style="width: 100%; height: auto;"/>
146
- </div>
147
  <div style="margin-bottom: 1.5rem;">
148
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Income Required Immediately After Retirement</div>
149
  <span style='font-size: 1.5rem; font-weight: bold; color: #1678fb'>{annual_income_required_at_retirement:,.0f}</span>
@@ -167,7 +165,11 @@ def retirement_planning(
167
  <span style='font-size: 1.5rem; font-weight: bold; color: #1678fb'>{abs(negative_differences_sum):,.0f}</span>
168
  <hr style="margin: 1.5rem 0;">
169
  </div>
170
-
 
 
 
 
171
  </div>
172
  </div>
173
  <div style="margin-bottom: 2rem;"></div>
 
3
  from io import StringIO
4
  import matplotlib.pyplot as plt
5
  import io
 
6
  from modules.utils import load_css
7
 
8
  def retirement_planning(
 
16
  annual_increase_in_monthly_investment=None, # 추가된 입력
17
  reinvest_dividends=None,
18
  pre_retirement_roi=None,
 
19
  post_retirement_roi=None,
20
+ pre_retirement_dividend_yield=None,
21
  post_retirement_dividend_yield=None
22
  ):
23
  # NoneType일 때 0으로 처리
 
134
  plt.close(fig)
135
  svg_data = svg_output.getvalue()
136
  svg_base64 = base64.b64encode(svg_data.encode('utf-8')).decode('utf-8')
137
+
138
+ graph_html = f'<h3 style="margin-bottom: 0.5rem;">Retirement Planning: Income vs. Dividends</h3>'
139
 
140
  # 은퇴 계획에 대한 HTML 결과 생성
141
  result_html = css + f"""
142
+ <div class="wrap-text">
143
  <div>
144
+
 
 
 
145
  <div style="margin-bottom: 1.5rem;">
146
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Income Required Immediately After Retirement</div>
147
  <span style='font-size: 1.5rem; font-weight: bold; color: #1678fb'>{annual_income_required_at_retirement:,.0f}</span>
 
165
  <span style='font-size: 1.5rem; font-weight: bold; color: #1678fb'>{abs(negative_differences_sum):,.0f}</span>
166
  <hr style="margin: 1.5rem 0;">
167
  </div>
168
+ <div style="margin-bottom: 1.5rem;">
169
+ <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;"></div>
170
+ {graph_html}
171
+ <img src="data:image/svg+xml;base64,{svg_base64}" alt="Retirement Plan Graph" style="width: 100%; height: auto;"/>
172
+ </div>
173
  </div>
174
  </div>
175
  <div style="margin-bottom: 2rem;"></div>
modules/share_price_trend.py CHANGED
@@ -10,6 +10,9 @@ def get_stock_prices(stock_code, days):
10
  end_date = pd.to_datetime('today')
11
  start_date = pd.date_range(end=end_date, periods=days, freq='B')[0]
12
  df = df[(df.index >= start_date) & (df.index <= end_date)]
 
 
 
13
  return df['Close']
14
  except Exception as e:
15
  print(f"Failed to fetch data for {stock_code}: {e}")
@@ -28,19 +31,29 @@ def share_price_trend(stock_codes, days):
28
  except Exception as e:
29
  print(f"Failed to fetch data for {stock_code}: {e}")
30
 
 
 
 
31
  plt.switch_backend('agg')
32
- plt.style.use('tableau-colorblind10') # 테마 변경
33
 
34
  fig, ax = plt.subplots(figsize=(8, 4.5))
35
  for stock_code, prices in stock_prices.items():
36
  relative_prices = prices / prices.iloc[0]
37
  ax.plot(prices.index, relative_prices, label=stock_code.upper())
38
-
 
39
  ax.spines['top'].set_visible(False)
40
  ax.spines['right'].set_visible(False)
 
 
 
 
 
 
 
 
41
 
42
- ax.set_xlabel('Date')
43
- ax.set_ylabel('Relative Price (Normalized to 1)')
44
  ax.legend()
45
  plt.tight_layout()
46
 
@@ -81,7 +94,6 @@ def share_price_trend(stock_codes, days):
81
  </style>
82
  </svg>''')
83
 
84
- # Replace line color with gradient, add shadow filter, and apply animation
85
  svg_data = svg_data.replace('stroke="#1f77b4"', 'stroke="url(#grad1)" filter="url(#dropshadow)"')
86
 
87
  html_table = "<h3>Stock Prices Data</h3><div class='table-container'><table>"
@@ -90,11 +102,17 @@ def share_price_trend(stock_codes, days):
90
  html_table += f"<th>{stock_code.upper()}</th>"
91
  html_table += "</tr></thead><tbody>"
92
 
93
- dates = stock_prices[list(stock_prices.keys())[0]].index[::-1]
94
- for date in dates:
 
 
95
  html_table += f"<tr><td>{date.strftime('%Y-%m-%d')}</td>"
96
  for stock_code in stock_prices.keys():
97
- html_table += f"<td>{stock_prices[stock_code][date]:,.2f}</td>"
 
 
 
 
98
  html_table += "</tr>"
99
 
100
  html_table += "</tbody></table></div>"
@@ -102,8 +120,8 @@ def share_price_trend(stock_codes, days):
102
  graph_html = f'<h3>Relative Stock Prices Over the Last {days} Days</h3>{svg_data}'
103
  return graph_html + html_table
104
 
105
- # 예시 사용 방법
106
  # stock_codes = "AAPL,MSFT,GOOGL"
107
  # days = 30
108
- # result = compare_stock_prices(stock_codes, days)
109
  # print(result)
 
10
  end_date = pd.to_datetime('today')
11
  start_date = pd.date_range(end=end_date, periods=days, freq='B')[0]
12
  df = df[(df.index >= start_date) & (df.index <= end_date)]
13
+ if df.empty:
14
+ print(f"No data available for {stock_code}")
15
+ return None
16
  return df['Close']
17
  except Exception as e:
18
  print(f"Failed to fetch data for {stock_code}: {e}")
 
31
  except Exception as e:
32
  print(f"Failed to fetch data for {stock_code}: {e}")
33
 
34
+ if not stock_prices:
35
+ return "<p>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
 
 
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>"
 
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
+
108
+ for date in all_dates:
109
  html_table += f"<tr><td>{date.strftime('%Y-%m-%d')}</td>"
110
  for stock_code in stock_prices.keys():
111
+ price = stock_prices[stock_code].get(date, None)
112
+ if price is not None:
113
+ html_table += f"<td>{price:,.2f}</td>"
114
+ else:
115
+ html_table += "<td>N/A</td>"
116
  html_table += "</tr>"
117
 
118
  html_table += "</tbody></table></div>"
 
120
  graph_html = f'<h3>Relative Stock Prices Over the Last {days} Days</h3>{svg_data}'
121
  return graph_html + html_table
122
 
123
+ # Example usage
124
  # stock_codes = "AAPL,MSFT,GOOGL"
125
  # days = 30
126
+ # result = share_price_trend(stock_codes, days)
127
  # print(result)
modules/utils.py CHANGED
@@ -35,8 +35,10 @@ def get_currency_symbol(currency_code):
35
  def get_currency_codes():
36
  return list(currency_symbols.keys())
37
 
 
 
38
  # Helper function to add buttons
39
- def clear_buttons(inputs, update_fn, output):
40
  clear_button = gr.ClearButton(value="Clear")
41
  clear_button.click(
42
  fn=lambda: [None] * len(inputs),
@@ -53,3 +55,32 @@ def submit_buttons(inputs, update_fn, output):
53
  outputs=output
54
  )
55
  return submit_button
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  def get_currency_codes():
36
  return list(currency_symbols.keys())
37
 
38
+ currency_codes = get_currency_codes()
39
+
40
  # Helper function to add buttons
41
+ def clear_buttons(inputs):
42
  clear_button = gr.ClearButton(value="Clear")
43
  clear_button.click(
44
  fn=lambda: [None] * len(inputs),
 
55
  outputs=output
56
  )
57
  return submit_button
58
+
59
+ def on_change(inputs, update_ouutput, outputs):
60
+ for input_component in inputs:
61
+ input_component.change(
62
+ fn=update_ouutput,
63
+ inputs=inputs,
64
+ outputs=outputs
65
+ )
66
+
67
+ def render_components(component_rows):
68
+ for row in component_rows:
69
+ if isinstance(row, list):
70
+ with gr.Row():
71
+ for component in row:
72
+ component.render()
73
+ else:
74
+ row.render()
75
+
76
+ def create_tab(tab_name, inputs, outputs, update_fn, examples, component_rows):
77
+ with gr.TabItem(tab_name):
78
+ with gr.Row():
79
+ with gr.Column(elem_classes="input"):
80
+ render_components(component_rows)
81
+ # clear_buttons(inputs)
82
+ # submit_buttons(inputs, update_fn, outputs)
83
+ gr.Examples(examples=examples, cache_examples=False, inputs=inputs)
84
+ with gr.Column():
85
+ outputs.render()
86
+ on_change(inputs, update_fn, outputs)
style.css CHANGED
@@ -20,6 +20,13 @@
20
 
21
  }
22
 
 
 
 
 
 
 
 
23
  .code {
24
  font-family: 'IBM Plex Mono', 'ui-monospace', 'Consolas', 'monospace';
25
  }
 
20
 
21
  }
22
 
23
+ .input_title {
24
+ padding: .75rem;
25
+ font-weight: 700;
26
+ border-bottom: 1px solid rgb(229, 231, 235);
27
+ /* box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); */
28
+ }
29
+
30
  .code {
31
  font-family: 'IBM Plex Mono', 'ui-monospace', 'Consolas', 'monospace';
32
  }