Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sreenivasdoosa
GitHub Repository: sreenivasdoosa/sdoosa-algo-trade-python
Path: blob/master/src/strategies/BNFORB30Min.py
301 views
1
import logging
2
from datetime import datetime
3
4
from instruments.Instruments import Instruments
5
from models.Direction import Direction
6
from models.ProductType import ProductType
7
from strategies.BaseStrategy import BaseStrategy
8
from utils.Utils import Utils
9
from trademgmt.Trade import Trade
10
from trademgmt.TradeManager import TradeManager
11
12
# Each strategy has to be derived from BaseStrategy
13
class BNFORB30Min(BaseStrategy):
14
__instance = None
15
16
@staticmethod
17
def getInstance(): # singleton class
18
if BNFORB30Min.__instance == None:
19
BNFORB30Min()
20
return BNFORB30Min.__instance
21
22
def __init__(self):
23
if BNFORB30Min.__instance != None:
24
raise Exception("This class is a singleton!")
25
else:
26
BNFORB30Min.__instance = self
27
# Call Base class constructor
28
super().__init__("BNFORB30Min")
29
# Initialize all the properties specific to this strategy
30
self.productType = ProductType.MIS
31
self.symbols = []
32
self.slPercentage = 0
33
self.targetPercentage = 0
34
self.startTimestamp = Utils.getTimeOfToDay(9, 45, 0) # When to start the strategy. Default is Market start time
35
self.stopTimestamp = Utils.getTimeOfToDay(14, 30, 0) # This is not square off timestamp. This is the timestamp after which no new trades will be placed under this strategy but existing trades continue to be active.
36
self.squareOffTimestamp = Utils.getTimeOfToDay(15, 0, 0) # Square off time
37
self.capital = 100000 # Capital to trade (This is the margin you allocate from your broker account for this strategy)
38
self.leverage = 0
39
self.maxTradesPerDay = 1 # Max number of trades per day under this strategy
40
self.isFnO = True # Does this strategy trade in FnO or not
41
self.capitalPerSet = 100000 # Applicable if isFnO is True (1 set means 1CE/1PE or 2CE/2PE etc based on your strategy logic)
42
43
def process(self):
44
now = datetime.now()
45
processEndTime = Utils.getTimeOfToDay(9, 50, 0)
46
if now < self.startTimestamp:
47
return
48
if now > processEndTime:
49
# We are interested in creating the symbol only between 09:45 and 09:50
50
# since we are not using historical candles so not aware of exact high and low of the first 30 mins
51
return
52
53
if len(self.trades) >= 2:
54
return
55
56
symbol = Utils.prepareMonthlyExpiryFuturesSymbol('BANKNIFTY')
57
quote = self.getQuote(symbol)
58
if quote == None:
59
logging.error('%s: Could not get quote for %s', self.getName(), symbol)
60
return
61
62
logging.info('%s: %s => lastTradedPrice = %f', self.getName(), symbol, quote.lastTradedPrice)
63
self.generateTrade(symbol, Direction.LONG, quote.high, quote.low)
64
self.generateTrade(symbol, Direction.SHORT, quote.high, quote.low)
65
66
67
def generateTrade(self, tradingSymbol, direction, high, low):
68
trade = Trade(tradingSymbol)
69
trade.strategy = self.getName()
70
trade.isFutures = True
71
trade.direction = direction
72
trade.productType = self.productType
73
trade.placeMarketOrder = True
74
trade.requestedEntry = high if direction == Direction.LONG else low
75
trade.timestamp = Utils.getEpoch(self.startTimestamp) # setting this to strategy timestamp
76
# Calculate lots
77
numLots = self.calculateLotsPerTrade()
78
isd = Instruments.getInstrumentDataBySymbol(tradingSymbol) # Get instrument data to know qty per lot
79
trade.qty = isd['lot_size'] * numLots
80
81
trade.stopLoss = low if direction == Direction.LONG else high
82
slDiff = high - low
83
# target is 1.5 times of SL
84
if direction == 'LONG':
85
trade.target = Utils.roundToNSEPrice(trade.requestedEntry + 1.5 * slDiff)
86
else:
87
trade.target = Utils.roundToNSEPrice(trade.requestedEntry - 1.5 * slDiff)
88
89
trade.intradaySquareOffTimestamp = Utils.getEpoch(self.squareOffTimestamp)
90
# Hand over the trade to TradeManager
91
TradeManager.addNewTrade(trade)
92
93
def shouldPlaceTrade(self, trade, tick):
94
# First call base class implementation and if it returns True then only proceed
95
if super().shouldPlaceTrade(trade, tick) == False:
96
return False
97
98
if tick == None:
99
return False
100
101
if trade.direction == Direction.LONG and tick.lastTradedPrice > trade.requestedEntry:
102
return True
103
elif trade.direction == Direction.SHORT and tick.lastTradedPrice < trade.requestedEntry:
104
return True
105
return False
106
107