cryman38 commited on
Commit
ee455e6
ยท
verified ยท
1 Parent(s): 92a2e10

Upload 16 files

Browse files
app.py CHANGED
@@ -105,7 +105,7 @@ def create_tab(tab_name, inputs, outputs, update_fn, examples, component_rows):
105
  render_components(component_rows)
106
  clear_buttons(inputs)
107
  submit_buttons(inputs, update_fn, outputs)
108
- with gr.Column(scale=2):
109
  outputs.render()
110
  with gr.Accordion("๐Ÿ‘€ Examples", open=False):
111
  gr.Examples(examples=examples, cache_examples=False, inputs=inputs)
 
105
  render_components(component_rows)
106
  clear_buttons(inputs)
107
  submit_buttons(inputs, update_fn, outputs)
108
+ with gr.Column(scale=3):
109
  outputs.render()
110
  with gr.Accordion("๐Ÿ‘€ Examples", open=False):
111
  gr.Examples(examples=examples, cache_examples=False, inputs=inputs)
interface/dollar_cost_averaging_interface.py CHANGED
@@ -2,20 +2,20 @@ import gradio as gr
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
- stock_code = gr.Textbox(label="Stock Code", value="368590")
10
  first_purchase = gr.Markdown("<h3 class='h3_title'>FIRST PURCHASE</h3>")
11
  old_price = gr.Number(label="Old Price", value=18153)
12
  old_quantity = gr.Number(label="Quantity", value=122)
13
  second_purchase = gr.Markdown("<h3 class='h3_title'>SECOND PURCHASE</h3>")
 
14
  new_quantity = gr.Number(label="Quantity", value=1)
15
 
16
- input = [stock_code, old_price, old_quantity, new_quantity]
17
  output = gr.HTML()
18
- component_rows = [stock_code, first_purchase, old_price, old_quantity, second_purchase, 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
+ [200, 90, 100, 200]
6
  ]
7
 
8
  # Define the inputs
 
9
  first_purchase = gr.Markdown("<h3 class='h3_title'>FIRST PURCHASE</h3>")
10
  old_price = gr.Number(label="Old Price", value=18153)
11
  old_quantity = gr.Number(label="Quantity", value=122)
12
  second_purchase = gr.Markdown("<h3 class='h3_title'>SECOND PURCHASE</h3>")
13
+ new_price = gr.Textbox(label="New Price", value="15000")
14
  new_quantity = gr.Number(label="Quantity", value=1)
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):
interface/retirement_planning_interface.py CHANGED
@@ -27,9 +27,9 @@ post_retirement_dividend_yield = gr.Number(label="Dividend Yield (Post-retiremen
27
  input = [current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, initial_investment, monthly_contribution, annual_increase_in_monthly_contribution, reinvest_dividends, pre_retirement_dividend_growth, post_retirement_dividend_growth, pre_retirement_dividend_yield, post_retirement_dividend_yield]
28
  output = gr.HTML()
29
  component_rows = [
30
- title_1, [current_age, retirement_age, life_expectancy],[monthly_income_required, inflation_rate],
31
- title_2, [initial_investment, monthly_contribution, annual_increase_in_monthly_contribution], [reinvest_dividends],
32
- title_3, [pre_retirement_dividend_growth, post_retirement_dividend_growth], [pre_retirement_dividend_yield, post_retirement_dividend_yield]
33
  ]
34
 
35
  # Define the update function
 
27
  input = [current_age, retirement_age, life_expectancy, monthly_income_required, inflation_rate, initial_investment, monthly_contribution, annual_increase_in_monthly_contribution, reinvest_dividends, pre_retirement_dividend_growth, post_retirement_dividend_growth, pre_retirement_dividend_yield, post_retirement_dividend_yield]
28
  output = gr.HTML()
29
  component_rows = [
30
+ [current_age, retirement_age, life_expectancy],[monthly_income_required, inflation_rate],
31
+ [initial_investment, monthly_contribution, annual_increase_in_monthly_contribution], [reinvest_dividends],
32
+ [pre_retirement_dividend_growth, post_retirement_dividend_growth], [pre_retirement_dividend_yield, post_retirement_dividend_yield]
33
  ]
34
 
35
  # Define the update function
modules/dollar_cost_averaging.py CHANGED
@@ -2,20 +2,20 @@ 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
- # ํ•œ๊ตญ ์ฃผ์‹ ์ฝ”๋“œ๊ฐ€ ์ˆซ์ž๋งŒ ์žˆ๋Š”์ง€ ํ™•์ธ (ํ•œ๊ตญ ์ฃผ์‹์€ ๋ณดํ†ต ์ˆซ์ž ์ฝ”๋“œ)
8
- if stock_code.isdigit():
9
- df = fdr.DataReader(stock_code)
10
- return df['Close'].iloc[-1]
11
- else:
12
- # ํ•œ๊ตญ ์™ธ ์ฃผ์‹์€ yfinance๋กœ ์กฐํšŒ
13
- stock = yf.Ticker(stock_code)
14
- df = stock.history(period="1d")
15
- return df['Close'].iloc[-1]
16
- except Exception as e:
17
- # ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ 0.0์œผ๋กœ ์„ค์ •ํ•˜๊ณ , ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜
18
- return None
19
 
20
  def calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
21
  old_avg_price = float(old_avg_price) if old_avg_price else 0.0
@@ -36,15 +36,15 @@ def calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_
36
 
37
  return new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return
38
 
39
- def dollar_cost_averaging(stock_code, old_avg_price, old_quantity, new_quantity):
40
  css = load_css()
41
 
42
  # ์ฃผ์‹ ๊ฐ€๊ฒฉ ๊ฐ€์ ธ์˜ค๊ธฐ
43
- new_price = get_stock_price(stock_code)
44
 
45
- new_price = float(new_price) if new_price else 0.0
46
  old_avg_price = float(old_avg_price) if old_avg_price else 0.0
47
  old_quantity = float(old_quantity) if old_quantity else 0.0
 
48
  new_quantity = float(new_quantity) if new_quantity else 0.0
49
 
50
  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)
@@ -52,9 +52,9 @@ def dollar_cost_averaging(stock_code, old_avg_price, old_quantity, new_quantity)
52
  emoji_return = ""
53
  new_return_class = ""
54
  old_return_class = ""
55
- if new_return > old_return:
56
  emoji_return = "๐Ÿ’ง"
57
- elif new_return < old_return:
58
  emoji_return = "๐Ÿ”ฅ"
59
  else:
60
  emoji_return = ""
@@ -77,18 +77,14 @@ def dollar_cost_averaging(stock_code, old_avg_price, old_quantity, new_quantity)
77
  <div class="wrap-text">
78
  <div>
79
  <div style="margin-bottom: 1.5rem;">
80
- <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">New Price</div>
81
- <div style="font-size: 1.5rem; color: #1c75bc;">
82
- <span style='color: #1678fb; font-weight: bold;'>{new_price:,}</span>
83
- </div>
84
- <hr style="margin: 1.5rem 0;">
85
  </div>
86
  </div>
87
  <div>
88
  <div style="margin-bottom: 1.5rem;">
89
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Old Price</div>
90
  <div style="font-size: 1.5rem; color: #1c75bc;">
91
- <span style='color: #1678fb; font-weight: bold;'>{old_avg_price:,.0f}</span>
92
  <span style='font-size: 1rem;'>{old_return_class}</span>
93
  </div>
94
  <hr style="margin: 1.5rem 0;">
@@ -98,7 +94,7 @@ def dollar_cost_averaging(stock_code, old_avg_price, old_quantity, new_quantity)
98
  <div style="margin-bottom: 1.5rem;">
99
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Average Price</div>
100
  <div style="font-size: 1.5rem; color: #1c75bc;">
101
- <span style='color: #1678fb; font-weight: bold;'>{new_avg_price:,.0f}</span>
102
  <span style='font-size: 1rem;'>{new_return_class}</span>
103
  </div>
104
  <hr style="margin: 1.5rem 0;">
@@ -108,7 +104,7 @@ def dollar_cost_averaging(stock_code, old_avg_price, old_quantity, new_quantity)
108
  <div style="margin-bottom: 1.5rem;">
109
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Additional Investment</div>
110
  <div style="font-size: 1.5rem; font-weight: bold; color: #1c75bc;">
111
- <span style='color: #1678fb'>{additional_investment:,.0f}</span>
112
  </div>
113
  <hr style="margin: 1.5rem 0;">
114
  </div>
 
2
  import FinanceDataReader as fdr
3
  from modules.utils import load_css
4
 
