Appcelerator Blog

The Leading Resource for All Things Mobile

Appcelerator Node.ACS Financial Stock Watch List

0 Flares 0 Flares ×
Implementing a Financial Stock Watch List may seem pretty straightforward at first, but optimizing it for mobile in the most efficient way possible presents a few challenges. Today, I’d like to walk you through how you can use the Appcelerator Mobile Platform to streamline API calls and data over the wire for your mobile applications leveraging remote data sources. Appcelerator Custom Cloud Service (Node.ACS) allows Node.js based custom services to be published into the cloud and can be used to create a middleware tier to expose mobile-optimized web services to your application. Instead of making multiple calls from the Titanium mobile client directly to the stock quote web service, we will create a Node.js service which will make multiple calls to a back end Stock Quote web service over the high speed internet and present aggregated data to the Titanium mobile client. The Titanium mobile client can then make a single mobile optimized web service call to Node.ACS over the slower cellular network to retrieve the Stock Watch List data. Furthermore, since the Watch List only displays 3 data values from the 13 provided by the stock quote web service, a substantial reduction in overhead is achieved which results in improved user experience and reduced data transmission. The Problem The mobile watch list we are trying to create is shown below:
The Stock Watch List displays a list of Stock Symbols as well as the Last Price and Change (from the prior day) for each stock symbol in the list. The “As of” time and date is useful to display as well so the user can see when the stock data was last retrieved. The stock web service used in this example is from Markit On Demand. In order to implement the watch list, repeated calls to a stock quote web service needs to be made; one call for each stock symbol the user is “watching”. The data then needs to be assembled and applied to a list control (i.e. TableView). Below is an example of a stock quote REST web service call and JSON reply from MarkitOnDemand for the stock symbol AAPL (Apple Inc): Call:   http://dev.markitondemand.com/Api/Quote/json?symbol=AAPL Reply:
{
	"Data":{
		"Name":"Apple Inc", "Symbol":"AAPL", "LastPrice":424.04,
                "Change":-3.36899999999997,
		"ChangePercent":-0.788237964104632,
		"Timestamp":"Tue Jan 22 10:58:00 UTC-07:00 2012",
		"MarketCap":395266765800,
                "Volume":263809,
		"ChangeYTD":402.64,
                "ChangePercentYTD":5.31492151798133,
                "High":424.99,
		"Low":423.22,
		"Open":424.86
	}
}
From the reply above, you can see that we only need 3 of the 13 values returned by the web service for our watch list: LastPrice, Change and Timestamp. While these calls can be made from the Titanium mobile client, there is a large amount of overhead due to the unused data returned by the web service. Also, these calls are made across the often slow and unreliable cellular network as illustrated in the diagram below:
SOLUTION One solution to this problem is to change the application architecture so that the watch list is retrieved by Appcelerator’s Node.ACS Platform as a Service (PaaS). Then the Titanium mobile client only needs to make one web service call to Node.ACS to retrieve the watch list data. The Node.ACS service makes the repeated calls to the Stock Quote web service to collect the watch list data but it does this across the high speed Internet instead of the slow cellular network as illustrated below:
The custom Node.ACS service is shown below. Note that an additional feature in this Node.ACS service is that the Watch List symbols are retrieved from ACS Custom Object. This enables watch lists to be maintained across mobile devices.
var ACS = require('acs').ACS;
var logger = require('acs').logger;
var EventEmitter = require('events').EventEmitter;
var https = require('http');
var sessionID = null;
var stocks;
ACS.init('', ''); // use your ACS OAuth key and secret

