diff --git a/autoTradeGenericLongCall.sh b/autoTradeGenericLongCall.sh new file mode 100755 index 0000000..5deae74 --- /dev/null +++ b/autoTradeGenericLongCall.sh @@ -0,0 +1,116 @@ +#!/bin/bash +#set -x +IFS=$'\0' + +. helpers.sh + +Symbol="$1" +if [[ -z ${Symbol} ]]; then + throw "A Stock symbol must be given as first parameter. exiting." err 2 +fi + +AccountName="$2" +if [[ -z ${AccountName} ]]; then + throw "An Account name must be given as first parameter. exiting." err 2 +fi + +if [[ -z $(./getAccountNumbers.sh "${AccountName}") ]]; then + throw "An the account with name _${AccountName}_ doesn't exist. exiting." err 2 +fi + +marketOpen=$([[ $(./getMarketHours.sh | jq '.option[].isOpen' | grep true | wc -l) -ne 0 ]] && echo true || echo false) +if [[ ${marketOpen} == false ]]; then + throw "The market is closed, exiting." info 2 +fi + +daysOutMin=87 +daysOutMax=91 +deltaMin=0.35 +deltaMax=0.40 + +marketOpen=$([[ $(./getMarketHours.sh | jq '.option[].isOpen' | grep true | wc -l) -ne 0 ]] && echo true || echo false) +if [[ ${marketOpen} == false ]]; then + throw "The market is closed, exiting." info 2 +fi + + +inputFile=temp/orderInputFile.$$.json +./getOptionChain.sh ''${Symbol}'' fromDate $(date "+%Y-%m-%d" -d "+${daysOutMin} days") toDate $(date "+%Y-%m-%d" -d "+${daysOutMax} days") > "${inputFile}" + +if [[ ! -f "${inputFile}" ]]; then + throw "ERROR: Input file _${inputFile}_ does not exist." err 1 +fi + +#Find the date closest to the Minimum number of days +dateKey=$(jq -r '.callExpDateMap | keys | .[]' "${inputFile}" | sort -r -t ":" +2 | awk -F ":" -e '{theDay=$2; if (theDay < '${daysOutMin}') { print lastDay; exit; } else { lastDay=$0; } } END { print $0 }') +log "Date-Key: _${dateKey}_" debug + +daysOut=$(cut -d : -f 2 <<< ${dateKey}) +if [[ ${daysOut} -gt ${daysOutMax} ]]; then + throw "This option is too far in the future. _${daysOut}_ is bigger than the max days in the future is _${daysOutMax}_. Exiting." info +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 + throw "No suitable long leg found - exiting." warning 1 +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) +log "Long Symbol: _${longSymbol}_ Strike: _${longStrike}_ Bid: _${longBid}_ Ask: _${longAsk}_" info + +#Check if this order has already been submitted. +./getOrders.sh | grep '\(WORKING\|FILLED\),'"${longSymbol:0:12}" > temp/existingOrders.$$ +if [[ $(wc -l < temp/existingOrders.$$) -eq 0 ]];then + log "Not Yet traded, continuing" info +else + throw "Already traded, exiting" info +fi + +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 +) + +log "Order: _${orderJson}_" debug + +if [[ "${noconfirm}" != "true" ]]; then + echo Enter to continue, Ctrl+C to cancel _${noconfirm}_ + read +fi + +curl -s -X POST \ + "https://api.schwabapi.com/trader/v1/accounts/$(./getAccountNumbers.sh "${AccountName}")/orders" \ + -H "Authorization: Bearer $(./getNewAccessToken.sh)" \ + -H 'accept: */*' \ + -H 'Content-Type: application/json' \ + -d "${orderJson}" + +log "Result: _$?_" debug diff --git a/autoTradeQQQLongCall.sh b/autoTradeQQQLongCall.sh index fef8de5..7d06f35 100755 --- a/autoTradeQQQLongCall.sh +++ b/autoTradeQQQLongCall.sh @@ -9,7 +9,7 @@ if [[ ${marketOpen} == false ]]; then throw "The market is closed, exiting." info 2 fi -daysOutMin=87 +daysOutMin=85 daysOutMax=91 deltaMin=0.35 deltaMax=0.40