Python/파이썬과 주식, 코인
파이썬으로 만들어 본 주식 계산기
컴닥
2025. 3. 28. 17:10
반응형
1. 매수 매도 가격 입력 -> 예상 수익률
2. 매수 가격, 목표 수익률 입력 -> 매도 가격
매수 매도 수수료 및 증권 거래세를 포함.
다만 실제 거래에서는 10원 단위 절사 등을 하는데, 완벽하게 같지는 않습니다.
참고만 하시구요.
혹시 오류가 있다면 리플 남겨주세요.
pip install ttkbootstrap
import os
import tkinter as tk
from tkinter import font, ttk
from ttkbootstrap import Style
BUY_FEE = 0.015
SELL_FEE = 0.015
TAX = 0.15
def on_radiobutton_click(*args):
if selected_option_var.get() == 'profit_rate':
buy_price_label.configure(font=BOLD_FONT)
sell_price_label.configure(font=BOLD_FONT)
quantity_label.configure(font=BOLD_FONT)
profit_rate_label.configure(font=DEFAULT_FONT)
elif selected_option_var.get() == 'sell_price':
buy_price_label.configure(font=BOLD_FONT)
sell_price_label.configure(font=DEFAULT_FONT)
quantity_label.configure(font=BOLD_FONT)
profit_rate_label.configure(font=BOLD_FONT)
def on_key_release(entry):
format_number(entry)
if selected_option_var.get() == 'profit_rate':
calculate_profit()
elif selected_option_var.get() == 'sell_price':
calculate_sell_price()
def format_number(entry):
value = entry.get().replace(',', '')
if value.isdigit():
formatted_value = f'{int(value):,}'
entry.delete(0, tk.END)
entry.insert(0, formatted_value)
def calculate_sell_price(*args):
try:
buy_price = float(buy_price_entry.get().replace(',', ''))
quantity = int(quantity_entry.get().replace(',', ''))
profit_rate = float(profit_rate_entry.get()) / 100
buy_fee_rate = float(buy_fee_entry.get()) / 100
sell_fee_rate = float(sell_fee_entry.get()) / 100
tax_rate = float(tax_entry.get()) / 100
total_buy = buy_price * quantity * (1 + buy_fee_rate)
total_buy_fee = buy_price * quantity * buy_fee_rate
sell_price = buy_price * (1 + buy_fee_rate) * (1 + profit_rate) / (1 - sell_fee_rate - tax_rate)
total_sell = sell_price * quantity * (1 - sell_fee_rate - tax_rate)
total_sell_fee_tax = sell_price * quantity * (sell_fee_rate + tax_rate)
profit = total_sell - total_buy
sell_price_entry.delete(0, tk.END)
sell_price_entry.insert(0, f'{sell_price:,.2f}')
fee_entry.delete(0, tk.END)
fee_entry.insert(0, f'{total_buy_fee + total_sell_fee_tax:,.2f}')
profit_entry.delete(0, tk.END)
profit_entry.insert(0, f'{profit:,.2f}')
except Exception as e:
print(e)
def calculate_profit(*args):
try:
buy_price = float(buy_price_entry.get().replace(',', ''))
sell_price = float(sell_price_entry.get().replace(',', ''))
quantity = int(quantity_entry.get().replace(',', ''))
buy_fee_rate = float(buy_fee_entry.get()) / 100
sell_fee_rate = float(sell_fee_entry.get()) / 100
tax_rate = float(tax_entry.get()) / 100
total_buy = buy_price * quantity * (1 + buy_fee_rate)
total_buy_fee = buy_price * quantity * buy_fee_rate
total_sell = sell_price * quantity * (1 - sell_fee_rate - tax_rate)
total_sell_fee_tax = sell_price * quantity * (sell_fee_rate + tax_rate)
profit = total_sell - total_buy
profit_rate = (profit / total_buy) * 100
fee_entry.delete(0, tk.END)
fee_entry.insert(0, f'{total_buy_fee + total_sell_fee_tax:,.2f}')
profit_entry.delete(0, tk.END)
profit_entry.insert(0, f'{profit:,.2f}')
profit_rate_entry.delete(0, tk.END)
profit_rate_entry.insert(0, f'{profit_rate:,.2f}')
except Exception as e:
print(e)
def toggle_always_on_top():
if always_on_top_var.get():
root.wm_attributes('-topmost', 1) # 항상 위
else:
root.wm_attributes('-topmost', 0) # 기본 상태
root = tk.Tk()
root.title('주식 계산기')
root.wm_attributes('-topmost', 1)
if os.path.isfile('icon.ico'):
root.iconbitmap('icon.ico')
style = Style(theme='superhero')
DEFAULT_FONT = font.nametofont("TkDefaultFont")
BOLD_FONT = font.Font(**{**DEFAULT_FONT.actual(), 'weight': 'bold', 'underline': 1})
frame1 = ttk.Frame(root, padding=(10, 10, 10, 0))
frame1.pack()
selected_option_var = tk.StringVar(value='profit_rate')
selected_option_var.trace_add("write", on_radiobutton_click)
profit_rate_radio = ttk.Radiobutton(frame1, text='수익률', variable=selected_option_var, value='profit_rate',
style='Toolbutton')
profit_rate_radio.grid(row=0, column=1)
sell_price_radio = ttk.Radiobutton(frame1, text='매도가격', variable=selected_option_var, value='sell_price',
style='Toolbutton')
sell_price_radio.grid(row=0, column=2)
frame2 = ttk.Frame(root, padding=10)
frame2.pack()
buy_price_label = ttk.Label(frame2, text='매수가격')
buy_price_label.configure(font=BOLD_FONT)
buy_price_label.grid(row=0, column=0, sticky='e')
buy_price_entry = ttk.Entry(frame2)
buy_price_entry.grid(row=0, column=1)
buy_price_entry.bind('<KeyRelease>', lambda e: on_key_release(buy_price_entry))
sell_price_label = ttk.Label(frame2, text='매도가격')
sell_price_label.configure(font=BOLD_FONT)
sell_price_label.grid(row=1, column=0, sticky='e')
sell_price_entry = ttk.Entry(frame2)
sell_price_entry.grid(row=1, column=1)
sell_price_entry.bind('<KeyRelease>', lambda e: on_key_release(sell_price_entry))
quantity_label = ttk.Label(frame2, text='수량')
quantity_label.configure(font=BOLD_FONT)
quantity_label.grid(row=2, column=0, sticky='e')
quantity_entry = ttk.Entry(frame2)
quantity_entry.grid(row=2, column=1)
quantity_entry.bind('<KeyRelease>', lambda e: on_key_release(quantity_entry))
profit_rate_label = ttk.Label(frame2, text='수익률(%)')
profit_rate_label.configure(font=DEFAULT_FONT)
profit_rate_label.grid(row=3, column=0, sticky='e')
profit_rate_entry = ttk.Entry(frame2)
profit_rate_entry.grid(row=3, column=1)
profit_rate_entry.bind('<KeyRelease>', lambda e: on_key_release(profit_rate_entry))
profit_label = ttk.Label(frame2, text='수익(원)')
profit_label.grid(row=4, column=0, sticky='e')
profit_entry = ttk.Entry(frame2)
profit_entry.grid(row=4, column=1)
fee_label = ttk.Label(frame2, text='수수료 및 세금(원)')
fee_label.grid(row=5, column=0, sticky='e')
fee_entry = ttk.Entry(frame2)
fee_entry.grid(row=5, column=1)
buy_fee_label = ttk.Label(frame2, text='매수 수수료(%)')
buy_fee_label.grid(row=6, column=0, sticky='e')
buy_fee_entry = ttk.Entry(frame2)
buy_fee_entry.grid(row=6, column=1)
buy_fee_entry.insert(0, str(BUY_FEE))
buy_fee_entry.bind('<KeyRelease>', calculate_profit)
sell_fee_label = ttk.Label(frame2, text='매도 수수료(%)')
sell_fee_label.grid(row=7, column=0, sticky='e')
sell_fee_entry = ttk.Entry(frame2)
sell_fee_entry.grid(row=7, column=1)
sell_fee_entry.insert(0, str(SELL_FEE))
sell_fee_entry.bind('<KeyRelease>', calculate_profit)
tax_label = ttk.Label(frame2, text='증권거래세(%)')
tax_label.grid(row=8, column=0, sticky='e')
tax_entry = ttk.Entry(frame2)
tax_entry.grid(row=8, column=1)
tax_entry.insert(0, str(TAX))
tax_entry.bind('<KeyRelease>', calculate_profit)
frame3 = ttk.Frame(root, padding=(10, 0, 10, 10))
frame3.pack()
always_on_top_var = tk.BooleanVar(value=True)
always_on_top_checkbox = ttk.Checkbutton(frame3, text='항상 위', variable=always_on_top_var, command=toggle_always_on_top)
always_on_top_checkbox.grid(row=9, column=0, sticky='w')
root.mainloop()
개선할 점..
Configparser나 yaml 등을 이용해
BUY_FEE = 0.015
SELL_FEE = 0.015
TAX = 0.15
이런 변수들을 외부에서 다룰 수 있도록 한다면 좋을 것 같습니다.
어렵지 않으니 직접 해보시는 것을 추천합니다.
반응형