feat: Add trading app with position calculator and portfolio management
This commit is contained in:
parent
8302d796e0
commit
b7d3b8bc6d
87
src/trading/main.py
Normal file
87
src/trading/main.py
Normal 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
44
src/trading/portfolio.py
Normal 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
|
||||
]
|
||||
44
src/trading/position_calculator.py
Normal file
44
src/trading/position_calculator.py
Normal 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
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user