#!/bin/bash set -x set -e IFS=$'\0' myPID=$$ marketOpen=$([[ $(./getMarketHours.sh | jq '.option[].isOpen' | grep true | wc -l) -ne 0 ]] && echo true || echo false) if [[ ${marketOpen} == false ]]; then errMsg="The market is closed, exiting." systemd-cat -t "`basename $0` $1" -p info <<< ${errMsg} >&2 echo "${errMsg}" exit 2 fi inputFile="$1" if [[ "" == "$inputFile" ]]; then inputFile=temp/orderInputFile.$$.json ./getOptionChain.sh '$SPX' fromDate $(date "+%Y-%m-%d") toDate $(date "+%Y-%m-%d") > "${inputFile}" fi if [[ ! -f "${inputFile}" ]]; then errMsg="ERROR: Input file _${inputFile}_ does not exist." systemd-cat -t "`basename $0` $1" -p err <<< ${errMsg} >&2 echo "${errMsg}" exit 1 fi dateKey=$(jq -r '.putExpDateMap | keys | .[]' "${inputFile}" | head -n 1) systemd-cat -t "`basename $0` $1" -p debug <<< "Date-Key: _${dateKey}_" echo "Date-Key: _${dateKey}_" underlyingPrice=$(jq ".underlyingPrice" "${inputFile}") atmStrike=$(jq -r '.callExpDateMap[]|keys[]' "${inputFile}" | sort -n | awk -e '{lastStrike=$1; if ($1 > '${underlyingPrice}') {print $1; exit } }') jq '.putExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) |.[] | select(.strikePrice=='${atmStrike}') ' "${inputFile}" | tail -n 8 > temp/shortLegP.json shortStrikeP=$(jq -r '.strikePrice' < temp/shortLegP.json) shortBidP=$(jq -r '.bid' < temp/shortLegP.json) shortAskP=$(jq -r '.ask' < temp/shortLegP.json) shortSymbolP=$(jq -r '.symbol' < temp/shortLegP.json) optionRoot=$(jq -r '.optionRoot' < temp/shortLegP.json) msg="Short Put Symbol: _${shortSymbolP}_ Strike: _${shortStrikeP}_ Bid: _${shortBidP}_ Ask: _${shortAskP}_" systemd-cat -t "`basename $0` $1" -p info <<< ${msg} echo "${msg}" jq '.callExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) |.[] | select(.strikePrice=='${atmStrike}') ' "${inputFile}" | tail -n 8 > temp/shortLegC.json shortStrikeC=$(jq -r '.strikePrice' < temp/shortLegC.json) shortBidC=$(jq -r '.bid' < temp/shortLegC.json) shortAskC=$(jq -r '.ask' < temp/shortLegC.json) shortSymbolC=$(jq -r '.symbol' < temp/shortLegC.json) msg="Short Call Symbol: _${shortSymbolC}_ Strike: _${shortStrikeC}_ Bid: _${shortBidC}_ Ask: _${shortAskC}_" systemd-cat -t "`basename $0` $1" -p info <<< ${msg} echo "${msg}" jq '.putExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) | .[] | select(.optionRoot == "'${optionRoot}'" and .strikePrice >= '${shortStrikeP}'-10 and .strikePrice < '${shortStrikeP}')' "${inputFile}" | head -n 8 > temp/longLegP.json longStrikeP=$(jq -r '.strikePrice' < temp/longLegP.json) longBidP=$(jq -r '.bid' < temp/longLegP.json) longAskP=$(jq -r '.ask' < temp/longLegP.json) longSymbolP=$(jq -r '.symbol' < temp/longLegP.json) msg="Long Symbol: _${longSymbolP}_ Strike: _${longStrikeP}_ Bid: _${longBidP}_ Ask: _${longAskP}_" systemd-cat -t "`basename $0` $1" -p info <<< ${msg} echo "${msg}" #Check if this order has already been submitted. jq '.callExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) | .[] | select(.optionRoot == "'${optionRoot}'" and .strikePrice >= '${shortStrikeC}'+10 and .strikePrice > '${shortStrikeP}')' "${inputFile}" | head -n 8 > temp/longLegC.json longStrikeC=$(jq -r '.strikePrice' < temp/longLegC.json) longBidC=$(jq -r '.bid' < temp/longLegC.json) longAskC=$(jq -r '.ask' < temp/longLegC.json) longSymbolC=$(jq -r '.symbol' < temp/longLegC.json) msg="Long Symbol: _${longSymbolC}_ Strike: _${longStrikeC}_ Bid: _${longBidC}_ Ask: _${longAskC}_" systemd-cat -t "`basename $0` $1" -p info <<< ${msg} echo "${msg}" #Check if this order has already been submitted. ./getOrders.sh | (grep '\(WORKING\|FILLED\),'${longSymbolC:0:12} || true) > temp/existingOrders.${myPID} if [[ $(wc -l < temp/existingOrders.${myPID}) -eq 0 ]];then msg="Not Yet traded, continuing" systemd-cat -t "`basename $0` $1" -p info <<< ${msg} echo ${msg} else msg="Already traded, exiting" systemd-cat -t "`basename $0` $1" -p info <<< ${msg} echo ${msg} # exit 0 fi priceOffset=1.1 # try to get $10 more in premium... profitTargetPct=25 # cash in at 25% gains #For SPX we need to submit orders at the closest 5cent price #To find the closest 5cent price the mathematical solution is # 1) Multiply by 20 # 2) Round to the Coloses full number # 3) Divide by 20 priceOpen=$(echo "scale=2; exact=((${shortBidC}+${shortAskC})/2) + ((${shortBidP}+${shortAskP})/2) - ((${longBidC}+${longAskC})/2) - ((${longBidP}+${longAskP})/2) + ${priceOffset}; scale=0; round5=exact*20/1; scale=2; round5/20" | bc) priceClose=$(echo "scale=2; exact=${priceOpen} * (100-${profitTargetPct}) /100; scale=0; round5=exact*20/1; scale=2; round5/20" | bc) # Profit target 25% orderJson=$(jq -c <<-EOM { "orderType": "NET_CREDIT", "session": "NORMAL", "price": ${priceOpen}, "duration": "DAY", "orderStrategyType": "SINGLE", "quantity": 1, "orderLegCollection": [ { "instruction": "SELL_TO_OPEN", "quantity": 1, "instrument": { "symbol": "${shortSymbolP}", "assetType": "OPTION" } }, { "instruction": "SELL_TO_OPEN", "quantity": 1, "instrument": { "symbol": "${shortSymbolC}", "assetType": "OPTION" } }, { "instruction": "BUY_TO_OPEN", "quantity": 1, "instrument": { "symbol": "${longSymbolP}", "assetType": "OPTION" } }, { "instruction": "BUY_TO_OPEN", "quantity": 1, "instrument": { "symbol": "${longSymbolC}", "assetType": "OPTION" } } ], "orderStrategyType": "TRIGGER", "childOrderStrategies": [ { "orderType": "NET_DEBIT", "session": "NORMAL", "price": ${priceClose}, "duration": "DAY", "orderStrategyType": "SINGLE", "quantity": 1, "orderLegCollection": [ { "instruction": "BUY_TO_CLOSE", "quantity": 1, "instrument": { "symbol": "${shortSymbolP}", "assetType": "OPTION" } }, { "instruction": "BUY_TO_CLOSE", "quantity": 1, "instrument": { "symbol": "${shortSymbolC}", "assetType": "OPTION" } }, { "instruction": "SELL_TO_CLOSE", "quantity": 1, "instrument": { "symbol": "${longSymbolP}", "assetType": "OPTION" } }, { "instruction": "SELL_TO_CLOSE", "quantity": 1, "instrument": { "symbol": "${longSymbolC}", "assetType": "OPTION" } } ] } ] } EOM ) systemd-cat -t "`basename $0` $1" -p debug <<< "Order: _${orderJson}_" if [[ "${noconfirm}" != "true" ]]; then echo ${orderJSON} | jq echo Enter to continue, Ctrl+C to cancel _${noconfirm}_ read fi ./getNewAccessToken.sh curl -s -X POST \ "https://api.schwabapi.com/trader/v1/accounts/$(./getAccountNumbers.sh Regular)/orders" \ -H "Authorization: Bearer $(