5
+ # def get_stock_price(stock_code):
6
+ # try:
7
+ # # ํ•œ๊ตญ ์ฃผ์‹ ์ฝ”๋“œ๊ฐ€ ์ˆซ์ž๋งŒ ์žˆ๋Š”์ง€ ํ™•์ธ (ํ•œ๊ตญ ์ฃผ์‹์€ ๋ณดํ†ต ์ˆซ์ž ์ฝ”๋“œ)
8
+ # if stock_code.isdigit():
9
+ # df = fdr.DataReader(stock_code)
10
+ # return df['Close'].iloc[-1]
11
+ # else:
12
+ # # ํ•œ๊ตญ ์™ธ ์ฃผ์‹์€ yfinance๋กœ ์กฐํšŒ
13
+ # stock = yf.Ticker(stock_code)
14
+ # df = stock.history(period="1d")
15
+ # return df['Close'].iloc[-1]
16
+ # except Exception as e:
17
+ # # ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ 0.0์œผ๋กœ ์„ค์ •ํ•˜๊ณ , ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜
18
+ # return None
19
 
20
  def calculate_dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
21
  old_avg_price = float(old_avg_price) if old_avg_price else 0.0
 
36
 
37
  return new_avg_price, total_quantity, total_investment, new_return, additional_investment, old_return
38
 
39
+ def dollar_cost_averaging(old_avg_price, old_quantity, new_price, new_quantity):
40
  css = load_css()
41
 
42
  # ์ฃผ์‹ ๊ฐ€๊ฒฉ ๊ฐ€์ ธ์˜ค๊ธฐ
43
+ # new_price = get_stock_price(stock_code)
44
 
 
45
  old_avg_price = float(old_avg_price) if old_avg_price else 0.0
46
  old_quantity = float(old_quantity) if old_quantity else 0.0
47
+ new_price = float(new_price) if new_price else 0.0
48
  new_quantity = float(new_quantity) if new_quantity else 0.0
49
 
50
  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)
 
52
  emoji_return = ""
53
  new_return_class = ""
54
  old_return_class = ""
55
+ if new_price < old_avg_price:
56
  emoji_return = "๐Ÿ’ง"
57
+ elif new_price > old_avg_price:
58
  emoji_return = "๐Ÿ”ฅ"
59
  else:
60
  emoji_return = ""
 
77
  <div class="wrap-text">
78
  <div>
79
  <div style="margin-bottom: 1.5rem;">
80
+ <div style="font-size: 2.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">{emoji_return}</div>
 
 
 
 
81
  </div>
82
  </div>
83
  <div>
84
  <div style="margin-bottom: 1.5rem;">
85
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Old Price</div>
86
  <div style="font-size: 1.5rem; color: #1c75bc;">
87
+ <span style='color: #1678fb; font-weight: bold;'>{old_avg_price:,.2f}</span>
88
  <span style='font-size: 1rem;'>{old_return_class}</span>
89
  </div>
90
  <hr style="margin: 1.5rem 0;">
 
94
  <div style="margin-bottom: 1.5rem;">
95
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Average Price</div>
96
  <div style="font-size: 1.5rem; color: #1c75bc;">
97
+ <span style='color: #1678fb; font-weight: bold;'>{new_avg_price:,.2f}</span>
98
  <span style='font-size: 1rem;'>{new_return_class}</span>
99
  </div>
100
  <hr style="margin: 1.5rem 0;">
 
104
  <div style="margin-bottom: 1.5rem;">
105
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Additional Investment</div>
106
  <div style="font-size: 1.5rem; font-weight: bold; color: #1c75bc;">
107
+ <span style='color: #1678fb'>{additional_investment:,.2f}</span>
108
  </div>
109
  <hr style="margin: 1.5rem 0;">
110
  </div>
