feat: Add trading app with position calculator and portfolio management

This commit is contained in:
Bobby Abellana (aider) 2025-02-06 21:10:59 -08:00
parent 8302d796e0
commit b7d3b8bc6d
No known key found for this signature in database
GPG Key ID: 647714CC45F3647B
3 changed files with 175 additions and 0 deletions

87
src/trading/main.py Normal file
View File

@ -0,0 +1,87 @@
from datetime import datetime
from position_calculator import PositionCalculator
from portfolio import Portfolio, Position
def main():
# Initialize portfolio and position calculator
portfolio = Portfolio()
calculator = PositionCalculator(account_size=100000) # $100k account
while True:
print("\nTrading Management System")
print("1. Calculate Position Size")
print("2. Add Position")
print("3. View Portfolio")
print("4. Remove Position")
print("5. Exit")
choice = input("\nSelect an option (1-5): ")
if choice == "1":
try:
entry_price = float(input("Enter entry price: "))
stop_loss = float(input("Enter stop loss price: "))
position = calculator.calculate_position_size(entry_price, stop_loss)
print("\nPosition Details:")
print(f"Shares: {position['shares']}")
print(f"Position Value: ${position['position_value']:.2f}")
print(f"Risk Amount: ${position['risk_amount']:.2f}")
print(f"Risk Per Share: ${position['risk_per_share']:.2f}")
except ValueError as e:
print(f"Error: {e}")
elif choice == "2":
try:
symbol = input("Enter symbol: ")
entry_price = float(input("Enter entry price: "))
shares = int(input("Enter number of shares: "))
stop_loss = float(input("Enter stop loss: "))
target_price = float(input("Enter target price: "))
position = Position(
symbol=symbol,
entry_date=datetime.now(),
entry_price=entry_price,
shares=shares,
stop_loss=stop_loss,
target_price=target_price
)
portfolio.add_position(position)
print(f"\nAdded position: {symbol}")
except ValueError:
print("Invalid input. Please try again.")
elif choice == "3":
positions = portfolio.get_position_summary()
if not positions:
print("\nNo positions in portfolio")
else:
print("\nCurrent Portfolio:")
for pos in positions:
print(f"\nSymbol: {pos['symbol']}")
print(f"Entry Date: {pos['entry_date']}")
print(f"Entry Price: ${pos['entry_price']:.2f}")
print(f"Shares: {pos['shares']}")
print(f"Current Value: ${pos['current_value']:.2f}")
print(f"Stop Loss: ${pos['stop_loss']:.2f}")
print(f"Target: ${pos['target_price']:.2f}")
elif choice == "4":
symbol = input("Enter symbol to remove: ")
portfolio.remove_position(symbol)
print(f"\nRemoved position: {symbol}")
elif choice == "5":
print("\nExiting Trading Management System")
break
else:
print("\nInvalid choice. Please try again.")
if __name__ == "__main__":
main()

44
src/trading/portfolio.py Normal file
View File

@ -0,0 +1,44 @@
from typing import List, Dict
from dataclasses import dataclass
from datetime import datetime
@dataclass
class Position:
symbol: str
entry_date: datetime
entry_price: float
shares: int
stop_loss: float
target_price: float
@property
def current_value(self) -> float:
# TODO: Implement real-time price fetching
return self.shares * self.entry_price
class Portfolio:
def __init__(self):
self.positions: List[Position] = []
def add_position(self, position: Position):
"""Add a new position to the portfolio"""
self.positions.append(position)
def remove_position(self, symbol: str):
"""Remove a position from the portfolio by symbol"""
self.positions = [p for p in self.positions if p.symbol != symbol]
def get_position_summary(self) -> List[Dict]:
"""Get summary of all positions"""
return [
{
"symbol": p.symbol,
"entry_date": p.entry_date,
"entry_price": p.entry_price,
"shares": p.shares,
"current_value": p.current_value,
"stop_loss": p.stop_loss,
"target_price": p.target_price
}
for p in self.positions
]

View File

@ -0,0 +1,44 @@
class PositionCalculator:
def __init__(self, account_size: float, risk_percentage: float = 1.0):
"""
Initialize position calculator with account size and risk percentage
Args:
account_size (float): Total trading account value
risk_percentage (float): Maximum risk per trade as percentage (default 1%)
"""
self.account_size = account_size
self.risk_percentage = risk_percentage / 100.0 # Convert to decimal
def calculate_position_size(self, entry_price: float, stop_loss: float) -> dict:
"""
Calculate position size based on risk parameters
Args:
entry_price (float): Planned entry price
stop_loss (float): Stop loss price
Returns:
dict: Position details including shares and dollar amounts
"""
# Calculate risk amount in dollars
risk_amount = self.account_size * self.risk_percentage
# Calculate per-share risk
risk_per_share = abs(entry_price - stop_loss)
if risk_per_share == 0:
raise ValueError("Entry price cannot equal stop loss price")
# Calculate number of shares
shares = int(risk_amount / risk_per_share)
# Calculate total position value
position_value = shares * entry_price
return {
"shares": shares,
"position_value": position_value,
"risk_amount": risk_amount,
"risk_per_share": risk_per_share
}