- Separate getting option chains from recording
- Add checking for market open - Remove SPX from recording - Hopefully precent the refresh token from being overwritten sometimes
This commit is contained in:
@@ -86,9 +86,6 @@
|
|||||||
{
|
{
|
||||||
"Symbol": "SLV"
|
"Symbol": "SLV"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Symbol": "$SPX"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Symbol": "SPY"
|
"Symbol": "SPY"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -89,8 +89,11 @@ EOM
|
|||||||
|
|
||||||
systemd-cat -t "`basename $0` $1" -p debug <<< "Order: _${orderJson}_"
|
systemd-cat -t "`basename $0` $1" -p debug <<< "Order: _${orderJson}_"
|
||||||
|
|
||||||
echo Enter to continue, Ctrl+C to cancel
|
if [[ "${noconfirm}" != "true" ]]; then
|
||||||
read
|
echo Enter to continue, Ctrl+C to cancel _${noconfirm}_
|
||||||
|
read
|
||||||
|
fi
|
||||||
|
|
||||||
./getNewAccessToken.sh
|
./getNewAccessToken.sh
|
||||||
|
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
|
|||||||
@@ -4,12 +4,19 @@ set -e
|
|||||||
IFS=$'\0'
|
IFS=$'\0'
|
||||||
myPID=$$
|
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"
|
inputFile="$1"
|
||||||
if [[ "" == "$inputFile" ]]; then
|
if [[ "" == "$inputFile" ]]; then
|
||||||
latestFile="$(ls data/`date +%Y-%m-%d`/*\$SPX* | sort | tail -n 1)"
|
inputFile=temp/orderInputFile.$$.json
|
||||||
systemd-cat -t "`basename $0` $1" -p debug <<< "Latest File: _${latestFile}_"
|
./getOptionChain.sh '$SPX' fromDate $(date "+%Y-%m-%d" -d "+40 days") toDate $(date "+%Y-%m-%d" -d "+46 days") > "${inputFile}"
|
||||||
inputFile=temp/orderInputFile.json
|
|
||||||
bzip2 -dc < "${latestFile}" > "${inputFile}"
|
|
||||||
fi
|
fi
|
||||||
if [[ ! -f "${inputFile}" ]]; then
|
if [[ ! -f "${inputFile}" ]]; then
|
||||||
errMsg="ERROR: Input file _${inputFile}_ does not exist."
|
errMsg="ERROR: Input file _${inputFile}_ does not exist."
|
||||||
@@ -20,6 +27,7 @@ fi
|
|||||||
|
|
||||||
dateKey=$(jq -r '.putExpDateMap | keys | .[]' "${inputFile}" | head -n 1)
|
dateKey=$(jq -r '.putExpDateMap | keys | .[]' "${inputFile}" | head -n 1)
|
||||||
systemd-cat -t "`basename $0` $1" -p debug <<< "Date-Key: _${dateKey}_"
|
systemd-cat -t "`basename $0` $1" -p debug <<< "Date-Key: _${dateKey}_"
|
||||||
|
echo "Date-Key: _${dateKey}_"
|
||||||
|
|
||||||
jq '.putExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) |.[] | select(.delta >= -0.30 and .delta <= -0.25) ' "${inputFile}" | tail -n 8 > temp/shortLeg.json
|
jq '.putExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) |.[] | select(.delta >= -0.30 and .delta <= -0.25) ' "${inputFile}" | tail -n 8 > temp/shortLeg.json
|
||||||
shortStrike=$(jq -r '.strikePrice' < temp/shortLeg.json)
|
shortStrike=$(jq -r '.strikePrice' < temp/shortLeg.json)
|
||||||
@@ -31,7 +39,7 @@ msg="Short Symbol: _${shortSymbol}_ Strike: _${shortStrike}_ Bid: _${shortBid}_
|
|||||||
systemd-cat -t "`basename $0` $1" -p info <<< ${msg}
|
systemd-cat -t "`basename $0` $1" -p info <<< ${msg}
|
||||||
echo "${msg}"
|
echo "${msg}"
|
||||||
|
|
||||||
jq '.putExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) | .[] | select(.optionRoot == "'${shortOptionRoot}'" and .strikePrice >= '${shortStrike}'-50 and .strikePrice < '${shortStrike}')' temp/orderInputFile.json | head -n 8 > temp/longLeg.json
|
jq '.putExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) | .[] | select(.optionRoot == "'${shortOptionRoot}'" and .strikePrice >= '${shortStrike}'-50 and .strikePrice < '${shortStrike}')' "${inputFile}" | head -n 8 > temp/longLeg.json
|
||||||
longStrike=$(jq -r '.strikePrice' < temp/longLeg.json)
|
longStrike=$(jq -r '.strikePrice' < temp/longLeg.json)
|
||||||
longBid=$(jq -r '.bid' < temp/longLeg.json)
|
longBid=$(jq -r '.bid' < temp/longLeg.json)
|
||||||
longAsk=$(jq -r '.ask' < temp/longLeg.json)
|
longAsk=$(jq -r '.ask' < temp/longLeg.json)
|
||||||
@@ -89,8 +97,11 @@ EOM
|
|||||||
|
|
||||||
systemd-cat -t "`basename $0` $1" -p debug <<< "Order: _${orderJson}_"
|
systemd-cat -t "`basename $0` $1" -p debug <<< "Order: _${orderJson}_"
|
||||||
|
|
||||||
#echo Enter to continue, Ctrl+C to cancel
|
if [[ "${noconfirm}" != "true" ]]; then
|
||||||
#read
|
echo Enter to continue, Ctrl+C to cancel _${noconfirm}_
|
||||||
|
read
|
||||||
|
fi
|
||||||
|
|
||||||
./getNewAccessToken.sh
|
./getNewAccessToken.sh
|
||||||
|
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
|
|||||||
205
autoTradeSPX_IB_0DTE_25pctProfitTaker.sh
Executable file
205
autoTradeSPX_IB_0DTE_25pctProfitTaker.sh
Executable file
@@ -0,0 +1,205 @@
|
|||||||
|
#!/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/C819AC820A502BA92E55D775B22BDF0E1BC91D86C62685714347734A5827CCB3/orders' \
|
||||||
|
-H "Authorization: Bearer $(<access_token.dat)" \
|
||||||
|
-H 'accept: */*' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d "${orderJson}"
|
||||||
|
|
||||||
160
autoTradeSPX_IB_1DTE.sh
Executable file
160
autoTradeSPX_IB_1DTE.sh
Executable file
@@ -0,0 +1,160 @@
|
|||||||
|
#!/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" -d "+1 days") toDate $(date "+%Y-%m-%d" -d "+1 days") > "${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 } }')
|
||||||
|
|
||||||
|
|
||||||
|
optionRoot=SPXW #I only want the PM expiry (SPX without the W is AM expiry)
|
||||||
|
|
||||||
|
jq '.putExpDateMap."'${dateKey}'"[]|map({symbol,delta,strikePrice,bid,ask,optionRoot}) |.[] | select(.optionRoot == "'${optionRoot}'" and .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)
|
||||||
|
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(.optionRoot == "'${optionRoot}'" and .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}'-5 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}'+5 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=0.00 # try to get a little better price
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
|
orderJson=$(jq -c <<-EOM
|
||||||
|
{
|
||||||
|
"orderType": "NET_CREDIT",
|
||||||
|
"session": "NORMAL",
|
||||||
|
"price": ${priceOpen},
|
||||||
|
"duration": "GOOD_TILL_CANCEL",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
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/C819AC820A502BA92E55D775B22BDF0E1BC91D86C62685714347734A5827CCB3/orders' \
|
||||||
|
-H "Authorization: Bearer $(<access_token.dat)" \
|
||||||
|
-H 'accept: */*' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d "${orderJson}"
|
||||||
|
|
||||||
@@ -7,6 +7,14 @@ daysOutMax=91
|
|||||||
deltaMin=0.35
|
deltaMin=0.35
|
||||||
deltaMax=0.40
|
deltaMax=0.40
|
||||||
|
|
||||||
|
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"
|
inputFile="$1"
|
||||||
if [[ "" == "$inputFile" ]]; then
|
if [[ "" == "$inputFile" ]]; then
|
||||||
latestFile="$(ls data/`date +%Y-%m-%d`/*SPY* | sort | tail -n 1)"
|
latestFile="$(ls data/`date +%Y-%m-%d`/*SPY* | sort | tail -n 1)"
|
||||||
@@ -21,7 +29,7 @@ if [[ ! -f "${inputFile}" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
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; } }')
|
dateKey=$(jq -r '.callExpDateMap | keys | .[]' "${inputFile}" | sort -r -t ":" +2 | awk -F ":" -e '{theDay=$2; if (theDay < '${daysOutMin}') { print lastDay; exit; } else { lastDay=$0; } }')
|
||||||
systemd-cat -t "`basename $0` $1" -p debug <<< "Date-Key: _${dateKey}_"
|
systemd-cat -t "`basename $0` $1" -p debug <<< "Date-Key: _${dateKey}_"
|
||||||
|
|
||||||
daysOut=$(cut -d : -f 2 <<< ${dateKey})
|
daysOut=$(cut -d : -f 2 <<< ${dateKey})
|
||||||
@@ -89,8 +97,11 @@ EOM
|
|||||||
|
|
||||||
systemd-cat -t "`basename $0` $1" -p debug <<< "Order: _${orderJson}_"
|
systemd-cat -t "`basename $0` $1" -p debug <<< "Order: _${orderJson}_"
|
||||||
|
|
||||||
echo Enter to continue, Ctrl+C to cancel
|
if [[ "${noconfirm}" != "true" ]]; then
|
||||||
read
|
echo Enter to continue, Ctrl+C to cancel _${noconfirm}_
|
||||||
|
read
|
||||||
|
fi
|
||||||
|
|
||||||
./getNewAccessToken.sh
|
./getNewAccessToken.sh
|
||||||
|
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
|
|||||||
52
getMarketHours.sh
Executable file
52
getMarketHours.sh
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#set -x
|
||||||
|
set -e
|
||||||
|
mkdir -p temp
|
||||||
|
|
||||||
|
ErrorLogLevel=err
|
||||||
|
#Handle additional commandline parameters
|
||||||
|
if [[ $1 == -* ]]; then
|
||||||
|
if [[ $1 == "-ErrorAsWarning" ]]; then
|
||||||
|
ErrorLogLevel=warning
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
markets=""
|
||||||
|
if [[ ! -z $1 ]]; then
|
||||||
|
markets=$1
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${markets}" ]]; then
|
||||||
|
markets="equity&markets=option&markets=bond&markets=future&markets=forex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
queryString="?markets=${markets}"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
queryString="${queryString}&$1=$2"
|
||||||
|
shift; shift
|
||||||
|
done
|
||||||
|
|
||||||
|
msg="Querying for markets: _${markets}_ query string: _${queryString}_"
|
||||||
|
systemd-cat -t "`basename $0` $1" -p debug <<< ${msg}
|
||||||
|
|
||||||
|
curl -s -X GET "https://api.schwabapi.com/marketdata/v1/markets${queryString}" \
|
||||||
|
-H "Authorization: Bearer $(<access_token.dat)" > temp/markets.tmp.$$.json
|
||||||
|
|
||||||
|
|
||||||
|
marketsCheck=$(jq -e -r '.. | .isOpen?' temp/markets.tmp.$$.json | grep -v null | wc -l)
|
||||||
|
if [[ ${marketsCheck} -eq 0 ]]; then
|
||||||
|
errMsg="ERROR: THE RESPONSE IS INCORRECT! markets: _${markets}_ Check: _${marketsCheck}_ check file _temp/markets.tmp.$$.json_"
|
||||||
|
systemd-cat -t "`basename $0` $1" -p ${ErrorLogLevel} <<< ${errMsg}
|
||||||
|
if [[ "${ErrorLogLevel}" == "err" ]]; then
|
||||||
|
>&2 echo "${errMsg}"
|
||||||
|
fi
|
||||||
|
exit 2
|
||||||
|
else
|
||||||
|
jq < temp/markets.tmp.$$.json
|
||||||
|
rm temp/markets.tmp.$$.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
@@ -17,11 +17,12 @@ if [[ $? -ne 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
#echo Access Token: $(<access_token.dat)
|
#echo Access Token: $(<access_token.dat)
|
||||||
|
|
||||||
# I have not seen it change, but let's see if they give us a new one before expiry...
|
## I found the refresh token to be empty after the network is unreachable, therefore I don't handle the refresh token here...
|
||||||
# after all they send it so we should probably process it.
|
## I have not seen it change, but let's see if they give us a new one before expiry...
|
||||||
jq -e -r .refresh_token temp/accessTokenReqResp.$$.json > temp/refresh_token.dat
|
## after all they send it so we should probably process it.
|
||||||
if [[ $? -eq 0 ]]; then
|
#jq -e -r .refresh_token temp/accessTokenReqResp.$$.json > temp/refresh_token.dat
|
||||||
mv temp/refresh_token.dat refresh_token.dat
|
#if [[ $? -eq 0 ]]; then
|
||||||
fi
|
# mv temp/refresh_token.dat refresh_token.dat
|
||||||
#echo Refresh Token: $(<refresh_token.dat)
|
#fi
|
||||||
|
##echo Refresh Token: $(<refresh_token.dat)
|
||||||
|
#
|
||||||
|
|||||||
44
getOptionChain.sh
Executable file
44
getOptionChain.sh
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#set -x
|
||||||
|
mkdir -p temp
|
||||||
|
|
||||||
|
ErrorLogLevel=err
|
||||||
|
#Handle additional commandline parameters
|
||||||
|
if [[ $1 == -* ]]; then
|
||||||
|
if [[ $1 == "-ErrorAsWarning" ]]; then
|
||||||
|
ErrorLogLevel=warning
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
symbol=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
queryString="?symbol=${symbol}"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
queryString="${queryString}&$1=$2"
|
||||||
|
shift; shift
|
||||||
|
done
|
||||||
|
|
||||||
|
msg="Querying for Symbol: _${symbol}_ query string: _${queryString}_"
|
||||||
|
systemd-cat -t "`basename $0` $1" -p debug <<< ${msg}
|
||||||
|
|
||||||
|
curl -s -X GET "https://api.schwabapi.com/marketdata/v1/chains${queryString}" \
|
||||||
|
-H "Authorization: Bearer $(<access_token.dat)" > temp/optionChain.${symbol}.tmp.$$.json
|
||||||
|
|
||||||
|
jqQuery=".symbol"
|
||||||
|
symbolCheck=$(jq -r ${jqQuery} < temp/optionChain.${symbol}.tmp.$$.json)
|
||||||
|
if [[ "${symbol}" != "${symbolCheck}" ]]; then
|
||||||
|
errMsg="ERROR: THE RESPONSE IS INCORRECT! Symbol: _${symbol}_ Check: _${symbolCheck}_ check file _temp/optionChain.${symbol}.tmp.$$.json_"
|
||||||
|
systemd-cat -t "`basename $0` $1" -p ${ErrorLogLevel} <<< ${errMsg}
|
||||||
|
if [[ "${ErrorLogLevel}" == "err" ]]; then
|
||||||
|
>&2 echo "${errMsg}"
|
||||||
|
fi
|
||||||
|
exit 2
|
||||||
|
else
|
||||||
|
jq < temp/optionChain.${symbol}.tmp.$$.json
|
||||||
|
rm temp/optionChain.${symbol}.tmp.$$.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
@@ -10,12 +10,7 @@ if [[ $? -ne 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
jq -r '.[].Symbol' allSymbols.json | sort | while read theSymbol; do
|
jq -r '.[].Symbol' allSymbols.json | sort | while read theSymbol; do
|
||||||
# I am not interested in detail quotes at the moment
|
#The result of XSP is too big causing a problem at the server, therefore limiting to future 400 days and splitting if needed
|
||||||
#./recordQuoteSingleSymbolSingleRun.sh ${theSymbol}
|
|
||||||
#if [[ $? -ne 0 ]]; then
|
|
||||||
# touch temp/hadErrors.$$.tmp
|
|
||||||
#fi
|
|
||||||
|
|
||||||
if [[ '$XSP' = ${theSymbol} ]]; then
|
if [[ '$XSP' = ${theSymbol} ]]; then
|
||||||
./recordOptionChainSingleSymbolSingleRun.sh -ErrorAsWarning ${theSymbol} toDate $(date "+%Y-%m-%d" -d "+400 days")
|
./recordOptionChainSingleSymbolSingleRun.sh -ErrorAsWarning ${theSymbol} toDate $(date "+%Y-%m-%d" -d "+400 days")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
@@ -29,14 +24,6 @@ jq -r '.[].Symbol' allSymbols.json | sort | while read theSymbol; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ '$SPX' = ${theSymbol} ]]; then
|
|
||||||
./recordOptionChainSingleSymbolSingleRun.sh -ErrorAsWarning ${theSymbol} fromDate $(date "+%Y-%m-%d" -d "+40 days") toDate $(date "+%Y-%m-%d" -d "+46 days")
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
touch temp/hadErrors.$$.tmp
|
|
||||||
fi
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
#Default behavior - fall back to stitching on error
|
#Default behavior - fall back to stitching on error
|
||||||
./recordOptionChainSingleSymbolSingleRun.sh -ErrorAsWarning ${theSymbol}
|
./recordOptionChainSingleSymbolSingleRun.sh -ErrorAsWarning ${theSymbol}
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user