NAME

POE::Component::Client::opentick - A POE component for working with opentick.com's market data feeds.

SYNOPSIS

 use POE qw( Component::Client::opentick );

 my $alias = 'otdemo';
 my $opentick = POE::Component::Client::opentick->spawn(
                    Username => 'MYUSER',       # REPLACE THIS
                    Password => 'MYPASS',       # REPLACE THIS
                    Events   => [ qw( all ) ],
                    Notifyee => $alias,
 );

 my $session = POE::Session->create(
     inline_states => {
         _start => sub {
             print "OT demo script starting up.\n";
             $poe_kernel->alias_set( $alias );
         },
         ot_on_login => sub {
             print "Logged in!\n";
             my $rid = $opentick->call( requestSplits =>
                                        'Q', 'MSFT',
                                        999999999, 1111111111 );
             print "ReqID $rid: requestSplits()\n";
         },
         ot_on_data  => sub {
             my ( $rid, $cmd, $record ) = @_[ARG0..$#_];
             print "ReqID $rid: Data: ", $record->as_string(), "\n";
         },
         ot_on_error => sub {
             my ( $rid, $cmd, $error ) = @_[ARG0..ARG2];
             print "ReqID $rid: Error: $error\n";
         },
     },
 );

 $poe_kernel->run();
 exit(0);

DESCRIPTION

POE::Component::Client::opentick allows you to easily interface with opentick.com's market data feed service using the power of POE to handle the asynchronous, simultaneous requests allowed with their protocol. This service provides both real-time and historical market data, much of it free of charge, other data based on subscriptions.

It is primarily designed as an interface library, for example, to log to a database, rather than a standalone client application to query market data, although it will work fine in both regards.

NOTE: This is primarily the documentation for the lower-level POE component itself. You may be looking for POE::Component::Client::opentick::OTClient, which is part of this distribution, and provides an opentick.com otFeed Standard API-compatible front-end interface for this component.

PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE

Please read the FAQ. It should answer 99% of your questions. Then come back here for comprehensive documentation on how to use the interface.

CONSTRUCTOR

spawn()

    my $opentick = POE::Component::Client::opentick->spawn(
            Username => 'Steve',        # Your opentick.com username
            Password => 'Zissou',       # Your opentick.com password
            Notifyee => 'myclient',     # POE alias of client session
            Events   => [ 'all' ],      # Arrayref of events to trap
    );

Spawn a new POE component, connect to the opentick server, log in, and get ready for action.

ARGUMENTS:

All arguments are of the hash form Var => Value. "spawn()" will complain and exit if they do not follow this form.

Username [ required ] (but see NOTE)
Password [ required ] (but see NOTE)

These are your login credentials for opentick.com. If you do not have an opentick.com account, please visit their website ("SEE ALSO") to create one. Note, that it is not necessarily a free service, but it is very inexpensive. (I don't work for them.)

NOTE: A username and password MUST be specified either as arguments to spawn() or via the "OPENTICK_USER" and/or "OPENTICK_PASS" environment variables (detailed in "ENVIRONMENT" below), or the component complain and throw an exception.

Events [ required ]
Notifyee [ required ]

Events is an arrayref of event notifications to send to the POE session alias specified by Notifyee. At the occurrence of various important events, this component will notify your session of its occurrence, with relevant data passed as arguments.

Both of these are mandatory.

For a list of events for which you can register, see the "EVENTS" section. The string 'all' works as a shortcut to just register for all events.

AutoLogin [ default: TRUE ]

Set to automatically log into the opentick server upon POE kernel startup.

NOTE: This does not affect automatic reconnection, which is set with the AutoReconnect option, and is disabled if you explicitly log out.

Realtime [ default: FALSE ]

Request real-time quote information. Pass in a TRUE value to enable it. It is implemented on their service by connecting you to a different port.

RawData [ default: FALSE ]

The default response to your queries from the opentick server comes to you as a POE::Component::Client::opentick::Record object, which has accessor methods and additional features you can use to examine the data, but if you prefer to receive simple @arrays, set this option to a TRUE value.

Alias [ default: opentick ]

The alias under which the opentick component will be registered within POE. See the POE documentation for further details.

Servers [ default: [ feed1.opentick.com, feed2.opentick.com ] ]

An arrayref of server hostnames with which to connect to the opentick service.

Port [ default: 10015 ]

The port number to which to connect. Two are default for the protocol: 10010 (realtime) and 10015 (delayed).

NOTE: If you specify a Port setting, it will be used regardless; otherwise the port is selected based on the Realtime setting (detailed next).

ConnTimeout [ default: 30 ]

Timeout in seconds before declaring this connection attempt to have failed.

NOTE: This also covers OT_LOGIN, so the actual timeout is from initiating the socket connection until reaching OT_STATUS_LOGGED_IN.

AutoReconnect [ default: TRUE ]

Boolean. Set TRUE to automatically reconnect to the server when disconnected, FALSE otherwise.

ReconnInterval [ default: 60 ]

Set to the delay you wish between attempts to automatically reconnect to the server.

Please be polite with this setting.

ReconnRetries [ default: 5 ]

Set to the number of times you wish to attempt to retry before giving up. (Set to 0 (zero) to try to reconnect forever, waiting ReconnInterval seconds between attempts.)

BindAddress [ default: undef ]
BindPort [ default: undef ]

Set these if you wish to bind to a specific local address and local port for outgoing connections, for instance, if you are running this on a multi-homed host. Leaving them blank will choose an arbitrary interface and port.

Don't bother using these unless you need them. You'll know if you do.

ProtocolVer [ default: 4 ]
MacAddr [ default: some 3Com address ]
Platform [ default: 1 (opentick) ]
PlatformPass [ default: '' ]
OS [ default: 20 (Linux) ]

Internal variables used for the opentick protocol itself. I have set sane defaults. Unless you REALLY know what you are doing and have read their protocol guide thoroughly, understand it, and know the constant values for these, just leave them alone.

If you tweak these and your account becomes disabled, don't blame me or ask me for support with the modified settings. Retest with the defaults.

Debug [ default: FALSE ]

Set to enable (lots of) debugging output from this component.

Quiet [ default: FALSE ]

Set to have the suite not print ANYTHING AT ALL (it doesn't much anyway, but you may get the occasional warning). The only way you will be able to receive status from the suite is via sending and receiving POE events.

RETURNS: blessed $object, or undef on failure.

initialize()

    $self->initialize();

Initialize the object. If you are subclassing, overload this, not "spawn()".

call()

post()

yield()

    $opentick->call( someevent => @args );
    $opentick->post( someevent => @args );
    $opentick->yield( someevent => @args );

These correspond to their POE counterparts, but automatically direct the events to the OpenTick session instead of requiring the extra argument of the target session (in the case of call() and post()).

They are useful as time-savers so you don't have to mess around with locating the POE session ID, passing in the POE alias, etc.

shutdown()

Logs out and disconnects from the opentick server, closes down the OT component, and eventually exits. You need to remove all references to the object in order to have it truly destroyed, of course.

After this, you must call "spawn()" again to create a new object/session.

ready()

    my $isready = $opentick->ready();

Returns BOOLEAN depending upon whether the OT component is ready to accept API requests (i.e., POE is running, the Session exists, is connected to the opentick.com server, and has successfully logged in).

Polling this would be silly. It would be better to just register to receive the "ot_on_login" or "ot_status_changed" events.

statistics()

    my @stats = $opentick->statistics();

Returns some statistics about the $opentick object and connection. More fields will be added over time, but right now it returns a list with the following fields:

0 packets sent
1 packets received
2 bytes sent
3 bytes received
4 messages sent
5 messages received
6 records received
7 errors received
8 object lifetime (in seconds)
9 opentick.com server connection time (in seconds)

new()

Nothing. Don't use this. Use "spawn()" instead.

get_status()

    my $status = $opentick->get_status();

Returns the current state of the object, as specified by the opentick protocol specification.

Possible states are:

1 - OT_STATUS_INACTIVE
2 - OT_STATUS_CONNECTING
3 - OT_STATUS_CONNECTED
4 - OT_STATUS_LOGGED_IN

See POE::Component::Client::opentick::Constants for more information.

get_uptime()

    my $uptime = $opentick->get_uptime();

Returns object lifetime in seconds.

login()

    $opentick->login();

Begin the login process.

logout()

    $opentick->logout();

Log out from the opentick server, and disconnect the socket.

set_hosts()

set_port()

set_platform_id()

These exist solely for higher-level compatibility with the otFeed Standard API. Don't use them. Pass arguments to the object constructor "spawn()" instead.

EVENTS

To do anything useful with this module, you must register to receive events upon important occurrences. You do this either by using the Events => [] argument to "spawn()" (preferred), or by sending a 'register' event to the object using POE, with an \@arrayref argument containing the list of events for which you wish to register.

All events sent to your session will receive at least the following two arguments:

 ( $request_id, $command_id ) = @_[ARG0,ARG1];

Specific events will also have more arguments. If an event receives different or additional arguments, they will be listed and described.

Below is a list of events for which you may register:

all

A time saver. Registers to receive all events. You don't even have to set up handlers for all of them, just the ones you want.

ot_on_login

Sent upon successful login to the opentick.com server.

ot_on_logout

Sent upon logout from the opentick.com server.

ot_on_data

Sent upon the receipt of data from a request you have placed.

Extra arguments: ( @data ) = @_[ARG2..$#_]

@data corresponds to the individual fields of the particular API call for which this is a response to. For more information on the API calls, see the "OPENTICK API" section below, as well as the http://www.opentick.com/ home page and documentation wiki.

ot_on_error

Sent upon any type of error.

Extra arguments: ( $Error ) = @_[ARG2]

$Error is an object of type POE::Component::Client::opentick::Error, and contains detailed information about the error, at what point it occurred, etc.

However, the object's stringify() method is overloaded, so it prints a meaningful and complete error message if you simply call something similar to print "$Error".

For more detailed documentation, see POE::Component::Client::opentick::Error.

ot_request_complete

Sent upon the completion of a request.

ot_request_cancelled

Sent upon the successful cancellation of a request.

ot_connect_failed

Sent upon failed connection and exhaustion of all retry attempts.

ot_status_changed

Sent upon any status change; will be sent as a duplicate request, alongside (but slightly later than) "ot_on_login".

Primarily exists for compatibility with OTClient.pm, but traps all status changes; not just login and logout.

OPENTICK API

The opentick.com API provides several commands that you may send. All of the API requests return a unique numeric $request_id for the particular command you issue. You properly send these commands by using the "call()" method (or the $poe_kernel->call() method with the session ID of the component), so that you receive a numeric $request_id as a return value. "yield()" and "post()" are asynchronous, and do not return a $request_id.

Because opentick is an asychronous protocol and allows multiple requests at once, getting this $request_id into your client is essential, to keep track of and match particular requests with their corresponding responses.

It is left as an exercise to the implementor (YOU!) as to how best keep track of these, although a %hash would work quite well. See the examples/ directory of this distribution for some examples of how to do this, if you are not sure.

I don't explain their protocol completely in this document. A link to their documentation is found under "SEE ALSO".

Arguments

Most commands take at least the following two arguments:

$exchange = STRING

The corresponding exchange code in the opentick.com format.

See http://www.opentick.com/dokuwiki/doku.php?id=general:exchange_codes for details.

$symbol = STRING

The corresponding symbol in the opentick.com format.

Use "requestListSymbols" if you actually want a list, otherwise these just generally correspond to the equity/security symbol from the exchange.

See http://www.opentick.com/dokuwiki/doku.php?id=general:symbol_formats for details.

Other Common Arguments

$startDate = EPOCH DATE
$endDate = EPOCH DATE

The time, in seconds, since Jan 1, 1970 00:00:00 UTC. This is the standard UNIX time format, as returned by the Perl function time().

Including Date/Time conversion routines in this component is out of scope. Please read "Why do you only accept UNIX epoch dates?" in POE::Component::Client::opentick::FAQ.

$expMonth = INTEGER (1-12)
$expYear = INTEGER (4-DIGIT YEAR)

Expiration month and year, as appropriate to the particular request.

$request_id = INTEGER

A numeric request, as previously returned from an API call. Usually used for stream cancellation.

$minStrike = REAL
$maxStrike = REAL

The minimum and maximum strike prices for which you wish to filter.

Most other arguments take a range of constants. See the opentick API documentation for further details.

Issuable Events

Here are the API-related events that you can issue to the POE component, which correspond to the opentick.com API:

requestSplits

ARGUMENTS: ( $exchange, $symbol, $startDate, $endDate );

requestDividends

ARGUMENTS: ( $exchange, $symbol, $startDate, $endDate );

requestOptionInit

ARGUMENTS: ( $exchange, $symbol, $expMonth, $expYear, $minStrike, $maxStrike, $paramsType );

requestHistData

ARGUMENTS: ( $exchange, $symbol, $startDate, $endDate, $datatype, $interval );

requestHistTicks

ARGUMENTS: ( $exchange, $symbol, $startDate, $endDate, $mask );

requestTickSnapshot

ARGUMENTS: ( $exchange, $symbol, $mask );

requestOptionChainU

ARGUMENTS: ( $exchange, $symbol, $expMonth, $expYear, $mask, $minStrike, $maxStrike, $paramsType );

requestOptionChainSnapshot

ARGUMENTS: ( $exchange, $symbol, $expMonth, $expYear, $mask, $minStrike, $maxStrike, $paramsType );

requestEquityInit

ARGUMENTS: ( $exchange, $symbol );

requestBookStream

ARGUMENTS: ( $exchange, $symbol );

requestBookStreamEx

ARGUMENTS: ( $exchange, $symbol, $mask );

requestHistBooks

ARGUMENTS: ( $exchange, $symbol, $startDate, $endDate, $mask );

requestTickStream

ARGUMENTS: ( $exchange, $symbol );

NOTE: Deprecated by opentick.com; use "requestTickStreamEx" instead.

requestTickStreamEx

ARGUMENTS: ( $exchange, $symbol, $mask );

requestOptionChain

ARGUMENTS: ( $exchange, $symbol, $expMonth, $expYear );

NOTE: Deprecated by opentick.com; use "requestOptionChainEx" instead.

requestOptionChainEx

ARGUMENTS: ( $exchange, $symbol, $expMonth, $expYear, $mask );

requestListExchanges

ARGUMENTS: ( NONE! )

NOTE: You will NOT receive an "ot_request_complete" event upon completion of this command.

requestListSymbols

ARGUMENTS: ( $exchange );

NOTE: You will NOT receive an "ot_request_complete" event upon completion of this command.

requestListSymbolsEx

ARGUMENTS: ( $exchange, $symbol, $mask );

$symbol in this instance acts as a filter, matching specified symbols as either a whole or a substring (depending on the value of $mask).

NOTE: You will NOT receive an "ot_request_complete" event upon completion of this command.

cancelTickStream

ARGUMENTS: ( $request_id )

cancelBookStream

ARGUMENTS: ( $request_id )

cancelOptionChain

ARGUMENTS: ( $request_id )

cancelHistData

ARGUMENTS: ( $request_id )

More information regarding the opentick API, exchange codes, field definitions, etc., can be found at http://www.opentick.com.

NOTE: Several of the opentick API commands return different than expected values for CommandType. Generally, these are commands that were implemented later, that extend functionality of earlier commands, and they return their base types. For example, "requestTickStreamEx" (cid=16) returns a CommandType of 3 ("requestTickStream"). You should keep this in mind when writing your result handlers. I could program around it, and I may in a later version, but as long as you keep track of requests by $requestID instead of CommandType (which you should anyway), it should not pose a problem.

ENVIRONMENT

This module suite uses the following environment variables:

OPENTICK_USER

OPENTICK_PASS

These are used as a fallback mechanism, in case Username or Password are not passed as arguments to "spawn()". If after exhausting these two possibilities, the username and password are not set, the suite will throw an exception and exit.

They are also provided as a security option, since many people do not desire to store passwords directly in their software.

OPENTICK_LIB

This is used in the official opentick otFeed Standard API software. This module suite will also use this environment variable when attempting to locate the original opentick library, to preload constant values used in the protocol.

POE::Component::Client::opentick::Constants attempts to load the original libraries from @INC, and will prepend the directory specified in OPENTICK_LIB to the @INC search path, if it is set.

If the original libraries are not found, this is not a problem; we use our own values. This is only an attempt to maintain derived compatibility with the mainline software itself should they suddenly change features between versions of this software.

LOGGING OUT AND SIGNALS

It would be polite to opentick.com, and follow their protocol, if you ensured that you always logged out before actually exiting your client application. I have included several methods of doing so, but I am hesitant to include a signal handler in this module, as that is really the responsibility of your client application.

An easy way to do this would be to use a signal handler similar to the following, to trap SIGINT, and repeat for whichever other signals you wish to trap:

    $poe_kernel->sig( INT  => 'event_quit' );
    $poe_kernel->sig( TERM => 'event_quit' );

    sub event_quit {
        $opentick->call( 'shutdown' );
        $poe_kernel->alias_remove( 'your_alias' );
        exit(1);
    }

More information about POE's signal handling can be found at "Signal Watcher Methods" in POE::Kernel.

While testing, they did not seem to mind me disconnecting improperly several times until I had finished the logout code, but I have no control over their decision-making process, and this could change at any time.

If your account gets banned, don't cry to me.

SEE ALSO

POE::Component::Client::opentick::FAQ

The POE documentation, POE::Kernel, POE::Session

http://poe.perl.org/ - All about the Perl Object Environment (POE)

http://www.opentick.com/ - The official opentick site

http://www.opentick.com/dokuwiki/doku.php - opentick.com's documentation

The examples/ directory of this module's distribution.

ACKNOWLEDGEMENTS

Thank you, Rocco Caputo (dngor) for inventing and unleashing POE upon the world!

AUTHOR

Please kindly read the FAQ before emailing me with questions. Your answer is probably in there.

Jason McManus (INFIDEL) - infidel AT cpan.org

LICENSE

Copyright (c) Jason McManus

This module may be used, modified, and distributed under the same terms as Perl itself. Please see the license that came with your Perl distribution for details.

The data from opentick.com are under an entirely separate license that varies according to exchange rules, etc. It is your responsibility to follow the opentick.com and exchange license agreements with the data.

Further details are available on http://www.opentick.com/.