-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathmodels.py
More file actions
180 lines (141 loc) · 3.88 KB
/
Copy pathmodels.py
File metadata and controls
180 lines (141 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
"""
Data models for Bank Nifty Scalping Bot.
Defines core data structures used throughout the application.
"""
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum, auto
from typing import Any, Dict, Optional
class Signal(Enum):
"""Trading signal types."""
BUY_CE = auto() # Buy Call Option
BUY_PE = auto() # Buy Put Option
EXIT = auto() # Exit current position
HOLD = auto() # No action
class OrderStatus(Enum):
"""Order status types."""
PENDING = "pending"
OPEN = "open"
FILLED = "filled"
PARTIALLY_FILLED = "partially_filled"
CANCELLED = "cancelled"
REJECTED = "rejected"
EXPIRED = "expired"
class OptionType(Enum):
"""Option contract types."""
CALL = "CALL"
PUT = "PUT"
@dataclass
class Tick:
"""Single market tick data."""
security_id: str
ltp: float
timestamp: datetime
volume: Optional[int] = None
oi: Optional[int] = None
bid: Optional[float] = None
ask: Optional[float] = None
@dataclass
class Candle:
"""OHLCV candle data."""
timestamp: datetime
open: float
high: float
low: float
close: float
volume: int = 0
def to_dict(self) -> Dict[str, Any]:
return {
"timestamp": self.timestamp,
"Open": self.open,
"High": self.high,
"Low": self.low,
"Close": self.close,
"Volume": self.volume,
}
@dataclass
class IndicatorValues:
"""Calculated indicator values for a candle."""
ema_9: float
rsi: float
vwap: float
close: float
timestamp: datetime
@dataclass
class OptionContract:
"""Option contract details."""
security_id: str
symbol: str
strike: float
option_type: OptionType
expiry: datetime
ltp: Optional[float] = None
oi: Optional[int] = None
iv: Optional[float] = None # Implied Volatility
@dataclass
class Position:
"""Open position details."""
security_id: str
symbol: str
option_type: OptionType
strike: float
quantity: int
entry_price: float
entry_time: datetime
order_id: str
stop_loss: float
target: float
current_price: Optional[float] = None
pnl: float = 0.0
def update_pnl(self, current_price: float) -> float:
"""Update and return current P&L."""
self.current_price = current_price
self.pnl = (current_price - self.entry_price) * self.quantity
return self.pnl
def should_exit_sl(self, current_price: float) -> bool:
"""Check if stop loss is hit."""
return current_price <= self.stop_loss
def should_exit_target(self, current_price: float) -> bool:
"""Check if target is hit."""
return current_price >= self.target
@dataclass
class OrderRequest:
"""Order request details."""
security_id: str
exchange_segment: str
transaction_type: str # BUY or SELL
quantity: int
order_type: str # LIMIT or MARKET
price: float
product_type: str # INTRA or CNC
validity: str = "DAY"
trigger_price: Optional[float] = None
disclosed_quantity: Optional[int] = None
correlation_id: Optional[str] = None
@dataclass
class OrderResponse:
"""Order response from API."""
order_id: str
status: OrderStatus
security_id: str
quantity: int
price: float
filled_quantity: int = 0
average_price: float = 0.0
message: Optional[str] = None
timestamp: datetime = field(default_factory=datetime.now)
@dataclass
class TradeStats:
"""Daily trading statistics."""
date: datetime
total_trades: int = 0
winning_trades: int = 0
losing_trades: int = 0
total_pnl: float = 0.0
max_drawdown: float = 0.0
orders_placed: int = 0
@property
def win_rate(self) -> float:
if self.total_trades == 0:
return 0.0
return (self.winning_trades / self.total_trades) * 100