diff --git a/components/lib/ExpiryTypeComponent.tsx b/components/lib/ExpiryTypeComponent.tsx
new file mode 100644
index 00000000..87d139e1
--- /dev/null
+++ b/components/lib/ExpiryTypeComponent.tsx
@@ -0,0 +1,50 @@
+import React from 'react'
+import {
+ FormControl,
+ FormControlLabel,
+ Typography,
+ FormLabel,
+ RadioGroup,
+ Radio,
+ Grid
+} from '@material-ui/core'
+import { EXPIRY_TYPE, EXPIRY_TYPE_HUMAN } from '../../lib/constants'
+
+const ExpiryTypeComponent = ({ state, onChange }) => {
+ const expiryTypes = [
+ EXPIRY_TYPE.CURRENT,
+ EXPIRY_TYPE.NEXT,
+ EXPIRY_TYPE.MONTHLY
+ ]
+ return (
+
+
+ Option Expiry
+
+ onChange({ expiryType: e.target.value as EXPIRY_TYPE })
+ }
+ row
+ >
+ {expiryTypes.map(expiryType => (
+ }
+ label={
+
+ {EXPIRY_TYPE_HUMAN[expiryType]}
+
+ }
+ />
+ ))}
+
+
+
+ )
+}
+
+export default ExpiryTypeComponent
diff --git a/components/lib/commonDetailsRows.tsx b/components/lib/commonDetailsRows.tsx
index a9ec44d8..4f213a07 100644
--- a/components/lib/commonDetailsRows.tsx
+++ b/components/lib/commonDetailsRows.tsx
@@ -20,7 +20,8 @@ const CommonDetailsRows = ({
volatilityType,
liveTrailingSl,
lastTrailingSlSetAt,
- lastHeartbeatAt
+ lastHeartbeatAt,
+ expiryType
}) => {
const getAlgoStatus = useCallback(
() =>
@@ -55,6 +56,8 @@ const CommonDetailsRows = ({
return [
volatilityType ? [{ value: 'Vol type' }, { value: volatilityType }] : null,
productType ? [{ value: 'Product' }, { value: productType }] : null,
+ expiryType ? [{ value: 'Expiry' }, { value: expiryType }] : null,
+
[
{ value: 'Exit Strategy' },
{ value: EXIT_STRATEGIES_DETAILS[exitStrategy].label }
diff --git a/components/trades/atmStraddle/TradeSetupForm.tsx b/components/trades/atmStraddle/TradeSetupForm.tsx
index d4411ac8..39d98733 100644
--- a/components/trades/atmStraddle/TradeSetupForm.tsx
+++ b/components/trades/atmStraddle/TradeSetupForm.tsx
@@ -34,6 +34,7 @@ import ProductTypeComponent from '../../lib/ProductTypeComponent'
import VolatilityTypeComponent from '../../lib/VolatilityTypeComponent'
import RollbackComponent from '../../lib/RollbackComponent'
import SlManagerComponent from '../../lib/SlManagerComponent'
+import ExpiryTypeComponent from '../../lib/ExpiryTypeComponent'
interface ATMStraddleTradeSetupFormProps {
formHeading?: string
@@ -113,6 +114,8 @@ const TradeSetupForm = ({
+
+
+
+
Entry strategy
diff --git a/components/trades/directionalOptionSelling/TradeSetupForm.tsx b/components/trades/directionalOptionSelling/TradeSetupForm.tsx
index f13ef2be..156acac3 100644
--- a/components/trades/directionalOptionSelling/TradeSetupForm.tsx
+++ b/components/trades/directionalOptionSelling/TradeSetupForm.tsx
@@ -38,6 +38,7 @@ import HedgeComponent from '../../lib/HedgeComponent'
import RollbackComponent from '../../lib/RollbackComponent'
import ProductTypeComponent from '../../lib/ProductTypeComponent'
import SlManagerComponent from '../../lib/SlManagerComponent'
+import ExpiryTypeComponent from '../../lib/ExpiryTypeComponent'
interface DOSTradeSetupFormProps {
state: Partial
@@ -114,6 +115,8 @@ const TradeSetupForm = ({
+
+
= {
[INSTRUMENTS.NIFTY]: {
lotSize: 50,
@@ -86,6 +101,18 @@ export enum VOLATILITY_TYPE {
SHORT = 'SHORT'
}
+export enum EXPIRY_TYPE {
+ CURRENT = 'CURRENT',
+ NEXT = 'NEXT',
+ MONTHLY = 'MONTHLY'
+}
+
+export const EXPIRY_TYPE_HUMAN = {
+ [EXPIRY_TYPE.CURRENT]: 'Current weekly',
+ [EXPIRY_TYPE.NEXT]: 'Next weekly',
+ [EXPIRY_TYPE.MONTHLY]: 'Current Monthly'
+}
+
export enum STRANGLE_ENTRY_STRATEGIES {
DISTANCE_FROM_ATM = 'DISTANCE_FROM_ATM',
DELTA_STIKES = 'DELTA_STIKES'
@@ -136,6 +163,7 @@ export const STRATEGIES_DETAILS = {
trailingSlPercent: NEXT_PUBLIC_DEFAULT_SLM_PERCENT,
productType: PRODUCT_TYPE.MIS,
volatilityType: VOLATILITY_TYPE.SHORT,
+ expiryType: EXPIRY_TYPE.CURRENT,
runNow: false,
expireIfUnsuccessfulInMins: 10,
exitStrategy: EXIT_STRATEGIES.INDIVIDUAL_LEG_SLM_1X,
@@ -173,6 +201,7 @@ export const STRATEGIES_DETAILS = {
deltaStrikes: 20,
productType: PRODUCT_TYPE.MIS,
volatilityType: VOLATILITY_TYPE.SHORT,
+ expiryType: EXPIRY_TYPE.CURRENT,
runNow: false,
exitStrategy: EXIT_STRATEGIES.INDIVIDUAL_LEG_SLM_1X,
slOrderType: SL_ORDER_TYPE.SLL,
@@ -214,6 +243,7 @@ export const STRATEGIES_DETAILS = {
martingaleIncrementSize: 1,
isHedgeEnabled: true,
productType: PRODUCT_TYPE.MIS,
+ expiryType: EXPIRY_TYPE.CURRENT,
hedgeDistance: 2000,
entryStrategy: DOS_ENTRY_STRATEGIES.FIXED_TIME,
exitStrategy: EXIT_STRATEGIES.MIN_XPERCENT_OR_SUPERTREND,
diff --git a/lib/queue-processor/optionSellerStrategy/optionEntryWatcher.js b/lib/queue-processor/optionSellerStrategy/optionEntryWatcher.js
index cfe5f22a..6051c2c9 100644
--- a/lib/queue-processor/optionSellerStrategy/optionEntryWatcher.js
+++ b/lib/queue-processor/optionSellerStrategy/optionEntryWatcher.js
@@ -18,7 +18,7 @@ const optionSellerEntryWatcher = async ({
addHedge
}) => {
try {
- const { user, orderTag, instrument } = initialJobData
+ const { user, orderTag, instrument, expiryType } = initialJobData
const kite = syncGetKiteInstance(user)
const orderHistory = await kite.getOrderHistory(limitOrderAckId)
const revOrderHistory = orderHistory.reverse()
@@ -81,7 +81,8 @@ const optionSellerEntryWatcher = async ({
completedOrder.tradingsymbol.length - 2,
completedOrder.tradingsymbol.length - 1
),
- user
+ user,
+ expiry: expiryType
})
const hedgeOrder = {
diff --git a/lib/queue-processor/tradingQueue.ts b/lib/queue-processor/tradingQueue.ts
index eeed26f2..381e6539 100644
--- a/lib/queue-processor/tradingQueue.ts
+++ b/lib/queue-processor/tradingQueue.ts
@@ -21,6 +21,7 @@ async function processJob (job: Job) {
data,
data: { strategy }
} = job
+ console.log(`[job processing] Beginning job processing for ${strategy}`)
switch (strategy) {
case STRATEGIES.ATM_STRADDLE: {
return atmStraddle(data)
diff --git a/lib/session.ts b/lib/session.ts
index c26edfd8..e3bf1254 100644
--- a/lib/session.ts
+++ b/lib/session.ts
@@ -1,13 +1,70 @@
// this file is a wrapper with defaults to be used in both API routes and `getServerSideProps` functions
import { withIronSession } from 'next-iron-session'
+import { KiteConnect } from 'kiteconnect'
// NB: not the best place to require these
// ideally these should live in their own file that gets included as a middleware
import './queue-processor'
import './exit-strategies'
import './watchers'
+import { setUserSession, premiumAuthCheck } from './utils'
+import { KiteProfile } from '../types/kite'
+
+const withAdminCheck = handler => {
+ return async function withAdminWrapper (req, res) {
+ const sxApiKey = req.headers['signalx-api-key']
+ const kiteApiKey = req.headers['signalx-kite-key']
+ const kiteAccessToken = req.headers['signalx-kite-token']
+
+ if (!sxApiKey && !kiteApiKey) {
+ // UI based flow
+ return handler(req, res)
+ }
+
+ // for premium and club users
+ let validSxUser = false
+ try {
+ validSxUser = await premiumAuthCheck()
+ } catch (e) {
+ validSxUser = false
+ }
+
+ // block intrusion
+ if (!validSxUser) {
+ return handler(req, res)
+ }
+
+ if (!kiteAccessToken) {
+ // sx admin work, no broker authorization
+ await setUserSession(req, {} as KiteProfile)
+ } else {
+ console.log(
+ 'key and token found in headers. attempting to connect kite and save session'
+ )
+ try {
+ const kc = new KiteConnect({
+ api_key: kiteApiKey,
+ access_token: kiteAccessToken
+ })
+
+ const kiteProfile = await kc.getProfile()
+ await setUserSession(req, {
+ access_token: kiteAccessToken,
+ ...kiteProfile
+ })
+ console.log('session generated from headers')
+ return handler(req, res)
+ } catch (error) {
+ console.log(error)
+ return res
+ .status(403)
+ .send('Forbidden. Unauthorized key or token provided')
+ }
+ }
+ }
+}
export default function withSession (handler) {
- return withIronSession(handler, {
+ return withIronSession(withAdminCheck(handler), {
password: process.env.SECRET_COOKIE_PASSWORD!,
cookieName: 'khaching/kite/session',
cookieOptions: {
diff --git a/lib/strategies/atmStraddle.ts b/lib/strategies/atmStraddle.ts
index 294806e4..1fb39ebe 100644
--- a/lib/strategies/atmStraddle.ts
+++ b/lib/strategies/atmStraddle.ts
@@ -4,6 +4,7 @@ import { SignalXUser } from '../../types/misc'
import { ATM_STRADDLE_TRADE } from '../../types/trade'
import {
+ EXPIRY_TYPE,
INSTRUMENT_DETAILS,
INSTRUMENT_PROPERTIES,
PRODUCT_TYPE,
@@ -16,7 +17,7 @@ import {
attemptBrokerOrders,
delay,
ensureMarginForBasketOrder,
- getCurrentExpiryTradingSymbol,
+ getExpiryTradingSymbol,
getHedgeForStrike,
getIndexInstruments,
getInstrumentPrice,
@@ -58,6 +59,7 @@ export async function getATMStraddle (
thresholdSkewPercent,
takeTradeIrrespectiveSkew,
expiresAt,
+ expiryType,
attempt = 0
} = args
try {
@@ -98,11 +100,12 @@ export async function getATMStraddle (
const atmStrike =
Math.round(underlyingLTP / strikeStepSize!) * strikeStepSize!
- const { PE_STRING, CE_STRING } = (await getCurrentExpiryTradingSymbol({
+ const { PE_STRING, CE_STRING } = (await getExpiryTradingSymbol({
nfoSymbol,
- strike: atmStrike
+ strike: atmStrike,
+ expiry: expiryType
})) as StrikeInterface
-
+ console.log(`Expiry ${expiryType} strikes: ${PE_STRING} & ${CE_STRING}`)
// if time has expired
if (timeExpired) {
console.log(
@@ -205,6 +208,7 @@ async function atmStraddle ({
hedgeDistance,
productType = PRODUCT_TYPE.MIS,
volatilityType = VOLATILITY_TYPE.SHORT,
+ expiryType = EXPIRY_TYPE.CURRENT,
_nextTradingQueue = EXIT_TRADING_Q_NAME
}: ATM_STRADDLE_TRADE): Promise<
| {
@@ -240,7 +244,8 @@ async function atmStraddle ({
maxSkewPercent,
thresholdSkewPercent,
takeTradeIrrespectiveSkew,
- expiresAt
+ expiresAt,
+ expiryType
})
const { PE_STRING, CE_STRING, atmStrike } = straddle
@@ -256,7 +261,8 @@ async function atmStraddle ({
strike: atmStrike,
distance: hedgeDistance!,
type,
- nfoSymbol
+ nfoSymbol,
+ expiryType
})
)
)
diff --git a/lib/strategies/directionalOptionSelling.ts b/lib/strategies/directionalOptionSelling.ts
index 851fecce..d0089e61 100644
--- a/lib/strategies/directionalOptionSelling.ts
+++ b/lib/strategies/directionalOptionSelling.ts
@@ -20,8 +20,8 @@ import {
TRADING_Q_NAME
} from '../queue'
import {
+ getExpiryTradingSymbol,
attemptBrokerOrders,
- getCurrentExpiryTradingSymbol,
getInstrumentPrice,
getLastOpenDateSince,
getNearestCandleTime,
@@ -94,7 +94,8 @@ export default async function directionalOptionSelling (
.ENTRY_STRATEGIES.FIXED_TIME,
lastTrend,
lastTradeOrders,
- user
+ user,
+ expiryType
} = initialJobData
if (getTimeLeftInMarketClosingMs() < 40 * 60 * 1000) {
@@ -105,9 +106,10 @@ export default async function directionalOptionSelling (
const {
instrument_token: futInstrumentToken
- } = (await getCurrentExpiryTradingSymbol({
+ } = (await getExpiryTradingSymbol({
nfoSymbol,
- instrumentType: 'FUT'
+ instrumentType: 'FUT',
+ expiry: expiryType
})) as TradingSymbolInterface
const DATE_FORMAT = 'YYYY-MM-DD'
@@ -249,7 +251,8 @@ async function punchOrders (
rollback,
productType = PRODUCT_TYPE.MIS,
isHedgeEnabled = false,
- hedgeDistance = 1700
+ hedgeDistance = 1700,
+ expiryType
} = initialJobData
const strikeByPriceNumber = strikeByPrice ? Number(strikeByPrice) : null
const kite = _kite || syncGetKiteInstance(user)
@@ -271,13 +274,15 @@ async function punchOrders (
price: strikeByPriceNumber,
pivotStrike: atmStrike,
instrumentType,
- user: user!
+ user: user!,
+ expiry: expiryType
})
)
- : await getCurrentExpiryTradingSymbol({
+ : await getExpiryTradingSymbol({
nfoSymbol,
strike: superTrendStrike,
- instrumentType
+ instrumentType,
+ expiry: expiryType
})
const ltp = await withRemoteRetry(async () =>
@@ -297,10 +302,11 @@ async function punchOrders (
Number(optionStrike) +
Number(hedgeDistance) * (instrumentType === 'PE' ? -1 : 1)
- const hedgeStrikeData = (await getCurrentExpiryTradingSymbol({
+ const hedgeStrikeData = (await getExpiryTradingSymbol({
nfoSymbol,
strike: hedgeStrike,
- instrumentType
+ instrumentType,
+ expiry: expiryType
})) as TradingSymbolInterface
if (hedgeStrikeData) {
diff --git a/lib/strategies/optionSellerStrategy.js b/lib/strategies/optionSellerStrategy.js
index e30951d8..1e196082 100644
--- a/lib/strategies/optionSellerStrategy.js
+++ b/lib/strategies/optionSellerStrategy.js
@@ -15,6 +15,7 @@ import {
import {
delay,
getCurrentExpiryTradingSymbol,
+ getExpiryTradingSymbol,
getIndexInstruments,
getInstrumentPrice,
getLastOpenDateSince,
@@ -56,7 +57,7 @@ export const fetchHistoricalPrice = async instrumentToken => {
export default async initialJobData => {
try {
- const { instrument } = initialJobData
+ const { instrument, expiryType } = initialJobData
const { underlyingSymbol, strikeStepSize, nfoSymbol } = INSTRUMENT_DETAILS[
instrument
@@ -85,18 +86,20 @@ export default async initialJobData => {
const nfoInstruments = await getIndexInstruments('NFO')
- const callStrike = getCurrentExpiryTradingSymbol({
+ const callStrike = await getExpiryTradingSymbol({
sourceData: nfoInstruments,
nfoSymbol,
strike: callOptionStrike,
- instrumentType: 'CE'
+ instrumentType: 'CE',
+ expiry: expiryType
})
- const putStrike = getCurrentExpiryTradingSymbol({
+ const putStrike = await getExpiryTradingSymbol({
sourceData: nfoInstruments,
nfoSymbol,
strike: putOptionStrike,
- instrumentType: 'PE'
+ instrumentType: 'PE',
+ expiry: expiryType
})
// return {
diff --git a/lib/strategies/strangle.ts b/lib/strategies/strangle.ts
index 32e04dd7..dbdcf680 100644
--- a/lib/strategies/strangle.ts
+++ b/lib/strategies/strangle.ts
@@ -1,6 +1,7 @@
import { ATM_STRANGLE_TRADE } from '../../types/trade'
import {
ERROR_STRINGS,
+ EXPIRY_TYPE,
INSTRUMENTS,
INSTRUMENT_DETAILS,
PRODUCT_TYPE,
@@ -13,7 +14,7 @@ import {
apiResponseObject,
attemptBrokerOrders,
ensureMarginForBasketOrder,
- getCurrentExpiryTradingSymbol,
+ getExpiryTradingSymbol,
getHedgeForStrike,
getIndexInstruments,
getStrikeByDelta,
@@ -54,7 +55,8 @@ const getStrangleStrikes = async ({
inverted = false,
entryStrategy,
distanceFromAtm = 1,
- deltaStrikes
+ deltaStrikes,
+ expiryType
}: {
atmStrike: number
instrument: INSTRUMENTS
@@ -62,6 +64,7 @@ const getStrangleStrikes = async ({
entryStrategy: STRANGLE_ENTRY_STRATEGIES
distanceFromAtm?: number
deltaStrikes?: number
+ expiryType?: EXPIRY_TYPE
}) => {
const { nfoSymbol, strikeStepSize } = INSTRUMENT_DETAILS[instrument]
@@ -106,21 +109,21 @@ const getStrangleStrikes = async ({
higherLegCEStrike = atmStrike + distanceFromAtm * strikeStepSize
}
- const {
- tradingsymbol: LOWER_LEG_PE_STRING
- } = (await getCurrentExpiryTradingSymbol({
+ const { tradingsymbol: LOWER_LEG_PE_STRING } = (await getExpiryTradingSymbol({
nfoSymbol,
strike: lowerLegPEStrike,
- instrumentType: 'PE'
+ instrumentType: 'PE',
+ expiry: expiryType
})) as TradingSymbolInterface
- const {
- tradingsymbol: HIGHER_LEG_CE_STRING
- } = (await getCurrentExpiryTradingSymbol({
- nfoSymbol,
- strike: higherLegCEStrike,
- instrumentType: 'CE'
- })) as TradingSymbolInterface
+ const { tradingsymbol: HIGHER_LEG_CE_STRING } = (await getExpiryTradingSymbol(
+ {
+ nfoSymbol,
+ strike: higherLegCEStrike,
+ instrumentType: 'CE',
+ expiry: expiryType
+ }
+ )) as TradingSymbolInterface
const PE_STRING = !inverted
? LOWER_LEG_PE_STRING
@@ -153,6 +156,7 @@ async function atmStrangle (args: ATM_STRANGLE_TRADE) {
distanceFromAtm = 1,
productType = PRODUCT_TYPE.MIS,
volatilityType = VOLATILITY_TYPE.SHORT,
+ expiryType,
_nextTradingQueue = EXIT_TRADING_Q_NAME
} = args
const {
@@ -176,7 +180,8 @@ async function atmStrangle (args: ATM_STRANGLE_TRADE) {
underlyingSymbol,
exchange,
nfoSymbol,
- strikeStepSize
+ strikeStepSize,
+ expiryType
} as any)
const {
@@ -190,7 +195,8 @@ async function atmStrangle (args: ATM_STRANGLE_TRADE) {
inverted,
distanceFromAtm,
entryStrategy,
- deltaStrikes
+ deltaStrikes,
+ expiryType
})
const kite = syncGetKiteInstance(user)
@@ -210,7 +216,8 @@ async function atmStrangle (args: ATM_STRANGLE_TRADE) {
strike,
distance: hedgeDistance!,
type,
- nfoSymbol
+ nfoSymbol,
+ expiryType
})
)
)
diff --git a/lib/utils.ts b/lib/utils.ts
index 919778d7..820fd098 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -8,8 +8,10 @@ import { allSettled, allSettledInterface } from './es6-promise'
import {
ERROR_STRINGS,
EXIT_STRATEGIES,
+ EXPIRY_TYPE,
INSTRUMENTS,
INSTRUMENT_DETAILS,
+ KITE_INSTRUMENT_INFO,
STRATEGIES,
USER_OVERRIDE
} from './constants'
@@ -17,7 +19,7 @@ import {
// export const memoizer = require('redis-memoizer')(redisClient);
import { COMPLETED_ORDER_RESPONSE } from './strategies/mockData/orderResponse'
import { SignalXUser } from '../types/misc'
-import { KiteOrder } from '../types/kite'
+import { KiteOrder, KiteProfile } from '../types/kite'
Promise.config({ cancellation: true, warnings: true })
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
@@ -41,7 +43,9 @@ export const logDeep = object => console.log(JSON.stringify(object, null, 2))
export const ms = seconds => seconds * 1000
-const asyncGetIndexInstruments = (exchange = 'NFO') =>
+const asyncGetIndexInstruments = (
+ exchange = 'NFO'
+): Promise =>
new Promise((resolve, reject) => {
const filename = `instrument_${new Date().getTime()}.csv`
const file = fs.createWriteStream(filename)
@@ -104,17 +108,13 @@ export const getMisOrderLastSquareOffTime = () =>
.set('seconds', 0)
.format()
-export interface TradingSymbolInterface {
- tradingsymbol: string
- instrument_token: string
- strike: string
-}
+export type TradingSymbolInterface = KITE_INSTRUMENT_INFO
export interface StrikeInterface {
PE_STRING: string
CE_STRING: string
}
-export const getCurrentExpiryTradingSymbol = async ({
+const getSortedMatchingIntrumentsData = async ({
nfoSymbol,
strike,
instrumentType,
@@ -124,9 +124,9 @@ export const getCurrentExpiryTradingSymbol = async ({
strike?: number
instrumentType?: string
tradingsymbol?: string
-}): Promise => {
+}): Promise => {
const instrumentsData = await getIndexInstruments()
- const rows = instrumentsData
+ const rows: KITE_INSTRUMENT_INFO[] = instrumentsData
.filter(
item =>
(nfoSymbol ? item.name === nfoSymbol : true) &&
@@ -137,17 +137,172 @@ export const getCurrentExpiryTradingSymbol = async ({
.sort((row1, row2) =>
dayjs(row1.expiry).isSameOrBefore(dayjs(row2.expiry)) ? -1 : 1
)
+ return rows
+}
+
+export const getExpiryTradingSymbol = async ({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol,
+ expiry = EXPIRY_TYPE.CURRENT
+}: {
+ nfoSymbol?: string
+ strike?: number
+ instrumentType?: string
+ tradingsymbol?: string
+ expiry?: EXPIRY_TYPE
+}): Promise => {
+ console.log('Fetching trading symbol for expiry type: ', expiry)
+ switch (expiry) {
+ case EXPIRY_TYPE.MONTHLY:
+ return getMonthlyExpiryTradingSymbol({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+ })
+
+ case EXPIRY_TYPE.NEXT:
+ return getNextExpiryTradingSymbol({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+ })
+
+ default:
+ return getCurrentExpiryTradingSymbol({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+ })
+ }
+}
+
+export const getCurrentExpiryTradingSymbol = async ({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+}: {
+ nfoSymbol?: string
+ strike?: number
+ instrumentType?: string
+ tradingsymbol?: string
+}): Promise => {
+ const rows = await getSortedMatchingIntrumentsData({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+ })
if (instrumentType) {
return rows.length ? rows[0] : null
}
-
+ // get first two entries for current expiry
const relevantRows = rows.slice(0, 2)
- const peStrike = relevantRows.find(item => item.instrument_type === 'PE')
- .tradingsymbol
- const ceStrike = relevantRows.find(item => item.instrument_type === 'CE')
- .tradingsymbol
+ const peStrike = relevantRows?.find(item => item.instrument_type === 'PE')
+ ?.tradingsymbol
+ const ceStrike = relevantRows?.find(item => item.instrument_type === 'CE')
+ ?.tradingsymbol
+
+ if (!peStrike || !ceStrike) return null
+
+ return {
+ PE_STRING: peStrike,
+ CE_STRING: ceStrike
+ }
+}
+
+export const getNextExpiryTradingSymbol = async ({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+}: {
+ nfoSymbol?: string
+ strike?: number
+ instrumentType?: string
+ tradingsymbol?: string
+}): Promise => {
+ const rows = await getSortedMatchingIntrumentsData({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+ })
+
+ if (instrumentType) {
+ return rows.length ? rows[1] : null
+ }
+ // first two entries are CE and PE for current week. So taking the next two items here
+ const relevantRows = rows.slice(2, 4)
+
+ const peStrike = relevantRows?.find(item => item.instrument_type === 'PE')
+ ?.tradingsymbol
+ const ceStrike = relevantRows?.find(item => item.instrument_type === 'CE')
+ ?.tradingsymbol
+
+ if (!peStrike || !ceStrike) return null
+
+ return {
+ PE_STRING: peStrike,
+ CE_STRING: ceStrike
+ }
+}
+
+export const getMonthlyExpiryTradingSymbol = async ({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+}: {
+ nfoSymbol?: string
+ strike?: number
+ instrumentType?: string
+ tradingsymbol?: string
+}): Promise => {
+ const instrumentsData = await getSortedMatchingIntrumentsData({
+ nfoSymbol,
+ strike,
+ instrumentType,
+ tradingsymbol
+ })
+
+ // get current calendar month expiries
+ let rows = instrumentsData.filter(
+ item => dayjs().get('month') === dayjs(item.expiry).get('month')
+ )
+
+ // // get next calendar month expiries
+ if (!rows.length) {
+ const month = dayjs().get('month') === 11 ? 0 : dayjs().get('month') // to handle December current year & Jan next year cases
+ rows = instrumentsData.filter(
+ item => dayjs(item.expiry).get('month') === month
+ )
+ }
+ rows = rows.sort((row1, row2) =>
+ dayjs(row1.expiry).isSameOrBefore(dayjs(row2.expiry)) ? -1 : 1
+ )
+
+ const rowsLength = rows.length
+
+ if (instrumentType) {
+ return rows.length ? rows[rowsLength - 1] : null
+ }
+ // get last two entries for monthly expiry
+ const relevantRows = rows.slice(rowsLength - 2, rowsLength)
+
+ const peStrike = relevantRows?.find(item => item.instrument_type === 'PE')
+ ?.tradingsymbol
+ const ceStrike = relevantRows?.find(item => item.instrument_type === 'CE')
+ ?.tradingsymbol
+
+ if (!peStrike || !ceStrike) return null
return {
PE_STRING: peStrike,
@@ -559,6 +714,7 @@ interface TRADING_SYMBOL_BY_OPTION_PRICE_TYPE {
pivotStrike: number
user: SignalXUser
greaterThanEqualToPrice?: boolean
+ expiry?: EXPIRY_TYPE
}
interface GET_LTP_ARGS {
@@ -621,7 +777,8 @@ export const getTradingSymbolsByOptionPrice = async ({
instrumentType,
pivotStrike,
user,
- greaterThanEqualToPrice = false
+ greaterThanEqualToPrice = false,
+ expiry = EXPIRY_TYPE.CURRENT
}: TRADING_SYMBOL_BY_OPTION_PRICE_TYPE) => {
const kite = syncGetKiteInstance(user)
const totalStrikes = 31 // pivot and 15 on each side
@@ -638,10 +795,11 @@ export const getTradingSymbolsByOptionPrice = async ({
.sort((a, b) => a - b)
const instruments = await Promise.map(strikes, async strike => {
- const { tradingsymbol } = (await getCurrentExpiryTradingSymbol({
+ const { tradingsymbol } = (await getExpiryTradingSymbol({
nfoSymbol,
strike,
- instrumentType
+ instrumentType,
+ expiry
})) as TradingSymbolInterface
return {
@@ -1166,19 +1324,22 @@ export const getHedgeForStrike = async ({
strike,
distance,
type,
- nfoSymbol
+ nfoSymbol,
+ expiryType = EXPIRY_TYPE.CURRENT
}: {
strike: number
distance: number
type: string
nfoSymbol: string
+ expiryType: EXPIRY_TYPE
}): Promise => {
const hedgeStrike = strike + distance * (type === 'PE' ? -1 : 1)
- const { tradingsymbol } = (await getCurrentExpiryTradingSymbol({
+ const { tradingsymbol } = (await getExpiryTradingSymbol({
nfoSymbol,
strike: hedgeStrike,
- instrumentType: type
+ instrumentType: type,
+ expiry: expiryType
})) as TradingSymbolInterface
return tradingsymbol
@@ -1220,6 +1381,19 @@ export const getStrikeByDelta = (
}
}
+export const setUserSession = async (
+ req,
+ userData: KiteProfile
+): Promise => {
+ const user: SignalXUser = {
+ isLoggedIn: true,
+ session: userData
+ }
+ req.session.set('user', user)
+ await req.session.save()
+ return user
+}
+
export function round (value: number, step = 0.5): number {
const inv = 1.0 / step
return Math.round(value * inv) / inv
diff --git a/pages/api/get_orders.js b/pages/api/get_orders.js
index 7c910855..0a35f547 100644
--- a/pages/api/get_orders.js
+++ b/pages/api/get_orders.js
@@ -47,34 +47,34 @@ export default withSession(async (req, res) => {
: -1
)
- const getHumanTradingSymbol = async ({ tradingsymbol }) => {
- const instrumentType = tradingsymbol.substr(tradingsymbol.length - 2, 2)
- const expiryData = await getCurrentExpiryTradingSymbol({
- tradingsymbol,
- instrumentType
- })
- if (!expiryData) {
- return null
- }
- const { expiry, name, strike } = expiryData
- const dateString = dayjs(expiry)
- .format('Do MMM')
- .split(' ')
- .map((str, idx) => (idx === 1 ? str.toUpperCase() : str))
- .join(' ')
- return `${name} ${dateString} ${strike} ${instrumentType}`
- }
+ // const getHumanTradingSymbol = async ({ tradingsymbol }) => {
+ // const instrumentType = tradingsymbol.substr(tradingsymbol.length - 2, 2)
+ // const expiryData = await getCurrentExpiryTradingSymbol({
+ // tradingsymbol,
+ // instrumentType
+ // })
+ // if (!expiryData) {
+ // return null
+ // }
+ // const { expiry, name, strike } = expiryData
+ // const dateString = dayjs(expiry)
+ // .format('Do MMM')
+ // .split(' ')
+ // .map((str, idx) => (idx === 1 ? str.toUpperCase() : str))
+ // .join(' ')
+ // return `${name} ${dateString} ${strike} ${instrumentType}`
+ // }
- const humanOrders = await Promise.map(orders, async order => {
- return {
- ...order,
- humanTradingSymbol: await getHumanTradingSymbol({
- tradingsymbol: order.tradingsymbol
- })
- }
- })
+ // const humanOrders = await Promise.map(orders, async order => {
+ // return {
+ // ...order,
+ // humanTradingSymbol: await getHumanTradingSymbol({
+ // tradingsymbol: order.tradingsymbol
+ // })
+ // }
+ // })
- res.json(humanOrders)
+ res.json(orders)
} catch (e) {
res.status(500).send(e)
}
diff --git a/pages/api/redirect_url_kite.ts b/pages/api/redirect_url_kite.ts
index 4e823c72..cdaed67f 100644
--- a/pages/api/redirect_url_kite.ts
+++ b/pages/api/redirect_url_kite.ts
@@ -1,4 +1,3 @@
-import { AxiosResponse } from 'axios'
import { KiteConnect } from 'kiteconnect'
import { cleanupQueues } from '../../lib/queue'
@@ -7,10 +6,10 @@ import {
getIndexInstruments,
premiumAuthCheck,
storeAccessTokenRemotely,
- checkHasSameAccessToken
+ checkHasSameAccessToken,
+ setUserSession
} from '../../lib/utils'
import { KiteProfile } from '../../types/kite'
-import { SignalXUser } from '../../types/misc'
const apiKey = process.env.KITE_API_KEY
const kiteSecret = process.env.KITE_API_SECRET
@@ -30,9 +29,7 @@ export default withSession(async (req, res) => {
requestToken,
kiteSecret
)
- const user: SignalXUser = { isLoggedIn: true, session: sessionData }
- req.session.set('user', user)
- await req.session.save()
+ const user = await setUserSession(req, sessionData)
// prepare the day
// fire and forget
diff --git a/pages/api/trades_day.ts b/pages/api/trades_day.ts
index cd9f2149..9e02b72a 100644
--- a/pages/api/trades_day.ts
+++ b/pages/api/trades_day.ts
@@ -165,6 +165,7 @@ export default withSession(async (req, res) => {
}
if (req.method === 'DELETE') {
+ console.log('delete request recieved for: ', req.body._id)
try {
const { data } = await axios(`${endpoint}/${req.body._id as string}`)
if (data.queue?.id) {
diff --git a/types/plans.ts b/types/plans.ts
index c857ec18..440448f2 100644
--- a/types/plans.ts
+++ b/types/plans.ts
@@ -5,11 +5,13 @@ import {
STRATEGIES,
STRANGLE_ENTRY_STRATEGIES,
PRODUCT_TYPE,
- VOLATILITY_TYPE
+ VOLATILITY_TYPE,
+ EXPIRY_TYPE
} from '../lib/constants'
interface COMMON_TRADE_PROPS {
productType: PRODUCT_TYPE
+ expiryType: EXPIRY_TYPE
}
export interface SavedPlanMeta extends COMMON_TRADE_PROPS {