function refreshPrice(req, res) {
    var uid = req.query.uid;
    var Event = new EventEmitter;
    var results = [],
        evt_count = 0;
    // SETUP EVENT LISTENER
    Event.on("HTTP_COMPLETE", function (e) {
        console.log("EVENT: HTTP_COMPLETE");
        evt_count++;
        console.log(evt_count);
        if (evt_count >= stocks.length) {
            console.log("close response, results = " + JSON.stringify(results));
            res.write(JSON.stringify(results));
            res.end();
        }
    });
    ACS.Objects.query({
        page: 1,
        per_page: 100,
        classname: "stocks",
        where: {
            user_id: uid,
        }
    }, function (data) {
        console.log(JSON.stringify(data));
        stocks = data.stocks;
        var l = stocks.length;
        if (l == 0) {
            Event.emit("HTTP_COMPLETE");
        };
        for (var i = 0; i < l; i++) {
            marketOnDemandQuote(stocks[i].symbol);
        }
    })

    function marketOnDemandQuote(symbol) {
        var myreq =
            https.get('http://dev.markitondemand.com/Api/Quote/json?symbol=' + symbol, function (r) {
            r.setEncoding('utf8');
            r.on('data', function (chunk) {
                console.log(chunk);
                var o = {}, d = JSON.parse(chunk);
                o.symbol = d.Data.Symbol;
                o.name = d.Data.Name;
                o.lastPrice = d.Data.LastPrice;
                o.change = d.Data.Change;
                o.changePercent = d.Data.ChangePercent;
                o.timestamp = d.Data.Timestamp;
                results.push(o);
                Event.emit("HTTP_COMPLETE");
            });
        });
    }
};
exports.refreshPrice = refreshPrice;
// Source code attribution: Asim Siddiqui and Bert Grantges
Conclusion Appcelerator’s Node.ACS Platform as a Service can be used to build mobile optimized middleware services in Node.js. The middleware service reduces the overhead in retrieving the watch list data by making repeated calls to a stock quote web service and presents the aggregated data that the mobile application needs. This results in improved user experience and reduced latency and throughput requirements of the mobile application. While this example was designed around a stock watch list, the principles can be applied to many other use cases such as sales flash reports, key performance indicator dashboards and other applications where the back end data is not optimized for the mobile application or when data needs to be mashed up from disparate back end data sources. The Node.ACS online documentation is a good next step for learning about Appcelerator Custom Cloud Service and can be found here: http://docs.appcelerator.com/titanium/latest/#!/guide/Node.ACS
0 Flares Twitter 0 Facebook 0 Google+ 0 LinkedIn 0 Email -- 0 Flares ×

8 Comments

  1. Joe

    Superb!! I’ve been looking for Node.ACS examples. Much Thanks.

  2. MarkitOnDemand link is broken.

  3. Joe

    I’ve been trying to implement the Node.ACS project, with some success, though I’m blocked somewhere, this is what I’ve done:

    1- Created new Node.ACS Project ‘NodeFinanDemo’

    2- Added a New Service ‘refreshPrice’ & pasted the code above, and updated the ACS Oath & Secret key, and created a Custom Object to a user ‘stocks’ with a property called ‘symbol’ and value ‘APPL’.

    3- Published App & got a full url:https://.cloudapp.appcelerator.com

    4- Created a New Mobile App ‘NodeACSAppConnection’

    5- Imported the Node Project into a FirstView.js

    6- I see the code that got added to FirstView.js:
    ~~~
    // @autogenerated:start:ti.cloud.NodeFinanDemo
    var NodeFinanDemo = require(“ti.cloud.NodeFinanDemo”);
    // @autogenerated:end:ti.cloud.NodeFinanDemo
    var Cloud = require(‘ti.cloud’);

    function FirstView() {
    var self = Ti.UI.createView();

    Cloud.Users.login({
    login: ‘default’, // the user who owns the ‘stocks’ object
    password: ‘*******’
    }, function (e) {
    if (e.success) {
    var user = e.users[0];
    NodeFinanDemo.refreshPrice({ }, function (_e) {
    Ti.API.info(_e);
    });
    } else {
    alert(‘Error:n’ + ((e.error && e.message) || JSON.stringify(e)));
    }
    });
    return self;
    }

    module.exports = FirstView;
    ~~~

    7- No idea how to call the refreshPrice?

    Note: I breakpointed the line `NodeFinanDemo.refreshPrice` and peaked into NodeFinanDemo:
    URL: “http://localhost:53945” // shouldn’t this be https://.cloudapp…com ?
    uri: “app://ti.cloud.NodeFinanDemo.js”
    id: “ti.cloud.NodeFinanDemo”

    Also if I run the code above, I get a runtime error:
    message = “‘undefined’ is not a function (evaluating ‘NodeFinanDemo.refreshPrice({ }, function (_e) {n Ti.API.info(_e);n })’)”;

  4. Leor Brenman

    @joe

    You can find a more complete code sample at:

    https://github.com/lbrenman/MyStockPublic

    Check out the readme under the app folder

    I hope this helps

    (you will need to replace your ACS keys and Node.ACS URL)

  5. Sarat

    Hi,
    I am looking for a tutorial on database access. I tried http://docs.appcelerator.com/cloud/latest/#!/guide/node_samples_mongodb, but the line :
    mongoserver = new mongodb.Server(host, port, server_options)

    is tripping me up. where do I install the mongo db instance? how do I connect to it? Any input (and sample code) would be greatly appreciated

  6. shameerjan

    How can i connect mongodb and titanium studio node acs? can you give me any document ?

Comments are closed.

Sign up for updates!

Become a mobile leader. Take the first step to scale mobile innovation throughout your enterprise.
Get in touch
computer and tablet showing Appcelerator software
Start free, grow from there.
0 Flares Twitter 0 Facebook 0 Google+ 0 LinkedIn 0 Email -- 0 Flares ×