Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a2acbef03 | ||
|
|
d39996da0a | ||
|
|
abd53bce27 | ||
|
|
aeb332c15a | ||
|
|
d44ae664e8 | ||
|
|
25a01025b8 | ||
| 366ea11345 | |||
| d727655cdf | |||
|
|
2f94bac950 | ||
|
|
aa8b22a843 | ||
|
|
996f4a45df | ||
|
|
39e4eee1ec | ||
|
|
1bc359941b | ||
|
|
3fecb1b491 | ||
| bf662f2c75 | |||
| 79dd6881af | |||
| 45aef7a228 | |||
| e035c4cf71 | |||
| 9cdb599cf4 | |||
| ea57723a3c | |||
| cd7870f3dd | |||
| 4ecadfc7cd | |||
| cef7b771ca | |||
| 2feccc3a29 | |||
| b85dd30dc3 | |||
| 774c17d6e8 | |||
| a3360dda67 | |||
| 328e6b200b | |||
| 1ab04cae3e | |||
| 2010a0134f | |||
| 80b3485138 | |||
| fcc9512515 | |||
| befc693db3 | |||
| eced8d59b6 | |||
| f127f20a1f | |||
| bdbf88cde1 | |||
| 7e167cfe7e | |||
| bf78fb7c40 | |||
| 89c110ac38 | |||
| d8ca3ee20d | |||
| b6ec9ec1f1 | |||
| 27cf19f7b1 | |||
| 1bd4e89a68 | |||
| 14e340b724 | |||
|
|
36cec493b0 | ||
|
|
4853a0238d | ||
|
|
137df14462 | ||
|
|
cb287aee83 | ||
|
|
e7f8964c62 | ||
|
|
98da51a404 | ||
|
|
beab7a3ca8 | ||
|
|
87a760f4f5 | ||
|
|
a6bcc9a34d | ||
|
|
8899f7138e | ||
|
|
0c9025e564 | ||
|
|
44fa6b23f2 | ||
|
|
7784b587e9 |
@ -2,8 +2,9 @@ FROM python:3.7-alpine
|
|||||||
MAINTAINER Andrew Sotheran <cryptosky.user@gmail.com>
|
MAINTAINER Andrew Sotheran <cryptosky.user@gmail.com>
|
||||||
RUN apk update && \
|
RUN apk update && \
|
||||||
apk add py-pip libc-dev gcc
|
apk add py-pip libc-dev gcc
|
||||||
|
RUN python -m pip install --upgrade pip
|
||||||
RUN pip install utils pycryptodome && \
|
RUN pip install utils pycryptodome && \
|
||||||
pip install python-dotenv coinbase flask
|
pip install python-dotenv coinbase flask schedule numpy stomp.py python-json-logger
|
||||||
COPY . /home/price-collector/.
|
COPY . /home/price-collector/.
|
||||||
EXPOSE 9090
|
EXPOSE 9090
|
||||||
CMD ["python", "/home/price-collector/src/main.py"]
|
CMD ["python", "/home/price-collector/src/main.py"]
|
||||||
@ -8,7 +8,7 @@ metadata:
|
|||||||
name: RESOURCE_NAME
|
name: RESOURCE_NAME
|
||||||
namespace: production
|
namespace: production
|
||||||
spec:
|
spec:
|
||||||
replicas: 0
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: RESOURCE_NAME
|
app: RESOURCE_NAME
|
||||||
@ -19,6 +19,8 @@ spec:
|
|||||||
maxUnavailable: 0
|
maxUnavailable: 0
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
|
annotations:
|
||||||
|
linkerd.io/inject: enabled
|
||||||
labels:
|
labels:
|
||||||
app: RESOURCE_NAME
|
app: RESOURCE_NAME
|
||||||
spec:
|
spec:
|
||||||
@ -40,14 +42,24 @@ spec:
|
|||||||
resource: limits.memory
|
resource: limits.memory
|
||||||
- name: DATABASE_URL
|
- name: DATABASE_URL
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
configMapKeyRef:
|
||||||
name: endpoints
|
name: endpoints
|
||||||
key: dbGateway.url
|
key: dbGateway.url
|
||||||
- name: DATABASE_PORT
|
- name: AMQ_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: endpoints
|
||||||
|
key: amqStomp.url
|
||||||
|
- name: BROKER_USER
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: endpoints
|
name: amq
|
||||||
key: dbGateway.port
|
key: amq.username
|
||||||
|
- name: BROKER_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: amq
|
||||||
|
key: amq.password
|
||||||
- name: COINBASE_KEY
|
- name: COINBASE_KEY
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
@ -60,7 +72,7 @@ spec:
|
|||||||
key: coinbase.api.secret
|
key: coinbase.api.secret
|
||||||
- name: DB_GATEWAY_URL
|
- name: DB_GATEWAY_URL
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
configMapKeyRef:
|
||||||
name: endpoints
|
name: endpoints
|
||||||
key: dbGateway.url
|
key: dbGateway.url
|
||||||
ports:
|
ports:
|
||||||
@ -87,11 +99,11 @@ spec:
|
|||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 10m
|
|
||||||
memory: 16Mi
|
|
||||||
limits:
|
|
||||||
cpu: 25m
|
cpu: 25m
|
||||||
memory: 32Mi
|
memory: 32Mi
|
||||||
|
limits:
|
||||||
|
cpu: 25m
|
||||||
|
memory: 64Mi
|
||||||
securityContext:
|
securityContext:
|
||||||
capabilities:
|
capabilities:
|
||||||
add:
|
add:
|
||||||
|
|||||||
@ -28,7 +28,7 @@ try {
|
|||||||
timestamps {
|
timestamps {
|
||||||
node ("${env.SLAVE_LABEL}") {
|
node ("${env.SLAVE_LABEL}") {
|
||||||
stage('Initialise') {
|
stage('Initialise') {
|
||||||
checkout([$class: 'GitSCM', branches: [[name: 'master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'Github', url: 'https://github.com/andyjk15/price-collector.git']]])
|
checkout([$class: 'GitSCM', branches: [[name: 'master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'Github', url: env.GIT_REPOSITORY_URL]]])
|
||||||
|
|
||||||
env.APPLICATION_VERSION = get_application_version()
|
env.APPLICATION_VERSION = get_application_version()
|
||||||
|
|
||||||
@ -41,20 +41,11 @@ try {
|
|||||||
) {
|
) {
|
||||||
sh "doctl auth init --access-token ${DOCTL_TOKEN}"
|
sh "doctl auth init --access-token ${DOCTL_TOKEN}"
|
||||||
sh "doctl registry login"
|
sh "doctl registry login"
|
||||||
sh "doctl kubernetes cluster kubeconfig save cryptosky-kubernetes-cluster"
|
sh "doctl kubernetes cluster kubeconfig save cryptosky-cluster"
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Test Artifact') {
|
|
||||||
try {
|
|
||||||
// mvn 'verify -DskipUTs -DskipTests'
|
|
||||||
} finally {
|
|
||||||
// mvn 'test'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Build Image') {
|
stage('Build Image') {
|
||||||
// mvn 'clean package -DskipTests'
|
|
||||||
|
|
||||||
executeShellScript("configuration/scripts/mapVarsToConfigs.sh",
|
executeShellScript("configuration/scripts/mapVarsToConfigs.sh",
|
||||||
env.DIGITAL_OCEAN,
|
env.DIGITAL_OCEAN,
|
||||||
@ -63,10 +54,6 @@ try {
|
|||||||
env.APPLICATION_VERSION,
|
env.APPLICATION_VERSION,
|
||||||
env.APPLICATION_LABEL)
|
env.APPLICATION_LABEL)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Tag Repository') {
|
|
||||||
|
|
||||||
withDockerServer([uri: "${env.DOCKER_REPOSITORY_TCP}"]) {
|
withDockerServer([uri: "${env.DOCKER_REPOSITORY_TCP}"]) {
|
||||||
docker.build("${env.APPLICATION_NAME}:${env.APPLICATION_VERSION}")
|
docker.build("${env.APPLICATION_NAME}:${env.APPLICATION_VERSION}")
|
||||||
docker.build("${env.APPLICATION_NAME}:latest")
|
docker.build("${env.APPLICATION_NAME}:latest")
|
||||||
@ -78,6 +65,10 @@ try {
|
|||||||
sh "docker push ${env.DOCKER_REPOSITORY}/${env.APPLICATION_NAME}:latest"
|
sh "docker push ${env.DOCKER_REPOSITORY}/${env.APPLICATION_NAME}:latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Tag Repository') {
|
||||||
|
|
||||||
withCredentials(
|
withCredentials(
|
||||||
[usernamePassword(
|
[usernamePassword(
|
||||||
credentialsId: env.GITHUB_CREDENTIALS_ID,
|
credentialsId: env.GITHUB_CREDENTIALS_ID,
|
||||||
|
|||||||
@ -5,6 +5,4 @@ APPLICATION_NAME=$1
|
|||||||
kubectl apply -f configuration/kubernetes/deployment.yaml
|
kubectl apply -f configuration/kubernetes/deployment.yaml
|
||||||
kubectl apply -f configuration/kubernetes/service.yaml
|
kubectl apply -f configuration/kubernetes/service.yaml
|
||||||
|
|
||||||
kubectl get pods
|
|
||||||
|
|
||||||
kubectl rollout status deployment/${APPLICATION_NAME} --namespace=production
|
kubectl rollout status deployment/${APPLICATION_NAME} --namespace=production
|
||||||
@ -6,6 +6,8 @@ sys.path.append('/home/price-collector/')
|
|||||||
from threading import Thread
|
from threading import Thread
|
||||||
from pricing.collector import collectorMain
|
from pricing.collector import collectorMain
|
||||||
|
|
||||||
|
from src.utils.jsonLogger import setup_logging
|
||||||
|
|
||||||
from probes.probes import runFlaskProbes
|
from probes.probes import runFlaskProbes
|
||||||
|
|
||||||
def callCollector(args):
|
def callCollector(args):
|
||||||
@ -15,6 +17,7 @@ def callProbes():
|
|||||||
runFlaskProbes()
|
runFlaskProbes()
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
|
setup_logging()
|
||||||
|
|
||||||
Thread(target=callProbes).start()
|
Thread(target=callProbes).start()
|
||||||
|
|
||||||
|
|||||||
@ -7,30 +7,24 @@ import schedule
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from pricing.bitfinex import bitfinexPublicTicker, bitfinexVolAskBid
|
from pricing.exchanges.bitfinex import bitfinexPublicTicker, bitfinexVolAskBid
|
||||||
from pricing.coinbase import coinbasePublicTicker
|
from pricing.exchanges.gemini import geminiPublicTicker, geminiVolAskBid, geminiDailyOpenClose
|
||||||
from pricing.gemini import geminiPublicTicker, geminiVolAskBid, geminiDailyOpenClose
|
from pricing.exchanges.bitstamp import bitstampVolAskBid, bitstampHighLow, bitstampOpenClose
|
||||||
from pricing.bitstamp import bitstampVolAskBid, bitstampHighLow, bitstampOpenClose
|
from pricing.exchanges.kraken import krakenVolAskBid, krakenHighLow, krakenOpenClose
|
||||||
from pricing.kraken import krakenVolAskBid, krakenHighLow, krakenOpenClose
|
|
||||||
|
|
||||||
from src.utils.databaseConnect import send
|
# from src.utils.databaseConnect import send
|
||||||
|
from src.utils.activemqConnect import activeMQSender
|
||||||
|
|
||||||
import logging as logger
|
import json, uuid
|
||||||
|
|
||||||
logger.basicConfig(
|
from src.utils.jsonLogger import log
|
||||||
level=logger.INFO,
|
|
||||||
format="%(asctime)s: %(levelname)s -- %(message)s",
|
|
||||||
datefmt='%Y-%m-%d %H:%M:%S'
|
|
||||||
)
|
|
||||||
|
|
||||||
btc_usd="/home/price-collector/src/resources/queries/V1_INSERT_NEW_PRICE_RECORD_BTC.graphql"
|
|
||||||
|
|
||||||
def averager(type):
|
def averager(type):
|
||||||
|
|
||||||
timestamp = datetime.datetime.now()# + timedelta(hours=1)
|
timestamp = datetime.datetime.now() + datetime.timedelta(hours=1)
|
||||||
|
|
||||||
bitstampH, bitstampL = bitstampHighLow(type, logger)
|
bitstampH, bitstampL = bitstampHighLow(type, log)
|
||||||
krakenH, krakenL = krakenHighLow(type, logger)
|
krakenH, krakenL = krakenHighLow(type, log)
|
||||||
|
|
||||||
bitstamp_P = (bitstampH + bitstampL)/2
|
bitstamp_P = (bitstampH + bitstampL)/2
|
||||||
kraken_P = (krakenH + krakenL)/2
|
kraken_P = (krakenH + krakenL)/2
|
||||||
@ -40,23 +34,25 @@ def averager(type):
|
|||||||
|
|
||||||
averagePrice = round(averagePrice, 2)
|
averagePrice = round(averagePrice, 2)
|
||||||
|
|
||||||
logger.info("Hourly Price for ({}) is {}".format(timestamp ,averagePrice))
|
log("Hourly Price for ({}) is {}".format(timestamp ,averagePrice), 'INFO')
|
||||||
|
|
||||||
return averagePrice, timestamp
|
return averagePrice, timestamp
|
||||||
|
|
||||||
def getVol(type):
|
def getVol(type):
|
||||||
bitV, bitA, bitB = bitstampVolAskBid(type, logger)
|
bitV, bitA, bitB = bitstampVolAskBid(type, log)
|
||||||
kV, kA, kB = krakenVolAskBid(type, logger)
|
kV, kA, kB = krakenVolAskBid(type, log)
|
||||||
|
bV, bA, bB = bitfinexVolAskBid(type, log)
|
||||||
|
gV, gA, gB = geminiVolAskBid(type, log)
|
||||||
|
|
||||||
v_array = np.array([bitV, kV])
|
v_array = np.array([bitV, kV, bV, gV])
|
||||||
|
|
||||||
volume = v_array[np.nonzero(v_array)].mean()
|
volume = v_array[np.nonzero(v_array)].mean()
|
||||||
|
|
||||||
return volume
|
return volume
|
||||||
|
|
||||||
def getHighLow(type):
|
def getHighLow(type):
|
||||||
kH, kL = krakenHighLow(type, logger)
|
kH, kL = krakenHighLow(type, log)
|
||||||
bH, bL = bitstampHighLow(type, logger)
|
bH, bL = bitstampHighLow(type, log)
|
||||||
|
|
||||||
h_array = np.array([kH, bH])
|
h_array = np.array([kH, bH])
|
||||||
l_array = np.array([kL, bL])
|
l_array = np.array([kL, bL])
|
||||||
@ -67,8 +63,8 @@ def getHighLow(type):
|
|||||||
return high, low
|
return high, low
|
||||||
|
|
||||||
def getOpenClose(type):
|
def getOpenClose(type):
|
||||||
bO, bC = bitstampOpenClose(type, logger)
|
bO, bC = bitstampOpenClose(type, log)
|
||||||
kO, kC = krakenOpenClose(type, logger)
|
kO, kC = krakenOpenClose(type, log)
|
||||||
|
|
||||||
o_array = np.array([bO, kO])
|
o_array = np.array([bO, kO])
|
||||||
c_array = np.array([bC, kC])
|
c_array = np.array([bC, kC])
|
||||||
@ -78,31 +74,57 @@ def getOpenClose(type):
|
|||||||
|
|
||||||
return open, close
|
return open, close
|
||||||
|
|
||||||
def sendToGateway(c_type, timestamp, av_price, high, low, vol, o_price, c_price):
|
# def sendToGateway(c_type, timestamp, av_price, high, low, vol, o_price, c_price):
|
||||||
|
#
|
||||||
|
# with open(btc_usd, 'r') as file:
|
||||||
|
# data = file.read()
|
||||||
|
#
|
||||||
|
# strippedTimestamp = timestamp.replace(minute=0, second=0, microsecond=0)
|
||||||
|
# timestamp = '"'+strippedTimestamp.strftime('%Y-%m-%dT%H:%M:%S')+'"'
|
||||||
|
# type = '"'+c_type+'"'
|
||||||
|
#
|
||||||
|
# query = data % (timestamp, type, round(av_price, 2),
|
||||||
|
# round(high, 2),
|
||||||
|
# round(low, 2),
|
||||||
|
# round(o_price, 2),
|
||||||
|
# round(c_price, 2),
|
||||||
|
# round(vol, 2))
|
||||||
|
#
|
||||||
|
# log("Query sending down to db-gateway -- ({})".format(query), 'INFO')
|
||||||
|
|
||||||
with open(btc_usd, 'r') as file:
|
# status, response = send(query, log)
|
||||||
data = file.read()
|
|
||||||
|
|
||||||
timestamp = '"'+timestamp.strftime('%Y-%m-%dT%H:%M:%S')+'"'
|
# if status != 200:
|
||||||
type = '"'+c_type+'"'
|
# log("Query wasn't executed properly, view logs. Status = {}".format(status), 'WARN')
|
||||||
|
# log("With Response of : {}".format(response), 'ERR')
|
||||||
|
# else:
|
||||||
|
# log("Query executed successfully with Status = {}".format(status), 'INFO')
|
||||||
|
# log("With Response of : {}".format(response), 'INFO')
|
||||||
|
|
||||||
query = data % (timestamp, type, round(av_price, 2),
|
def sentToArtemis(c_type, timestamp, av_price, high, low, vol, o_price, c_price):
|
||||||
round(high, 2),
|
|
||||||
round(low, 2),
|
|
||||||
round(o_price, 2),
|
|
||||||
round(c_price, 2),
|
|
||||||
round(vol, 2))
|
|
||||||
|
|
||||||
logger.info("Query sending down to db-gateway -- ({})".format(query))
|
strippedTimestamp = timestamp.replace(minute=0, second=0, microsecond=0)
|
||||||
|
timestamp = strippedTimestamp.strftime('%Y-%m-%dT%H:%M:%S')
|
||||||
|
|
||||||
status, response = send(query, logger)
|
message = {
|
||||||
|
"timestamp" : timestamp,
|
||||||
|
"type" : c_type,
|
||||||
|
"average_price" : av_price,
|
||||||
|
"high_price" : high,
|
||||||
|
"low_price" : low,
|
||||||
|
"open_price": o_price,
|
||||||
|
"close_price" : c_price,
|
||||||
|
"volume" : vol
|
||||||
|
}
|
||||||
|
|
||||||
if status != 200:
|
messageJson = json.dumps(message, indent = 4)
|
||||||
logger.critical("Query wasn't executed properly, view logs. Status = {}".format(status))
|
|
||||||
logger.error("With Response of : {}".format(response))
|
syncId = uuid.uuid4()
|
||||||
else:
|
|
||||||
logger.info("Query executed successfully with Status = {}".format(status))
|
log("Sending message to PricingSave queue", 'INFO', syncId)
|
||||||
logger.info("With Response of : {}".format(response))
|
log("Message: {}".format(message), 'INFO', syncId)
|
||||||
|
|
||||||
|
activeMQSender(messageJson, syncId)
|
||||||
|
|
||||||
def timeFunction():
|
def timeFunction():
|
||||||
global time
|
global time
|
||||||
@ -123,20 +145,21 @@ def collector(c_type):
|
|||||||
global time
|
global time
|
||||||
time = timeFunction()
|
time = timeFunction()
|
||||||
|
|
||||||
print(time)
|
|
||||||
|
|
||||||
av_price, timestamp = averager(c_type)
|
av_price, timestamp = averager(c_type)
|
||||||
vol = getVol(c_type)
|
vol = getVol(c_type)
|
||||||
high, low = getHighLow(c_type)
|
high, low = getHighLow(c_type)
|
||||||
o_price, c_price = getOpenClose(c_type)
|
o_price, c_price = getOpenClose(c_type)
|
||||||
|
|
||||||
sendToGateway(c_type, timestamp, av_price, high, low, vol, o_price, c_price)
|
sentToArtemis(c_type, timestamp, av_price, high, low, vol, o_price, c_price)
|
||||||
|
# sendToGateway(c_type, timestamp, av_price, high, low, vol, o_price, c_price)
|
||||||
|
|
||||||
schedule.every().hour.at(time).do(collector, c_type).tag("collector")
|
schedule.every().hour.at(time).do(collector, c_type).tag("collector")
|
||||||
|
|
||||||
|
log("Collection will run again at {} every hour".format(time), 'INFO')
|
||||||
|
|
||||||
# Dynamically Spin up Child process for each type wanting to track
|
# Dynamically Spin up Child process for each type wanting to track
|
||||||
def collectorMain(c_type):
|
def collectorMain(c_type):
|
||||||
logger.info("== Historical Price Collector ==")
|
log("Starting Historical Price Collector", 'INFO')
|
||||||
|
|
||||||
collector(c_type)
|
collector(c_type)
|
||||||
|
|
||||||
|
|||||||
0
src/pricing/exchanges/__init__.py
Normal file
0
src/pricing/exchanges/__init__.py
Normal file
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import requests, json, sys
|
import requests, json, sys
|
||||||
|
|
||||||
def bitfinexPublicTicker(type, logger):
|
def bitfinexPublicTicker(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://api.bitfinex.com/v2/tickers?symbols=" + "t"+type.upper().replace('_', '')
|
uri = "https://api.bitfinex.com/v2/tickers?symbols=" + "t"+type.upper().replace('_', '')
|
||||||
|
|
||||||
@ -13,11 +13,11 @@ def bitfinexPublicTicker(type, logger):
|
|||||||
price = round(price, 2)
|
price = round(price, 2)
|
||||||
return price
|
return price
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Bitfinex Spot Price Error: {}".format(e))
|
log("Bitfinex Spot Price Error: {}".format(e), 'ERR')
|
||||||
price = 0
|
price = 0
|
||||||
return price
|
return price
|
||||||
|
|
||||||
def bitfinexVolAskBid(type, logger):
|
def bitfinexVolAskBid(type, log):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
uri = "https://api.bitfinex.com/v2/tickers?symbols=" + "t"+type.upper().replace('_', '')
|
uri = "https://api.bitfinex.com/v2/tickers?symbols=" + "t"+type.upper().replace('_', '')
|
||||||
@ -32,5 +32,5 @@ def bitfinexVolAskBid(type, logger):
|
|||||||
|
|
||||||
return vol, ask, bid
|
return vol, ask, bid
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Bitfinex High Low Volume Error: {}".format(e))
|
log("Bitfinex High Low Volume Error: {}".format(e), 'ERR')
|
||||||
return 0, 0, 0
|
return 0, 0, 0
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import requests, json, sys
|
import requests, json, sys
|
||||||
|
|
||||||
def bitstampVolAskBid(type, logger):
|
def bitstampVolAskBid(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://www.bitstamp.net/api/v2/ticker_hour/" + type.lower().replace('_', '') + "/"
|
uri = "https://www.bitstamp.net/api/v2/ticker_hour/" + type.lower().replace('_', '') + "/"
|
||||||
response = requests.request("GET", uri)
|
response = requests.request("GET", uri)
|
||||||
@ -14,10 +14,10 @@ def bitstampVolAskBid(type, logger):
|
|||||||
|
|
||||||
return vol, ask, bid
|
return vol, ask, bid
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Bitstamp Volume Ask Bid Error: {}".format(e))
|
log("Bitstamp Volume Ask Bid Error: {}".format(e), 'ERR')
|
||||||
return 0, 0, 0
|
return 0, 0, 0
|
||||||
|
|
||||||
def bitstampOpenClose(type, logger):
|
def bitstampOpenClose(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://www.bitstamp.net/api/v2/ticker_hour/" + type.lower().replace('_', '') + "/"
|
uri = "https://www.bitstamp.net/api/v2/ticker_hour/" + type.lower().replace('_', '') + "/"
|
||||||
response = requests.request("GET", uri)
|
response = requests.request("GET", uri)
|
||||||
@ -28,10 +28,10 @@ def bitstampOpenClose(type, logger):
|
|||||||
|
|
||||||
return open, close
|
return open, close
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Bitstamp Open Close Error: {}".format(e))
|
log("Bitstamp Open Close Error: {}".format(e), 'ERR')
|
||||||
return 0, 0, 0
|
return 0, 0
|
||||||
|
|
||||||
def bitstampHighLow(type, logger):
|
def bitstampHighLow(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://www.bitstamp.net/api/v2/ticker_hour/" + type.lower().replace('_', '') + "/"
|
uri = "https://www.bitstamp.net/api/v2/ticker_hour/" + type.lower().replace('_', '') + "/"
|
||||||
response = requests.request("GET", uri)
|
response = requests.request("GET", uri)
|
||||||
@ -42,5 +42,5 @@ def bitstampHighLow(type, logger):
|
|||||||
|
|
||||||
return high, low
|
return high, low
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Bitstamp Open Close Error: {}".format(e))
|
log("Bitstamp Open Close Error: {}".format(e), 'ERR')
|
||||||
return 0, 0, 0
|
return 0, 0
|
||||||
@ -10,7 +10,7 @@ class keys():
|
|||||||
self.api_key = os.getenv('COINBASE_KEY')
|
self.api_key = os.getenv('COINBASE_KEY')
|
||||||
self.api_secret = os.getenv("COINBASE_SECRET")
|
self.api_secret = os.getenv("COINBASE_SECRET")
|
||||||
|
|
||||||
def coinbasePublicTicker(type, logger):
|
def coinbasePublicTicker(type, log):
|
||||||
|
|
||||||
api_key = keys().api_key
|
api_key = keys().api_key
|
||||||
api_secret = keys().api_secret
|
api_secret = keys().api_secret
|
||||||
@ -24,6 +24,6 @@ def coinbasePublicTicker(type, logger):
|
|||||||
price = round(price, 2)
|
price = round(price, 2)
|
||||||
return price
|
return price
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Coinbase Spot Price Error: {}".format(e))
|
log("Coinbase Spot Price Error: {}".format(e), 'ERR')
|
||||||
price = 0
|
price = 0
|
||||||
return price
|
return price
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import requests, json, sys
|
import requests, json, sys
|
||||||
|
|
||||||
def geminiPublicTicker(type, logger):
|
def geminiPublicTicker(type, log):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
uri = "https://api.gemini.com/v1/pubticker/" + type.lower().replace('_', '')
|
uri = "https://api.gemini.com/v1/pubticker/" + type.lower().replace('_', '')
|
||||||
@ -15,11 +15,11 @@ def geminiPublicTicker(type, logger):
|
|||||||
|
|
||||||
return price
|
return price
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Gemini Spot Price Error: {}".format(e))
|
log("Gemini Spot Price Error: {}".format(e), 'ERR')
|
||||||
price = 0
|
price = 0
|
||||||
return price
|
return price
|
||||||
|
|
||||||
def geminiVolAskBid(type, logger):
|
def geminiVolAskBid(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://api.gemini.com/v2/ticker/" + type.lower().replace('_', '')
|
uri = "https://api.gemini.com/v2/ticker/" + type.lower().replace('_', '')
|
||||||
response = requests.request("GET", uri)
|
response = requests.request("GET", uri)
|
||||||
@ -36,20 +36,20 @@ def geminiVolAskBid(type, logger):
|
|||||||
|
|
||||||
return vol, ask, bid
|
return vol, ask, bid
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Gemini Volume Ask Bid Error: {}".format(e))
|
log("Gemini Volume Ask Bid Error: {}".format(e), 'ERR')
|
||||||
return 0, 0, 0
|
return 0, 0, 0
|
||||||
|
|
||||||
def geminiDailyOpenClose(type, logger):
|
def geminiDailyOpenClose(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://api.gemini.com/v2/ticker/" + type.lower().replace('_', '')
|
uri = "https://api.gemini.com/v2/ticker/" + type.lower().replace('_', '')
|
||||||
response = requests.request("GET", uri)
|
response = requests.request("GET", uri)
|
||||||
response = json.loads(response.text)
|
response = json.loads(response.text)
|
||||||
|
|
||||||
dailyOpen = round(float(response['open']), 2)
|
open = round(float(response['open']), 2)
|
||||||
dailyClose = round(float(response['close']), 2)
|
close = round(float(response['close']), 2)
|
||||||
|
|
||||||
return open, close
|
return open, close
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Gemini Open Close Error: {}".format(e))
|
log("Gemini Open Close Error: {}".format(e), 'ERR')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
return 0, 0
|
return 0, 0
|
||||||
@ -21,7 +21,7 @@ def krakenCalculateOHLC(response):
|
|||||||
|
|
||||||
return fopen, fhigh, flow, fclose
|
return fopen, fhigh, flow, fclose
|
||||||
|
|
||||||
def krakenVolAskBid(type, logger):
|
def krakenVolAskBid(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://api.kraken.com/0/public/Ticker?pair=" + type.upper().replace('_', '').replace('BTC', 'XBT')
|
uri = "https://api.kraken.com/0/public/Ticker?pair=" + type.upper().replace('_', '').replace('BTC', 'XBT')
|
||||||
response = requests.request("GET", uri)
|
response = requests.request("GET", uri)
|
||||||
@ -37,10 +37,10 @@ def krakenVolAskBid(type, logger):
|
|||||||
|
|
||||||
return vol, ask, bid
|
return vol, ask, bid
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Kraken Volume Ask Bid Error: {}".format(e))
|
log("Kraken Volume Ask Bid Error: {}".format(e), 'ERR')
|
||||||
return 0, 0, 0
|
return 0, 0, 0
|
||||||
|
|
||||||
def krakenOpenClose(type, logger):
|
def krakenOpenClose(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://api.kraken.com/0/public/OHLC?pair=" + type.upper().replace('_', '').replace('BTC', 'XBT') + "&?interval\=60"
|
uri = "https://api.kraken.com/0/public/OHLC?pair=" + type.upper().replace('_', '').replace('BTC', 'XBT') + "&?interval\=60"
|
||||||
response = requests.request("GET", uri)
|
response = requests.request("GET", uri)
|
||||||
@ -53,10 +53,10 @@ def krakenOpenClose(type, logger):
|
|||||||
|
|
||||||
return fopen, fclose
|
return fopen, fclose
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Kraken Open Close Error: {}".format(e))
|
log("Kraken Open Close Error: {}".format(e), 'ERR')
|
||||||
return 0, 0, 0
|
return 0, 0, 0
|
||||||
|
|
||||||
def krakenHighLow(type, logger):
|
def krakenHighLow(type, log):
|
||||||
try:
|
try:
|
||||||
uri = "https://api.kraken.com/0/public/OHLC?pair=" + type.upper().replace('_', '').replace('BTC', 'XBT') + "&?interval\=60"
|
uri = "https://api.kraken.com/0/public/OHLC?pair=" + type.upper().replace('_', '').replace('BTC', 'XBT') + "&?interval\=60"
|
||||||
response = requests.request("GET", uri)
|
response = requests.request("GET", uri)
|
||||||
@ -69,5 +69,5 @@ def krakenHighLow(type, logger):
|
|||||||
|
|
||||||
return fhigh, flow
|
return fhigh, flow
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error("Kraken Open Close Error: {}".format(e))
|
log("Kraken Open Close Error: {}".format(e), 'ERR')
|
||||||
return 0, 0
|
return 0, 0
|
||||||
@ -4,14 +4,7 @@ from flask import Flask
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from pricing.coinbase import coinbasePublicTicker
|
from pricing.exchanges.coinbase import coinbasePublicTicker
|
||||||
|
|
||||||
import logging as logger
|
|
||||||
logger.basicConfig(
|
|
||||||
level=logger.INFO,
|
|
||||||
format="%(asctime)s: %(levelname)s -- %(message)s",
|
|
||||||
datefmt='%Y-%m-%d %H:%M:%S'
|
|
||||||
)
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@ -22,7 +15,7 @@ def health():
|
|||||||
@app.route('/readiness')
|
@app.route('/readiness')
|
||||||
def readiness():
|
def readiness():
|
||||||
# Can it make a call to an exchange?
|
# Can it make a call to an exchange?
|
||||||
price = coinbasePublicTicker('btc_usd', logger)
|
price = coinbasePublicTicker('btc_usd')
|
||||||
|
|
||||||
if price != 0 :
|
if price != 0 :
|
||||||
return json.dumps({
|
return json.dumps({
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
mutation { createBtc(createdDate: %s, type: %s, average_price: %f, high_price: %f, low_price: %f, open_price: %f, close_price: %f, volume: %f){ id } }
|
|
||||||
0
src/utils/__init__.py
Normal file
0
src/utils/__init__.py
Normal file
36
src/utils/activemqConnect.py
Normal file
36
src/utils/activemqConnect.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import stomp
|
||||||
|
import os
|
||||||
|
|
||||||
|
from src.utils.jsonLogger import log
|
||||||
|
|
||||||
|
class keys():
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.uri = os.getenv("AMQ_URL")
|
||||||
|
self.amqU = os.getenv("BROKER_USER")
|
||||||
|
self.amqP = os.getenv("BROKER_PASSWORD")
|
||||||
|
self.addr = self.uri.split(':')[0]
|
||||||
|
self.port = self.uri.split(':')[1]
|
||||||
|
|
||||||
|
def returnKeys(self):
|
||||||
|
return self.addr, self.port, self.amqU, self.amqP
|
||||||
|
|
||||||
|
def activeMQSender(message, syncId):
|
||||||
|
addr, port, mqUser, mqPass = keys().returnKeys()
|
||||||
|
|
||||||
|
log("Attempting Connection to Artemis...", 'INFO', syncId)
|
||||||
|
con = stomp.Connection([(addr, port)], auto_content_length=False)
|
||||||
|
con.connect( mqUser, mqPass, wait=True)
|
||||||
|
|
||||||
|
con.send("PricingSave",
|
||||||
|
message,
|
||||||
|
content_type="application/json",
|
||||||
|
headers={
|
||||||
|
"Content-Type":"application/json",
|
||||||
|
"X-CRYPTO-Sync-ID":syncId
|
||||||
|
})
|
||||||
|
|
||||||
|
con.disconnect()
|
||||||
|
|
||||||
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
import requests, os, json, sys
|
import requests, os, json, sys
|
||||||
|
|
||||||
|
from src.utils.jsonLogger import log
|
||||||
|
|
||||||
class keys():
|
class keys():
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.uri = os.getenv("DATABASE_URL")
|
self.uri = os.getenv("DATABASE_URL")
|
||||||
self.port = os.getenv("DATABASE_PORT")
|
|
||||||
|
|
||||||
def send(query, logger):
|
def send(query):
|
||||||
try:
|
try:
|
||||||
uri = keys().uri + "/graphql"
|
uri = keys().uri + "/graphql"
|
||||||
headers = {'Content-type': 'application/json'}
|
headers = {'Content-type': 'application/json'}
|
||||||
@ -20,8 +21,8 @@ def send(query, logger):
|
|||||||
|
|
||||||
return statusCode, response
|
return statusCode, response
|
||||||
except requests.exceptions.HTTPError as e:
|
except requests.exceptions.HTTPError as e:
|
||||||
logger.critical("Unable to send data down to db-gateway: {}".format(e))
|
log("Unable to send data down to db-gateway: {}".format(e), 'ERR')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
logger.critical("Unable to send data down to db-gateway: {}".format(e))
|
log("Unable to send data down to db-gateway: {}".format(e), 'ERR')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
40
src/utils/jsonLogger.py
Normal file
40
src/utils/jsonLogger.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from pythonjsonlogger import jsonlogger
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
class CustomJsonFormatter(jsonlogger.JsonFormatter):
|
||||||
|
def add_fields(self, log_record, record, message_dict):
|
||||||
|
super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
|
||||||
|
if not log_record.get('@timestamp'):
|
||||||
|
# this doesn't use record.created, so it is slightly off
|
||||||
|
now = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')
|
||||||
|
log_record['@timestamp'] = now
|
||||||
|
if log_record.get('level'):
|
||||||
|
log_record['level'] = log_record['level'].upper()
|
||||||
|
else:
|
||||||
|
log_record['level'] = record.levelname
|
||||||
|
|
||||||
|
def setup_logging(log_level='INFO'):
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.propagate = 0
|
||||||
|
logger.setLevel(log_level)
|
||||||
|
logHandler = logging.StreamHandler()
|
||||||
|
|
||||||
|
formatter = CustomJsonFormatter('%(@timestamp)s %(level)s %(name)s %(message)s')
|
||||||
|
|
||||||
|
logHandler.setFormatter(formatter)
|
||||||
|
logger.addHandler(logHandler)
|
||||||
|
|
||||||
|
def log(message, level, syncId=""):
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
if level == 'INFO':
|
||||||
|
logger.info(message, extra={"X-CRYPTO-Sync-ID" : syncId})
|
||||||
|
elif level == 'WARN':
|
||||||
|
logger.warn(message, extra={"X-CRYPTO-Sync-ID" : syncId})
|
||||||
|
elif level == 'ERR':
|
||||||
|
logger.error(message, extra={"X-CRYPTO-Sync-ID" : syncId})
|
||||||
|
elif level == 'DEBUG':
|
||||||
|
logger.debug(message, extra={"X-CRYPTO-Sync-ID" : syncId})
|
||||||
Loading…
x
Reference in New Issue
Block a user