2024-07-17 14:08:55 -05:00
|
|
|
#!/bin/bash
|
|
|
|
|
set -x
|
|
|
|
|
IFS=$'\0'
|
|
|
|
|
|
2024-08-27 12:16:01 -05:00
|
|
|
. helpers.sh
|
|
|
|
|
|
2024-09-03 10:32:56 -05:00
|
|
|
daysOutMin=87
|
2024-07-17 14:08:55 -05:00
|
|
|
daysOutMax=91
|
|
|
|
|
deltaMin=0.35
|
|
|
|
|
deltaMax=0.40
|
|
|
|
|
|
|
|
|
|
inputFile="$1"
|
|
|
|
|
if [[ "" == "$inputFile" ]]; then
|
|
|
|
|
latestFile="$(ls data/`date +%Y-%m-%d`/*QQQ* | sort | tail -n 1)"
|
2024-08-27 12:16:01 -05:00
|
|
|
log "Latest File: _${latestFile}_" debug
|
2024-07-17 14:08:55 -05:00
|
|
|
inputFile=temp/orderInputFile.json
|
|
|
|
|
bzip2 -dc < "${latestFile}" > "${inputFile}"
|
|
|
|
|
fi
|
|
|
|
|
if [[ ! -f "${inputFile}" ]]; then
|
2024-08-27 12:16:01 -05:00
|
|
|
throw "ERROR: Input file _${inputFile}_ does not exist." err 1
|
2024-07-17 14:08:55 -05:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
dateKey=$(jq -r '.callExpDateMap | keys | .[]' temp/orderInputFile.json | sort -r -t ":" +2 | awk -F ":" -e '{theDay=$2; if (theDay < '${daysOutMin}') { print lastDay; exit; } else { lastDay=$0; } }')
|
2024-08-27 12:16:01 -05:00
|
|
|
log "Date-Key: _${dateKey}_" debug
|
2024-07-17 14:08:55 -05:00
|
|
|
|
|
|
|
|
daysOut=$(cut -d : -f 2 <<< ${dateKey})
|
|
|
|
|
if [[ ${daysOut} -gt ${daysOutMax} ]]; then
|
2024-08-27 12:16:01 -05:00
|
|
|
throw "This option is too far in the future. _${daysOut}_ is bigger than the max days in the future is _${daysOutMax}_. Exiting." info
|
2024-07-17 14:08:55 -05:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
#Looking for leg, between the specified deltas
|
|
|
|
|
# JTR - the "floor" is to only find the prices at the integer strikes, but I changed my mind about that...
|
|
|
|
|
#jq '.callExpDateMap."'${dateKey}'"[]|map({symbol, delta, strikePrice,bid,ask}) | .[] | select(.delta >= '${deltaMin}' and .delta <= '${deltaMax}') | select( (.strikePrice | floor) == .strikePrice)' "${inputFile}" | tail -n 7 > temp/longLeg.json
|
|
|
|
|
jq '.callExpDateMap."'${dateKey}'"[]|map({symbol, delta, strikePrice,bid,ask}) | .[] | select(.delta >= '${deltaMin}' and .delta <= '${deltaMax}')' "${inputFile}" | tail -n 7 > temp/longLeg.json
|
|
|
|
|
numLinesInLeg=$(wc -l temp/longLeg.json | cut -c1)
|
|
|
|
|
if [[ 7 -ne ${numLinesInLeg} ]]; then
|
2024-08-27 12:16:01 -05:00
|
|
|
throw "No suitable long leg found - exiting." warning 2
|
2024-07-17 14:08:55 -05:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
longStrike=$(jq -r '.strikePrice' < temp/longLeg.json)
|
|
|
|
|
longBid=$(jq -r '.bid' < temp/longLeg.json)
|
|
|
|
|
longAsk=$(jq -r '.ask' < temp/longLeg.json)
|
|
|
|
|
longSymbol=$(jq -r '.symbol' < temp/longLeg.json)
|
2024-08-27 12:16:01 -05:00
|
|
|
log "Long Symbol: _${longSymbol}_ Strike: _${longStrike}_ Bid: _${longBid}_ Ask: _${longAsk}_" info
|
2024-08-15 11:30:27 -05:00
|
|
|
|
2024-08-27 12:16:01 -05:00
|
|
|
#Check if this order has already been submitted.
|
2024-08-15 11:30:27 -05:00
|
|
|
./getOrders.sh | grep '\(WORKING\|FILLED\),'${longSymbol} > temp/existingOrders.$$
|
|
|
|
|
if [[ $(wc -l < temp/existingOrders.$$) -eq 0 ]];then
|
2024-08-27 12:16:01 -05:00
|
|
|
log "Not Yet traded, continuing" info
|
2024-08-15 11:30:27 -05:00
|
|
|
else
|
2024-08-27 12:16:01 -05:00
|
|
|
throw "Already traded, exiting" info
|
2024-08-15 11:30:27 -05:00
|
|
|
fi
|
2024-07-17 14:08:55 -05:00
|
|
|
|
|
|
|
|
priceOffset=0.0
|
|
|
|
|
# Get the Middle price...
|
|
|
|
|
price=$(echo "scale=2; ((${longBid}+${longAsk})/2) + ${priceOffset}" | bc)
|
|
|
|
|
|
|
|
|
|
orderJson=$(jq -c <<-EOM
|
|
|
|
|
{
|
|
|
|
|
"orderType": "LIMIT",
|
|
|
|
|
"session": "NORMAL",
|
|
|
|
|
"price": ${price},
|
|
|
|
|
"duration": "DAY",
|
|
|
|
|
"orderStrategyType": "SINGLE",
|
|
|
|
|
"quantity": 1,
|
|
|
|
|
"orderLegCollection": [
|
|
|
|
|
{
|
|
|
|
|
"instruction": "BUY_TO_OPEN",
|
|
|
|
|
"quantity": 1,
|
|
|
|
|
"instrument": {
|
|
|
|
|
"symbol": "${longSymbol}",
|
|
|
|
|
"assetType": "OPTION"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
EOM
|
|
|
|
|
)
|
|
|
|
|
|
2024-08-27 12:16:01 -05:00
|
|
|
log "Order: _${orderJson}_" debug
|
2024-07-17 14:08:55 -05:00
|
|
|
|
2024-08-26 15:18:24 -05:00
|
|
|
if [[ "${noconfirm}" != "true" ]]; then
|
|
|
|
|
echo Enter to continue, Ctrl+C to cancel _${noconfirm}_
|
|
|
|
|
read
|
|
|
|
|
fi
|
|
|
|
|
|
2024-07-17 14:08:55 -05:00
|
|
|
curl -s -X POST \
|
2024-08-26 21:44:43 -05:00
|
|
|
"https://api.schwabapi.com/trader/v1/accounts/$(./getAccountNumbers.sh IRA)/orders" \
|
2024-09-03 10:32:56 -05:00
|
|
|
-H "Authorization: Bearer $(./getNewAccessToken.sh)" \
|
2024-07-17 14:08:55 -05:00
|
|
|
-H 'accept: */*' \
|
|
|
|
|
-H 'Content-Type: application/json' \
|
2024-08-26 21:44:43 -05:00
|
|
|
-d "${orderJson}"
|
2024-07-17 14:08:55 -05:00
|
|
|
|