Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ft: auto square off v2 #89

Open
wants to merge 25 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d5849d2
ft: auto square off v2
aakashlpin Oct 22, 2021
331ad3c
Merge branch 'develop' into ft-losing-leg-fix-when-both-legs-winning
aakashlpin Oct 22, 2021
f90f88e
Merge branch 'develop' into ft-losing-leg-fix-when-both-legs-winning
aakashlpin Oct 22, 2021
8504260
Merge pull request #95 from aakashlpin/develop
aakashlpin Nov 12, 2021
815238e
Merge branch 'master' into ft-losing-leg-fix-when-both-legs-winning
aakashlpin Nov 15, 2021
199576b
fx: fix multi leg square off issues
aakashlpin Nov 15, 2021
b2cfc6d
increase heap size and new limit
aakashlpin Dec 13, 2021
b7f579d
lesser than 512mb
aakashlpin Dec 13, 2021
8b3cc6b
1gb
aakashlpin Dec 13, 2021
901bc0f
Merge pull request #104 from aakashlpin/hf-render-fix
aakashlpin Dec 13, 2021
c64656a
updated method
aakashlpin Dec 13, 2021
1af75fe
fx: stop continuous logging and fix withRemoteRetry usage
aakashlpin Dec 19, 2021
c1d27a3
Merge branch 'master' into ft-losing-leg-fix-when-both-legs-winning
aakashlpin Dec 19, 2021
090db80
reduced BNF freeze for testing
aakashlpin Dec 20, 2021
a7abd5f
ft: flag to selectively disable csl (#108)
aakashlpin Dec 20, 2021
798d6fc
Merge branch 'master' into ft-losing-leg-fix-when-both-legs-winning
aakashlpin Dec 20, 2021
d9677ea
Update multiLegPremiumThreshold.ts
aakashlpin Dec 21, 2021
140afb6
jan 2022 update: nf freeze qty
aakashlpin Jan 3, 2022
ad604f3
Merge branch 'master' into ft-losing-leg-fix-when-both-legs-winning
aakashlpin Jan 3, 2022
728bb90
remove DO disclaimer
aakashlpin Mar 1, 2022
a7f40f8
fx: updated holiday list for 2022 (#133)
aakashlpin Mar 21, 2022
fd89cb2
Merge branch 'master' into ft-losing-leg-fix-when-both-legs-winning
aakashlpin Apr 1, 2022
559aad8
ft: memory leak issue fix attempt #1
aakashlpin Apr 1, 2022
527f7bf
updated freeze qty
aakashlpin Apr 1, 2022
06b2a72
fx: prevent queue bloat up
aakashlpin Apr 5, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ _Update - Redislabs free tier drops connections very often. Recommend upgrading

## 1-click Installation

_Update - DigitalOcean's app platform is terribly slow. Recommend using render.com for all new installations. All other instructions remain as is._

[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy)

or, deploy the application on DigitalOcean's (DO) apps platform.
Expand Down
7 changes: 1 addition & 6 deletions lib/browserUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ export function commonOnChangeHandler (
const getSchedulingApiProps = ({
isAutoSquareOffEnabled,
squareOffTime,
exitStrategy,
runAt,
runNow,
expireIfUnsuccessfulInMins
Expand All @@ -97,9 +96,7 @@ const getSchedulingApiProps = ({
.format(),
autoSquareOffProps: isAutoSquareOffEnabled
? {
time: squareOffTime,
deletePendingOrders:
exitStrategy !== EXIT_STRATEGIES.MULTI_LEG_PREMIUM_THRESHOLD
time: squareOffTime
}
: undefined,
expiresAt: expireIfUnsuccessfulInMins
Expand Down Expand Up @@ -193,7 +190,6 @@ export const formatFormDataForApi = ({
...getSchedulingApiProps({
isAutoSquareOffEnabled,
squareOffTime,
exitStrategy,
expireIfUnsuccessfulInMins,
runAt,
runNow
Expand Down Expand Up @@ -237,7 +233,6 @@ export const formatFormDataForApi = ({
...getSchedulingApiProps({
isAutoSquareOffEnabled,
squareOffTime,
exitStrategy,
expireIfUnsuccessfulInMins,
runAt,
runNow
Expand Down
1 change: 0 additions & 1 deletion lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ export const INSTRUMENT_DETAILS: Record<INSTRUMENTS, INSTRUMENT_PROPERTIES> = {
exchange: 'NSE',
strikeStepSize: 100,
// [27501-40000]
// freezeQty: 100
freezeQty: 1200
},
[INSTRUMENTS.FINNIFTY]: {
Expand Down
27 changes: 18 additions & 9 deletions lib/exit-strategies/autoSquareOff.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { KiteOrder } from '../../types/kite'
import { ASO_TYPE } from '../../types/misc'
import {
ATM_STRADDLE_TRADE,
ATM_STRANGLE_TRADE,
Expand All @@ -7,6 +8,7 @@ import {
import { USER_OVERRIDE } from '../constants'
import console from '../logging'
import {
convertSllToMarketOrder,
// logDeep,
patchDbTrade,
remoteOrderSuccessEnsurer,
Expand Down Expand Up @@ -122,29 +124,36 @@ export async function doSquareOffPositions (
}

async function autoSquareOffStrat ({
squareOffType,
rawKiteOrdersResponse,
deletePendingOrders,
initialJobData
}: {
squareOffType: ASO_TYPE
rawKiteOrdersResponse: KiteOrder[]
deletePendingOrders: boolean
initialJobData: SUPPORTED_TRADE_CONFIG
}): Promise<any> {
const { user } = initialJobData
const kite = syncGetKiteInstance(user)
const completedOrders = rawKiteOrdersResponse

if (deletePendingOrders) {
// console.log('deletePendingOrders init')
if (squareOffType === ASO_TYPE.SLL_TO_MARKET) {
const triggerPendingOrders = rawKiteOrdersResponse
// if completed orders exist, they can be converted to market hours
try {
await doDeletePendingOrders(completedOrders, kite)
// console.log('🟢 deletePendingOrders success', res)
await Promise.all(
triggerPendingOrders.map(order => convertSllToMarketOrder(kite, order))
)
} catch (e) {
console.log('🔴 deletePendingOrders failed')
console.error(e)
}
} else {
const completedOrders = rawKiteOrdersResponse
try {
await doSquareOffPositions(completedOrders, kite, initialJobData)
} catch (e) {
console.log('🔴 doSquareOffPositions failed')
console.error(e)
}
}
return doSquareOffPositions(completedOrders, kite, initialJobData)
}

export default autoSquareOffStrat
50 changes: 29 additions & 21 deletions lib/exit-strategies/individualLegExitOrders.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { KiteOrder } from '../../types/kite'
import { ASO_TYPE } from '../../types/misc'
import { SL_ORDER_TYPE } from '../../types/plans'
import { SUPPORTED_TRADE_CONFIG } from '../../types/trade'
import console from '../logging'
import { addToNextQueue, WATCHER_Q_NAME } from '../queue'
import orderResponse from '../strategies/mockData/orderResponse'
import {
addToAutoSquareOffQueue,
addToNextQueue,
WATCHER_Q_NAME
} from '../queue'
// import orderResponse from '../strategies/mockData/orderResponse'
import {
attemptBrokerOrders,
isUntestedFeaturesEnabled,
// isUntestedFeaturesEnabled,
remoteOrderSuccessEnsurer,
round,
syncGetKiteInstance
Expand Down Expand Up @@ -62,10 +67,10 @@ async function individualLegExitOrders ({
orderTag,
rollback,
slLimitPricePercent = 1,
instrument
instrument,
isAutoSquareOffEnabled
} = initialJobData

const slOrderType = SL_ORDER_TYPE.SLL
const kite = _kite || syncGetKiteInstance(user)

const exitOrders = completedOrders.map(order => {
Expand Down Expand Up @@ -103,10 +108,7 @@ async function individualLegExitOrders ({
exchange
}

if (slOrderType === SL_ORDER_TYPE.SLL) {
exitOrder = convertSlmToSll(exitOrder, slLimitPricePercent!, kite)
}

exitOrder = convertSlmToSll(exitOrder, slLimitPricePercent!, kite)
exitOrder.trigger_price = round(exitOrder.trigger_price!)
console.log('placing exit orders...', exitOrder)
return exitOrder
Expand All @@ -132,20 +134,26 @@ async function individualLegExitOrders ({
throw Error('rolled back onBrokenExitOrders')
}

if (slOrderType === SL_ORDER_TYPE.SLL) {
const watcherQueueJobs = statefulOrders.map(async exitOrder => {
return addToNextQueue(initialJobData, {
_nextTradingQueue: WATCHER_Q_NAME,
rawKiteOrderResponse: exitOrder
})
if (isAutoSquareOffEnabled) {
await addToAutoSquareOffQueue({
squareOffType: ASO_TYPE.SLL_TO_MARKET,
jobResponse: { rawKiteOrdersResponse: statefulOrders },
initialJobData
})
}

const watcherQueueJobs = statefulOrders.map(async exitOrder => {
return addToNextQueue(initialJobData, {
_nextTradingQueue: WATCHER_Q_NAME,
rawKiteOrderResponse: exitOrder
})
})

try {
await Promise.all(watcherQueueJobs)
} catch (e) {
console.log('error adding to `watcherQueueJobs`')
console.log(e.message ? e.message : e)
}
try {
await Promise.all(watcherQueueJobs)
} catch (e) {
console.log('error adding to `watcherQueueJobs`')
console.log(e.message ? e.message : e)
}

return statefulOrders
Expand Down
45 changes: 17 additions & 28 deletions lib/exit-strategies/minXPercentOrSupertrend.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import axios from 'axios'
import dayjs from 'dayjs'
import { KiteOrder } from '../../types/kite'
import { SL_ORDER_TYPE } from '../../types/plans'
import { DIRECTIONAL_OPTION_SELLING_TRADE } from '../../types/trade'

import console from '../logging'
Expand All @@ -10,6 +9,7 @@ import {
attemptBrokerOrders,
getLastOpenDateSince,
getNearestCandleTime,
getOrderHistory,
getPercentageChange,
logDeep,
remoteOrderSuccessEnsurer,
Expand All @@ -35,15 +35,14 @@ async function minXPercentOrSupertrend ({
hedgeOrderResponse
}: DOS_TRAILING_INTERFACE): Promise<any> {
const { user, orderTag, slLimitPricePercent = 1, instrument } = initialJobData
const slOrderType = SL_ORDER_TYPE.SLL
try {
const kite = syncGetKiteInstance(user)
const [rawKiteOrderResponse] = rawKiteOrdersResponse
// NB: rawKiteOrderResponse here is of pending SLM Order
const orderHistory: KiteOrder[] = await withRemoteRetry(() =>
kite.getOrderHistory(rawKiteOrderResponse.order_id)
const byRecencyOrderHistory: KiteOrder[] = await getOrderHistory(
kite,
rawKiteOrderResponse.order_id!
)
const byRecencyOrderHistory = orderHistory.reverse()

const isSlOrderCancelled = byRecencyOrderHistory.find(
odr => odr.status === 'CANCELLED'
Expand Down Expand Up @@ -126,28 +125,21 @@ async function minXPercentOrSupertrend ({

// console.log('should trail SL!')
try {
const sllOrderProps =
slOrderType === SL_ORDER_TYPE.SLL
? convertSlmToSll(
{
transaction_type: kite.TRANSACTION_TYPE_BUY,
trigger_price: newSL
} as KiteOrder,
slLimitPricePercent!,
kite
)
: null
const sllOrderProps = convertSlmToSll(
{
transaction_type: kite.TRANSACTION_TYPE_BUY,
trigger_price: newSL
} as KiteOrder,
slLimitPricePercent!,
kite
)
const res = await kite.modifyOrder(
triggerPendingOrder!.variety,
triggerPendingOrder!.order_id,
slOrderType === SL_ORDER_TYPE.SLL
? {
trigger_price: sllOrderProps!.trigger_price,
price: sllOrderProps!.price
}
: {
trigger_price: newSL
}
{
trigger_price: sllOrderProps!.trigger_price,
price: sllOrderProps!.price
}
)
console.log(
`🟢 [minXPercentOrSupertrend] SL modified from ${String(
Expand Down Expand Up @@ -175,10 +167,7 @@ async function minXPercentOrSupertrend ({
tag: orderTag!
}

if (slOrderType === SL_ORDER_TYPE.SLL) {
exitOrder = convertSlmToSll(exitOrder, slLimitPricePercent!, kite)
}

exitOrder = convertSlmToSll(exitOrder, slLimitPricePercent!, kite)
const remoteOrder = remoteOrderSuccessEnsurer({
ensureOrderState: 'TRIGGER PENDING',
instrument,
Expand Down
44 changes: 26 additions & 18 deletions lib/exit-strategies/multiLegPremiumThreshold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,20 @@ import {
syncGetKiteInstance,
withRemoteRetry,
patchDbTrade,
getMultipleInstrumentPrices
getMultipleInstrumentPrices,
logDeep
} from '../utils'

import { doSquareOffPositions } from './autoSquareOff'

const patchTradeWithTrailingSL = async ({ dbId, trailingSl }) => {
try {
await patchDbTrade({
_id: dbId,
patchProps: {
liveTrailingSl: trailingSl,
lastTrailingSlSetAt: dayjs().format()
}
})
} catch (e) {
console.log('🔴 [patchTradeWithTrailingSL] error', e)
}
}
const patchTradeWithTrailingSL = async ({ dbId, trailingSl }) =>
await patchDbTrade({
_id: dbId,
patchProps: {
liveTrailingSl: trailingSl,
lastTrailingSlSetAt: dayjs().format()
}
})

const tradeHeartbeat = async dbId => {
const data = await patchDbTrade({
Expand Down Expand Up @@ -144,7 +140,14 @@ async function multiLegPremiumThreshold ({
'🔴 [multiLegPremiumThreshold] getInstrumentPrice error',
error
)
return Promise.reject(new Error('Kite APIs acting up'))
// [TODO] see if we can resolve this and add back to the queue to prevent memory leak issues
await addToNextQueue(initialJobData, {
_nextTradingQueue: EXIT_TRADING_Q_NAME,
rawKiteOrdersResponse,
squareOffOrders
})

return Promise.resolve('Kite APIs acting up!')
}

const liveTotalPremium = tradingSymbols.reduce((sum, tradingSymbol) => {
Expand Down Expand Up @@ -226,7 +229,12 @@ async function multiLegPremiumThreshold ({

if (liveTotalPremium < checkAgainstSl) {
const rejectMsg = `🟢 [multiLegPremiumThreshold] liveTotalPremium (${liveTotalPremium}) < threshold (${checkAgainstSl})`
return Promise.reject(new Error(rejectMsg))
await addToNextQueue(initialJobData, {
_nextTradingQueue: EXIT_TRADING_Q_NAME,
rawKiteOrdersResponse,
squareOffOrders
})
return Promise.resolve(rejectMsg)
}

// terminate the checker
Expand Down Expand Up @@ -280,13 +288,13 @@ async function multiLegPremiumThreshold ({
legOrder => legOrder.tradingsymbol === losingLeg.tradingSymbol
)
)
// console.log('squareOffLosingLegs', logDeep(squareOffLosingLegs))
console.log('squareOffLosingLegs', logDeep(squareOffLosingLegs))
const bringToCostOrders = winningLegs.map(winningLeg =>
legsOrders.find(
legOrder => legOrder.tradingsymbol === winningLeg.tradingSymbol
)
)
// console.log('bringToCostOrders', logDeep(bringToCostOrders))
console.log('bringToCostOrders', logDeep(bringToCostOrders))
// 1. square off losing legs
await doSquareOffPositions(
squareOffLosingLegs as KiteOrder[],
Expand Down
11 changes: 6 additions & 5 deletions lib/queue-processor/exitTradingQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const worker = new Worker(
const exitOrders = await processJob(job.data)
return exitOrders
} catch (e) {
console.log(e.message ? e.message : e)
// console.log(e.message ? e.message : e)
throw new Error(e)
}
},
Expand All @@ -85,10 +85,11 @@ worker.on('error', err => {
console.log('🔴 [exitTradingQueue] worker error', err)
})

// worker.on('completed', (job) => {
// // const { id, name } = job
// // console.log('// job has completed', { id, name })
// })
worker.on('completed', async job => {
await job.remove()
// const { id, name } = job
// console.log('// job has completed', { id, name })
})

// worker.on('failed', (job) => {
// try {
Expand Down
Loading