modules/rebalancing.py CHANGED
@@ -192,17 +192,9 @@ def generate_rebalancing_analysis(portfolio, target_ratios, total_value, main_cu
192
 
193
  # HTML ์ƒ์„ฑ
194
  rebalancing_analysis = css + f"""
195
- <div class="wrap-text">
196
- <div>
197
- <div style="margin-bottom: 1.5rem;">
198
- <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Re-Balancing Analysis | Your Portfolio Holdings as of {current_time}</div>
199
- <span style='font-size: 1.5rem; font-weight: bold; color: #1678fb'>{currency_symbol}{format_value(sum(adj['new_value'] for adj in adjustments))}</span>
200
- (After Trades)
201
- <hr style="margin: 1.5rem 0;">
202
- <br>
203
- </div>
204
- </div>
205
- <div class='table-container wrap-text'>
206
  <table>
207
  <thead>
208
  <tr>
 
192
 
193
  # HTML ์ƒ์„ฑ
194
  rebalancing_analysis = css + f"""
195
+ <div>
196
+
197
+ <div class='table-container'>
 
 
 
 
 
 
 
 
198
  <table>
199
  <thead>
200
  <tr>
modules/retirement_planning.py CHANGED
@@ -229,22 +229,16 @@ def retirement_planning(
229
  # HTML ๊ฒฐ๊ณผ ์ƒ์„ฑ
230
  result_html = css + f"""
231
  <div class="wrap-text">
232
- <div>
233
- <div style="margin-bottom: 1.5rem;">
234
- <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Total Shortfall</div>
235
- <span style='font-size: 1.5rem; font-weight: bold; color: #1678fb'>{abs(negative_differences_sum):,.0f}</span>
236
- <hr style="margin: 1.5rem 0;">
237
- </div>
238
  <div style="margin-bottom: 1.5rem;">
239
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Needs Overview</div>
240
  <iframe src="data:text/html;base64,{svg_base64}" style="width: 100%; height: 400px; border: none;"></iframe>
241
- <hr style="margin: 1.5rem 0;">
242
  </div>
243
  </div>
244
  </div>
245
  <div style="margin-bottom: 2rem;"></div>
246
  <div style="display: flex; align-items: center; justify-content: space-between;">
247
- <h3>Retirement Plan Overview</h3>
248
  <a href="data:text/csv;base64,{csv_base64}" download="retirement_planning.csv" style="padding: 10px 20px; border: 1px solid; border-radius: 5px; background-color: #1678fb; color: white; text-decoration: none;">Download CSV</a>
249
  </div>
250
  """ + table_html + """
 
229
  # HTML ๊ฒฐ๊ณผ ์ƒ์„ฑ
230
  result_html = css + f"""
231
  <div class="wrap-text">
232
+ <div>
 
 
 
 
 
233
  <div style="margin-bottom: 1.5rem;">
234
  <div style="font-size: 1.5rem; margin-top: 1.5rem; margin-bottom: 1.5rem;">Needs Overview</div>
235
  <iframe src="data:text/html;base64,{svg_base64}" style="width: 100%; height: 400px; border: none;"></iframe>
 
236
  </div>
237
  </div>
238
  </div>
239
  <div style="margin-bottom: 2rem;"></div>
240
  <div style="display: flex; align-items: center; justify-content: space-between;">
241
+ <h3>Retirement Plan Overview (Total Shortfall :<span style='font-weight: bold; color: #1678fb'>{abs(negative_differences_sum):,.0f}</span>)</h3>
242
  <a href="data:text/csv;base64,{csv_base64}" download="retirement_planning.csv" style="padding: 10px 20px; border: 1px solid; border-radius: 5px; background-color: #1678fb; color: white; text-decoration: none;">Download CSV</a>
243
  </div>
244
  """ + table_html + """
style.css CHANGED
@@ -64,6 +64,9 @@ body {
64
  margin: 0 auto;
65
  max-width: 100%;
66
  font-family: 'Quicksand', 'ui-sans-serif', 'system-ui', 'sans-serif';
 
 
 
67
  }
68
 
69
  .h3_title {
@@ -86,9 +89,11 @@ body {
86
  }
87
 
88
  .wrap-text {
89
- word-wrap: break-word;
90
- overflow-wrap: break-word;
91
- white-space: normal;
 
 
92
  }
93
 
94
  .buy-sell {
 
64
  margin: 0 auto;
65
  max-width: 100%;
66
  font-family: 'Quicksand', 'ui-sans-serif', 'system-ui', 'sans-serif';
67
+ word-wrap: break-word;
68
+ overflow-wrap: break-word;
69
+ white-space: normal;
70
  }
71
 
72
  .h3_title {
 
89
  }
90
 
91
  .wrap-text {
92
+ margin: auto; /* ๊ฐ€์šด๋ฐ ์ •๋ ฌ */
93
+ padding: 20px;
94
+ border: 1px solid #e5e5e5; /* ์–‡์€ ํ…Œ๋‘๋ฆฌ */
95
+ border-radius: 10px; /* ๋ชจ์„œ๋ฆฌ ๋‘ฅ๊ธ€๊ฒŒ */
96
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); /* ๊ทธ๋ฆผ์ž */
97
  }
98
 
99
  .buy-sell {