Event Driven Push Notification - Step 2
Description
In this Example we are going to modify the previous exercise by adding some rest calls to alphavantage finance API.
In particular, we want to study the performance of a stock through the 50-day average value and quickly report the best times to buy or sell the title under exam. The 50-day average value is a popular technical indicator which investors use to analyze price trends. You can calculate the 50-day moving average by taking the average of closing price over the last 50 days [(Day 1 + Day 2 + Day 3 + … + Day 49 + Day 50)/50].
When the current value of a title falls below the 50-day average value it’s a sign of a crisis for that title and it’s necessary to sell as soon as possible to avoid further losses. Conversely, when the value exceeds the 50-day average value, it’s convenient to buy before further increases.
System setup
We have to set up two rest-call elements to Alphavantage finance API in order to retrive the quotation trend and the historical quotes. But first, we need to define a new System:
Create a new System called “Finance” and a new Channel with the following attributes:
- endpoint = https://www.alphavantage.co
- type = RESTAdapter
- id-channel = ApiFinance
rest-call: HistoricalQuotes
This rest call has the task to retrive from Alphavantage finance API the last 50 daily adjusted close values.
- Insert into the channel “ApiFinance” a rest-call operation and name it HistoricalQuotes
- Now set HistoricalQuotes’s attributes:
- type = call
- method = GET
- name = HistoricalQuotes
- request-uri = /query
- Set up HistoricalQuotes subelements:
- parameters
- param(name: symbol, value: MSFT)
- param(name: outputsize, value: compact)
- param(name: function, value: TIME_SERIES_DAILY_ADJUSTED)
- param(name: apikey, value: YOUR_FREE_ALPHAVANTAGE_API_KEY)
Click here to get your ALPHAVANTAGE_API_KEY
- parameters
rest-call: QuotationTrend
This rest call has the task to retrive the last two values in order to know if the title is rising or falling.
- Insert into the channel “ApiFinance” a rest-call operation and name it QuotationTrend.
- Now set QuotationTrend’s attributes:
- type = call
- method = GET
- name = QuotationTrend
- request-uri = /query
- Set up QuotationTrend subelements:
- parameters
- param(name: symbol, value: MSFT)
- param(name: outputsize, value: compact)
- param(name: function, value: TIME_SERIES_INTRADAY)
- param(name: apikey, value: YOUR_FREE_ALPHAVANTAGE_API_KEY)
- param(name: interval, value: 1min)
- parameters
Flow setup
Once the System Finance is created we can start to build up the flow. So, create a new Service called FinanceService, a new Operation called Threshold, then open the flow editor.
Now you have to create a flow like this:
Flow nodes
getToken (ChangeGVBufferNode)
This node has the task to extract data from the incoming json and setup FCM_DEVICE_TOKEN property thet we need to send notifications:
- id = getToken
- input = input
- next-node-id = getQuotationTrend
- ChangeGVBufferNode:
- PropertyDef:
-
name = FCM_DEVICE_TOKEN
-
value = json{{fcm_device_token}}
-
- PropertyDef:
getQuotationTrend (GVOperationNode)
This node makes rest call to Alphavantage finance API to retrive the two last values of the index under exam, using QuotationTrend operation in the Finance System created before:
- id = getQuotationTrend
- id-channel = ApiFinance
- id-system = Finance
- input = input
- next-node-id = check1
- operation-name = QuotationTrend
- op-type = call
- OutputService (OutputService)
- retrive (script-service)
- retrive (script-call)
- Script (Script)
var str = new java.lang.String(data.getObject()); var payload = JSON.parse(str); var s = payload["Time Series (1min)"]; var keys = []; for(var k in s) keys.push(k); var last = keys[0]; var prev = keys[1]; var x = parseFloat(payload["Time Series (1min)"][last]["4. close"]); var y = parseFloat(payload["Time Series (1min)"][prev]["4. close"]); data.setProperty('DATE', last); data.setProperty('LAST_TICK', x); data.setProperty('PREV_TICK', y);
- retrive (script-call)
- retrive (script-service)
check1 (GVNodeCheck)
This node just check if the previous operation it was successful:
- default-id = getHistoricalQuotes
- id = check1
- input = input
- on-exception-id = error
getHistoricalQuotes (GVOperationNode)
This node makes rest call to Alphavantage finance API to retrive the average of the last 50 adjusted close daily values, using Historical Quotes operation in the Finance System created before:
- id = getHistoricalQuotes
- id-channel = ApiFinance
- id-system = Finance
- input = input
- next-node-id = check2
- operation-name = HistoricalQuotes
- op-type = call
- OutputService (OutputService)
- script (script-service)
- script (script-call)
- Script (Script)
var str = new java.lang.String(data.getObject()); var payload = JSON.parse(str); var s = payload["Time Series (Daily)"]; var keys = []; var daysCD = 0; var total = 0; for(var k in s) keys.push(k); for(var k in s){ daysCD+=1; if(daysCD<=50){ total+=parseFloat(payload["Time Series (Daily)"][k]["5. adjusted close"]); } } data.setProperty('AVG', (total/50));
- script (script-call)
- script (script-service)
check2 (GVNodeCheck)
This node just check if the previous operation it was successful:
- default-id = comparator
- id = check2
- input = input
- on-exception-id = error
error (GVEndNode)
This node return the result of the operation in case of failure:
- id = error
- output = input
comparator (ChangeGVBufferNode)
This node contains the logic to determinate if the index under exam should be bought, or be sold it. In the other cases it will returns Nothing to report.
- id = comparator
- input = input
- next-node-id = prepareJson
- ChangeGVBufferNode:
- Script:
var lastTick = parseFloat(data.getProperty('LAST_TICK')); var prevTick = parseFloat(data.getProperty('PREV_TICK')); var avg = parseFloat(data.getProperty('AVG')); if ( lastTick > prevTick && lastTick>avg && prevTick<avg) { data.setProperty('MESSAGE', 'Buy!'); } else if (lastTick < prevTick && lastTick<avg && prevTick>avg){ data.setProperty('MESSAGE', 'Sell!'); } else { data.setProperty('MESSAGE', 'Nothing to report.') }
prepareJson (ChangeGVBufferNode)
This node has the task to build the json file that will be sent to PushNotification service:
- id = prepareJson
- input = input
- next-node-id = pushNotificationCall
- ChangeGVBufferNode:
- Script:
var js = { "date":data.getProperty('DATE'), "message":data.getProperty('MESSAGE'), "fcm_device_token":data.getProperty('FCM_DEVICE_TOKEN') }; data.setObject(JSON.stringify(js));
pushNotificationCall (GVCoreCall)
This node just send the json to PushNotification service:
- id = pushNotificationCall
- id-service = PushNotification
- input = input
- next-node-id = end
- operation = Send
end (GVEndNode)
This node return the result of the operation in case of success.
- id = end
- output = input
Testing with GV Console
Now you are able to test your VulCon Service from the GV Console® once exported the configuration.
So, let’s start GreenVulcano® ESB, access to the GV Console and deploy your Vulcon project setting your apikey.
Once the configuration is deployed you can finally test it. Go to Execute section end select Threshold operation. To send a notify you have to insert a Json string. The device token is the code that you can find in the web app:
{ "fcm_device_token":"YOUR_FCM_DEVICE_TOKEN" }
Now you can reiceve notifications by your Android App:
Note: In case of error or exceptions you can check the file GVCore.log situated in the folder GV_HOME/data/log/.
Download
Here you can download the configuration: