|
| 1 | +import pandas as pd |
| 2 | +import numpy as np |
| 3 | +import matplotlib.pyplot as plt |
| 4 | + |
| 5 | +# Simulated historical price data (more data points) |
| 6 | +data = { |
| 7 | + 'Date': pd.date_range(start='2010-01-01', periods=1000), |
| 8 | + 'Open': np.random.uniform(100, 200, 1000), |
| 9 | + 'High': np.random.uniform(200, 250, 1000), |
| 10 | + 'Low': np.random.uniform(80, 150, 1000), |
| 11 | + 'Close': np.random.uniform(120, 180, 1000), |
| 12 | + 'Volume': np.random.randint(10000, 50000, 1000) |
| 13 | +} |
| 14 | + |
| 15 | +df = pd.DataFrame(data) |
| 16 | +df.set_index('Date', inplace=True) |
| 17 | + |
| 18 | +# Example trading strategy |
| 19 | +def simple_moving_average_strategy(data, short_window, long_window): |
| 20 | + signals = pd.DataFrame(index=data.index) |
| 21 | + signals['Signal'] = 0.0 |
| 22 | + |
| 23 | + signals['Short_MA'] = data['Close'].rolling(window=short_window, min_periods=1, center=False).mean() |
| 24 | + signals['Long_MA'] = data['Close'].rolling(window=long_window, min_periods=1, center=False).mean() |
| 25 | + |
| 26 | + signals['Signal'][short_window:] = np.where(signals['Short_MA'][short_window:] > signals['Long_MA'][short_window:], 1.0, 0.0) |
| 27 | + |
| 28 | + signals['Positions'] = signals['Signal'].diff() |
| 29 | + |
| 30 | + return signals |
| 31 | + |
| 32 | +# Define strategy parameters |
| 33 | +short_window = 10 |
| 34 | +long_window = 50 |
| 35 | + |
| 36 | +# Apply strategy |
| 37 | +signals = simple_moving_average_strategy(df, short_window, long_window) |
| 38 | + |
| 39 | +# Risk management parameters |
| 40 | +risk_per_trade = 0.02 # 2% risk per trade |
| 41 | +initial_portfolio_value = 100000 |
| 42 | + |
| 43 | +# Simulate trading |
| 44 | +position = 0 |
| 45 | +portfolio_value = [] |
| 46 | +for index, row in signals.iterrows(): |
| 47 | + if row['Positions'] == 1: |
| 48 | + max_position_size = (risk_per_trade * initial_portfolio_value) / (row['Close'] - row['Low']) |
| 49 | + position = min(max_position_size, initial_portfolio_value / row['Close']) |
| 50 | + initial_portfolio_value -= position * row['Close'] |
| 51 | + elif row['Positions'] == -1: |
| 52 | + initial_portfolio_value += position * row['Close'] |
| 53 | + position = 0 |
| 54 | + portfolio_value.append(initial_portfolio_value + position * row['Close']) |
| 55 | + |
| 56 | +signals['PortfolioValue'] = portfolio_value |
| 57 | + |
| 58 | +# Visualization improvements |
| 59 | +plt.figure(figsize=(12, 8)) |
| 60 | + |
| 61 | +plt.subplot(2, 1, 1) |
| 62 | +plt.plot(signals.index, signals['Close'], label='Close Price', alpha=0.5) |
| 63 | +plt.plot(signals.index, signals['Short_MA'], label=f'Short {short_window} MA') |
| 64 | +plt.plot(signals.index, signals['Long_MA'], label=f'Long {long_window} MA') |
| 65 | +plt.legend() |
| 66 | +plt.title('Price Data and Moving Averages') |
| 67 | + |
| 68 | +plt.subplot(2, 1, 2) |
| 69 | +plt.plot(signals.index, signals['PortfolioValue'], label='Portfolio Value', linestyle='--', color='green') |
| 70 | +plt.legend() |
| 71 | +plt.title('Portfolio Value') |
| 72 | + |
| 73 | +plt.tight_layout() |
| 74 | +plt.show() |
0 commit comments