File Coverage

blib/lib/Finance/OATS.pm
Criterion Covered Total %
statement 40 233 17.1
branch 3 32 9.3
condition 1 2 50.0
subroutine 9 15 60.0
pod 3 11 27.2
total 56 293 19.1


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Finance::OATS - Stub of a Perl extension to support generating OATS records
4              
5             =head1 SYNOPSIS
6              
7             use Finance::OATS qw(:all);
8              
9             $MPID = "TEST";
10             $OSOID= 9999;
11              
12             # all variables must be set before first call to AddNewAndRoute and
13             # friends
14              
15             # call AddNewAndRoute and AddCancel a bunch of times
16              
17             # closes last FORE file
18             CloseFOREFile();
19              
20              
21             =head1 DESCRIPTION
22              
23             Simple module to generate ROE records for OATS and package them up
24             into FORE files.
25              
26             =head1 SEE ALSO
27              
28             The NASDR OATS website, at L
29              
30             =head1 EXPORT
31              
32             None by default.
33              
34             AddNewAndRoute
35             AddCancel
36              
37             CloseFOREFile
38              
39             And a bunch of variables which can be used to tweak settings; settings must be tweaked before
40             first call to AddNewAndRoute or AddCancel.
41              
42             =head1 AUTHOR
43              
44             Mike Giroux, rmgiroux@acm.org
45              
46             =head1 COPYRIGHT AND LICENSE
47              
48             Copyright (C) 2006 by Mike Giroux and Wang Trading, LLC
49              
50             This library is free software; you can redistribute it and/or modify
51             it under the terms of the General Public License version 2, a.k.a. GPLv2.
52              
53             See L file for details.
54              
55             =head1 CREDITS AND DISCLAIMER
56              
57             This library is released under the GPL with the kind permission of
58             Dr. Meng-Yuan Wang, the Managing Partner of Wang Trading, LLC.
59              
60             This library is a STUB. It's the beginnings of an OATS implementation,
61             but it is far from complete. Many of the ROE fields contain hard-coded
62             values which may not be appropriate to your case; please check them
63             carefully!
64              
65             Neither Wang Trading, M-Y Wang, nor Mike Giroux is responsible nor
66             liable for any problems which may arise through the use of this library.
67              
68             YOU are RESPONSIBLE for any files you upload to NASDR. _YOU_ are liable
69             for fines if they are wrong. Please be very careful!
70              
71             At a minimum, use the NASDR OATS test site and make sure everything looks
72             good.
73              
74             See the TBD comments.
75              
76             =cut
77              
78             package Finance::OATS;
79              
80             require 5.005_62;
81 1     1   23485 use strict;
  1         2  
  1         58  
82 1     1   4 use warnings;
  1         2  
  1         30  
83              
84 1     1   5 use Carp qw(cluck confess);
  1         6  
  1         3015  
85              
86             require Exporter;
87              
88             our @ISA = qw(Exporter);
89              
90             # Items to export into callers namespace by default. Note: do not export
91             # names by default without a very good reason. Use EXPORT_OK instead.
92             # Do not simply export all your public functions/methods/constants.
93              
94             # This allows declaration use Finance::OATS ':all';
95             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
96             # will save memory.
97             our %EXPORT_TAGS = ( 'all' => [ qw(
98             $MPID
99             $OSOID
100             $UserID
101             $Password
102             $FOREByteLimit
103             $sep
104             $FOREPrefix
105             AddNewAndRoute
106             AddCancel
107             AddCancelReplace
108             GenerateFOREFiles
109             ) ] );
110              
111             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
112              
113             our @EXPORT = qw(
114              
115             );
116              
117             our $VERSION = '0.11';
118              
119             our $MPID = 'TEST';
120             our $OSOID = 999;
121              
122             our $UserID = "user";
123             our $Password = "pass";
124             #our $Password = "";
125              
126             our $FOREByteLimit = 1_450_000;
127              
128             # NASDR allows many different field separators,
129             # so choose the one you like.
130             our $sep=',';
131              
132             # fore files will have names starting with this prefix
133             our $FOREPrefix = "fore";
134              
135              
136             sub GetDateStamp {
137 1     1 0 145 my ($yr, $mn, $dy) = (localtime)[5,4,3];
138 1         3 $yr+=1900;
139 1         2 $mn++;
140              
141 1         8 sprintf("%04d%02d%02d",$yr,$mn,$dy);
142             }
143              
144             my $dateStamp = GetDateStamp();
145              
146             my $lastROEIdNo = 1;
147             my $roePrefix = 'WA';
148              
149             sub GetNextROEID {
150 0     0 0 0 my $id = sprintf("%2s%010d",$roePrefix, $lastROEIdNo);
151              
152 0         0 ++$lastROEIdNo;
153              
154              
155 0 0       0 if($lastROEIdNo > 9_999_999_999) {
156 0         0 $lastROEIdNo = 1;
157 0         0 $roePrefix++;
158             }
159              
160 0         0 return $id;
161             }
162              
163             my $lastFOREIdNo = 1;
164              
165             sub GetNextFOREId {
166 2     2 0 14 sprintf("${FOREPrefix}.${dateStamp}_%04d",$lastFOREIdNo++);
167             }
168              
169             =head2 sub AddNewAndRoute
170              
171             Generates New Order and Route events for a new order
172              
173             Arguments:
174             Symbol => 'MSFT',
175             Side => 'B', # or 'S', or 'SS', or 'SX'
176             OrderID=> 'AISL-123', # our order ID
177             Time => 'HHMMSS', # order timestamp
178             Price => '12.12345', # price, in dollars, to 7 decimal places if need be
179             Shares => 1200, # size, in shares
180             MPID => 'ISLD', # sent-to MPID (opt., def ISLD)
181             OtherID=> '123432', # exchange order ID
182             Date => 'yyyymmdd', # optional, defaults to today
183             IOC => 'IOC', # optional, specified if order is IOC
184             Visible=> 'Y', # optional, 'Y' or 'N'
185             # ******* TBD: LIST OUT OF DATE!!!! ***********
186             RouteType=> 'C', # 38) Routing method code (defaults to 'C')
187             # E routed elec to member firm
188             # C routed to ECN
189             # L routed to SelectNet
190             # N routed non-electronic to memb firm
191             # M routed to non-member firm
192             # O routed to SuprtSOES
193             # P routed to Primex
194             # S routed to SOES
195             # X routed to exchange
196             ProgramTradingCode=>'Y',# optional, 'Y' or 'N'
197             IndexArbCode=>'N', # optional, 'Y' or 'N'
198             PriceType=>'LIM', # optional, 'LIM' or 'MKT'
199              
200             =cut
201              
202             sub AddNewAndRoute {
203 0     0 1 0 my %defaults = (
204             MPID => 'ISLD',
205             RecvMPID=> '',
206             Visible => 'Y',
207             Date => $dateStamp,
208             IOC => '',
209             RouteType => 'C',
210             ProgramTradingCode => 'Y',
211             IndexArbCode => 'N',
212             PriceType => 'LIM',
213             CancelTimeStamp => '',
214             CancelledBy => ''
215             );
216 0         0 my %args = (%defaults, @_);
217              
218 0         0 foreach my $key (qw(Symbol Side OrderID Time Price Shares)) {
219 0 0       0 cluck "Missing argument '$key'" unless exists $args{$key};
220             }
221              
222 0         0 my $ROE;
223 0         0 my $ROEId=GetNextROEID();
224              
225             # Combined order/route record spec in Oats Technical Reporting ,
226             # Specifications Appendix C, pages C-19 to C-22.
227 0         0 $ROE="#OE#${sep}"; # 1) Order event record (OE)
228 0         0 $ROE.="OR${sep}"; # 2) Order event type (OR)
229 0         0 $ROE.="N${sep}"; # 3) Action type code (N/C/D/R)
230 0         0 $ROE.="$ROEId${sep}"; # 4) Firm ROE ID
231 0         0 $ROE.="${sep}"; # 5) corr/del TS
232 0         0 $ROE.="${sep}"; # 6) Rej ROE resub flag
233             #$ROE.="$MPID${sep}"; # 7) Receiving firm MPID
234             #$ROE.="${sep}"; # 7) Receiving firm MPID (blank if same)
235 0         0 $ROE.="$args{RecvMPID}${sep}"; # 7) Receiving firm MPID (blank if same)
236 0         0 $ROE.=sprintf("%08d000000${sep}",$args{Date}); # 8) Order received date
237 0         0 $ROE.="$args{OrderID}${sep}"; # 9) receiving firm order ID
238 0         0 $ROE.="${sep}"; # 10) Routing firm MPID
239 0         0 $ROE.="${sep}"; # 11) Routed order ID
240 0         0 $ROE.=sprintf("%08d%06s${sep}",$args{Date},$args{Time}); #12)Order received time
241 0         0 $ROE.="E${sep}"; # 13) received method code
242 0         0 $ROE.="$args{Symbol}${sep}"; # 14) Symbol
243 0         0 $ROE.="$args{Side}${sep}"; # 15) Buy/Sell code, B|S|SS|SX
244 0 0       0 if($args{PriceType} eq "LIM") {
245 0         0 $ROE.="$args{Price}${sep}"; # 16) Limit price
246             }
247             else {
248 0         0 $ROE.="${sep}"; # 16) Limit price
249             }
250 0         0 $ROE.="$args{Visible}${sep}"; # 17) Limit order display indicator
251 0         0 $ROE.="${sep}"; # 18) Stop price
252 0 0       0 if($args{PriceType} eq "LIM") {
253 0         0 $ROE.="DAY${sep}"; # 19) TIF
254             }
255             else {
256 0         0 $ROE.="${sep}"; # 19) TIF
257             }
258 0         0 $ROE.="${sep}"; # 20) Expiration date
259 0         0 $ROE.="${sep}"; # 21) Expiration time
260 0         0 $ROE.="${sep}"; # 22) Do not reduce/do not increase code
261 0         0 $ROE.="$args{IOC}${sep}"; # 23) First special handling code
262 0         0 $ROE.="${sep}"; # 24) 2nd special handling code
263 0         0 $ROE.="${sep}"; # 25) 3rd special handling code
264 0         0 $ROE.="${sep}"; # 26) 4th special handling code
265 0         0 $ROE.="${sep}"; # 27) 5th special handling code
266 0         0 $ROE.="${sep}"; # 28) receiving terminal ID
267 0         0 $ROE.="${sep}"; # 29) receiving dept ID
268 0         0 $ROE.="${sep}"; # 30) originating dept ID
269 0         0 $ROE.="W${sep}"; # 31) acct type code (Wholesale)
270 0         0 $ROE.="$args{ProgramTradingCode}${sep}"; # 32) program trading code
271 0         0 $ROE.="$args{IndexArbCode}${sep}"; # 33) arbitrage code
272 0         0 $ROE.="$args{OrderID}${sep}"; # 34) Sent to routed order ID
273 0         0 $ROE.="$args{MPID}${sep}"; # 35) Sent to firm MPID
274 0         0 $ROE.=sprintf("%08d%06s${sep}",$args{Date},$args{Time}); # 36)Order sent time
275 0         0 $ROE.="$args{Shares}${sep}"; # 37) Routed Shares Quantity
276 0         0 $ROE.="E${sep}"; # 38) Route type
277             # E Electronic
278             # M Manual
279             #$ROE.="${sep}"; # 39: bunched order indicator
280 0         0 $ROE.="${sep}"; # 39: bunched order indicator
281 0         0 $ROE.="N${sep}"; # 40: Member type code (N Non-Member Firm)
282             # TBD: LIST POSSIBLY OUT OF DATE!
283 0         0 $ROE.="$args{RouteType}${sep}"; # 41: Destination code
284             # E ecn
285             # L selectnet
286             # M Member firm
287             # N non member firm
288             # P Primex
289             # U Supermontage
290             # X Exchange
291 0         0 $ROE.="${sep}"; # 42: ECN flag
292 0         0 $ROE.="$args{CancelTimeStamp}${sep}";
293             # 43: Cancel time stamp, if order fully cancelled
294 0         0 $ROE.="$args{CancelledBy}"; # 44: Cancelled by flag, C or F
295 0         0 $ROE.="\n"; # 45: end of record marker (LF or CRLF)
296              
297 0         0 WriteROE($ROE);
298             }
299              
300             =head2 sub AddCancel
301              
302             Generates New Order and Route events for a new order
303              
304             Arguments:
305             Symbol => 'MSFT',
306             OrderID=> 'AISL-123', # our order ID
307             Time => 'HHMMSS', # order timestamp
308             CancelType=> 'F', # 'F'ull or 'P'artial, defaults to F
309             SharesCanceled => 1200, # shares canceled
310             SharesRemaining => 100, # shares canceled
311             MPID => 'ISLD', # sent-to MPID (opt., def ISLD)
312             Date => 'yyyymmdd', # optional, defaults to today
313              
314             =cut
315              
316             sub AddCancel {
317 0     0 1 0 my %defaults = (
318             MPID => 'ISLD',
319             RecvMPID=> '',
320             Date => $dateStamp,
321             CancelType => 'F',
322             SharesCanceled => '',
323             SharesRemaining => '',
324             );
325 0         0 my %args = (%defaults, @_);
326              
327 0         0 foreach my $key (qw(Symbol OrderID Time)) {
328 0 0       0 cluck "Missing argument '$key'" unless exists $args{$key};
329             }
330              
331             # 2004-12-08, this is wrong interpretation of "P"artial
332             # 2004-12-09, if partial, sharesCanceled must be present
333 0 0       0 if($args{CancelType} eq 'P') {
334 0 0       0 if(!exists $args{SharesCanceled}) {
335 0         0 $args{SharesCanceled}=0;
336             }
337             }
338              
339 0         0 my $ROE;
340 0         0 my $ROEId=GetNextROEID();
341              
342             # Cancel order record spec in Oats Technical Reporting Specifications,
343             # Appendix C, page C-14
344 0         0 $ROE="#OE#${sep}"; # 1) Order event record (OE)
345 0         0 $ROE.="CL${sep}"; # 2) Order event type (CL)
346 0         0 $ROE.="N${sep}"; # 3) Action type code (N/C/D/R)
347 0         0 $ROE.="$ROEId${sep}"; # 4) Firm ROE ID
348 0         0 $ROE.="${sep}"; # 5) corr/del TS
349 0         0 $ROE.="${sep}"; # 6) Rej ROE resub flag
350             #$ROE.="$MPID${sep}"; # 7) Receiving firm MPID
351             #$ROE.="${sep}"; # 7) Receiving firm MPID (blank if same)
352 0         0 $ROE.="$args{RecvMPID}${sep}"; # 7) Receiving firm MPID (blank if same)
353 0         0 $ROE.=sprintf("%08d000000${sep}",$args{Date}); # 8) Order received date
354 0         0 $ROE.="$args{OrderID}${sep}"; # 9) receiving firm order ID
355 0         0 $ROE.="$args{Symbol}${sep}"; # 10) Symbol
356 0         0 $ROE.=sprintf("%08d%06s${sep}",$args{Date},$args{Time}); #11)Order received time
357 0         0 $ROE.="$args{CancelType}${sep}"; # 12) Shares quantity
358 0         0 $ROE.="$args{SharesCanceled}${sep}"; # 13) Cancel Quantity
359 0         0 $ROE.="$args{SharesRemaining}${sep}"; # 14) Cancel leaves qty
360 0         0 $ROE.="C${sep}"; # 15) Canceled by flag 'C'ust or 'F'irm
361 0         0 $ROE.=""; # 16) Originating MPID (as of 20021213)
362 0         0 $ROE.="\n"; # 17) end of record marker (LF or CRLF)
363              
364 0         0 WriteROE($ROE);
365             }
366              
367             sub AddNew {
368 0     0 0 0 my %defaults = (
369             MPID => 'ISLD',
370             RecvMPID=> '',
371             Visible => 'Y',
372             Date => $dateStamp,
373             IOC => ''
374             );
375 0         0 my %args = (%defaults, @_);
376              
377 0         0 foreach my $key (qw(Symbol Side OrderID Time Price Shares OtherID)) {
378 0 0       0 cluck "Missing argument '$key'" unless exists $args{$key};
379             }
380              
381 0         0 my $ROE;
382 0         0 my $ROEId=GetNextROEID();
383              
384             # New order record spec in Oats Technical Reporting Specifications,
385             # Appendix C, pages C-6 to C-9.
386 0         0 $ROE="#OE#${sep}"; # 1) Order event record (OE)
387 0         0 $ROE.="NW${sep}"; # 2) Order event type (NW)
388 0         0 $ROE.="N${sep}"; # 3) Action type code (N/C/D/R)
389 0         0 $ROE.="$ROEId${sep}"; # 4) Firm ROE ID
390 0         0 $ROE.="${sep}"; # 5) corr/del TS
391 0         0 $ROE.="${sep}"; # 6) Rej ROE resub flag
392             #$ROE.="$MPID${sep}"; # 7) Receiving firm MPID
393             #$ROE.="${sep}"; # 7) Receiving firm MPID (blank if same)
394 0         0 $ROE.="$args{RecvMPID}${sep}"; # 7) Receiving firm MPID (blank if same)
395 0         0 $ROE.=sprintf("%08d000000${sep}",$args{Date}); # 8) Order received date
396 0         0 $ROE.="$args{OrderID}${sep}"; # 9) receiving firm order ID
397 0         0 $ROE.="${sep}"; # 10) Routing firm MPID
398 0         0 $ROE.="${sep}"; # 11) Routed order ID
399 0         0 $ROE.=sprintf("%08d%06s${sep}",$args{Date},$args{Time}); #12)Order received time
400 0         0 $ROE.="E${sep}"; # 13) received method code
401 0         0 $ROE.="$args{Symbol}${sep}"; # 14) Symbol
402 0         0 $ROE.="$args{Side}${sep}"; # 15) Buy/Sell code, B|S|SS|SX
403 0         0 $ROE.="$args{Shares}${sep}"; # 16) Shares quantity
404 0         0 $ROE.="$args{Price}${sep}"; # 17) Limit price
405 0         0 $ROE.="$args{Visible}${sep}"; # 18) Limit order display indicator
406 0         0 $ROE.="${sep}"; # 19) Stop price
407 0         0 $ROE.="DAY${sep}"; # 20) TIF
408 0         0 $ROE.="${sep}"; # 21) Expiration date
409 0         0 $ROE.="${sep}"; # 22) Expiration time
410 0         0 $ROE.="${sep}"; # 23) Do not reduce/do not increase code
411              
412 0         0 $ROE.="$args{IOC}${sep}"; # 24) First special handling code
413              
414 0         0 $ROE.="${sep}"; # 25) 2nd special handling code
415 0         0 $ROE.="${sep}"; # 26) 3rd special handling code
416 0         0 $ROE.="${sep}"; # 27) 4th special handling code
417 0         0 $ROE.="${sep}"; # 28) 5th special handling code
418 0         0 $ROE.="${sep}"; # 29) receiving terminal ID
419 0         0 $ROE.="${sep}"; # 30) receiving dept ID
420 0         0 $ROE.="${sep}"; # 31) originating dept ID
421 0         0 $ROE.="W${sep}"; # 32) acct type code (Wholesale)
422 0         0 $ROE.="N${sep}"; # 33) program trading code
423 0         0 $ROE.="N${sep}"; # 34) arbitrage code
424             #$ROE.="${sep}"; # 35) reserved for future use
425 0         0 $ROE.=""; # 35) reserved for future use
426 0         0 $ROE.="\n"; # 36) end of record marker (LF or CRLF)
427              
428 0         0 WriteROE($ROE);
429             }
430              
431             =head2 sub AddCancelReplace
432              
433             Generates Cancel/Replace report
434              
435             Arguments:
436             Symbol => 'MSFT',
437             Side => 'B', # or 'S', or 'SS', or 'SX'
438             OrderID=> 'AISL-123', # new order ID
439             OrigOrderID=> 'AISL-122', # original order ID
440             Time => 'HHMMSS', # new order timestamp
441             OrigTime=> 'HHMMSS', # new order timestamp
442             Price => '12.12345', # price, in dollars, to 7 decimal places if need be
443             Shares => 1200, # size, in shares
444             MPID => 'ISLD', # sent-to MPID (opt., def ISLD)
445             OtherID=> '123432', # exchange order ID
446             Date => 'yyyymmdd', # optional, defaults to today
447             IOC => 'IOC', # optional, specified if order is IOC
448             Visible=> 'Y', # optional, 'Y' or 'N'
449             RouteType=> 'C', # 38) Routing method code (defaults to 'C')
450             # E routed elec to member firm
451             # C routed to ECN
452             # L routed to SelectNet
453             # N routed non-electronic to memb firm
454             # M routed to non-member firm
455             # O routed to SuprtSOES
456             # P routed to Primex
457             # S routed to SOES
458             ProgramTradingCode=>'Y',# optional, 'Y' or 'N'
459             IndexArbCode=>'N', # optional, 'Y' or 'N'
460             PriceType=>'LIM', # optional, 'LIM' or 'MKT'
461              
462             =cut
463              
464             sub AddCancelReplace {
465 0     0 1 0 my %defaults = (
466             MPID => 'ISLD',
467             RecvMPID=> '',
468             Visible => 'Y',
469             Date => $dateStamp,
470             IOC => '',
471             RouteType => 'C',
472             ProgramTradingCode => 'Y',
473             IndexArbCode => 'N',
474             PriceType => 'LIM',
475             );
476 0         0 my %args = (%defaults, @_);
477              
478 0         0 foreach my $key (qw(Symbol Side OrderID OrigOrderID Time OrigTime
479             Price Shares)) {
480 0 0       0 cluck "Missing argument '$key'" unless exists $args{$key};
481             }
482              
483 0         0 my $ROE;
484 0         0 my $ROEId=GetNextROEID();
485              
486             # Cancel/Replace report
487             # Specifications Appendix C, pages C-15 to C-17.
488 0         0 $ROE="#OE#${sep}"; # 1) Order event record (OE)
489 0         0 $ROE.="CR${sep}"; # 2) Order event type (CR)
490 0         0 $ROE.="N${sep}"; # 3) Action type code (N/C/D/R)
491 0         0 $ROE.="$ROEId${sep}"; # 4) Firm ROE ID
492 0         0 $ROE.="${sep}"; # 5) corr/del TS
493 0         0 $ROE.="${sep}"; # 6) Rej ROE resub flag
494             #$ROE.="$MPID${sep}"; # 7) Receiving firm MPID
495             #$ROE.="${sep}"; # 7) Receiving firm MPID (blank if same)
496 0         0 $ROE.="$args{RecvMPID}${sep}"; # 7) Receiving firm MPID (blank if same)
497 0         0 $ROE.=sprintf("%08d000000${sep}",$args{Date});
498             # 8) Orig Order received date
499 0         0 $ROE.="$args{OrigOrderID}${sep}"; # 9) receiving firm orig order ID
500 0         0 die "AddCancelReplace not yet implemented!";
501             #TBD Finish coding this report!
502             #TBD Finish coding this report!
503             #TBD Finish coding this report!
504             #TBD Finish coding this report!
505             #TBD Finish coding this report!
506             #TBD Finish coding this report!
507             #TBD Finish coding this report!
508             #TBD Finish coding this report!
509             #TBD Finish coding this report!
510 0         0 $ROE.="${sep}"; # 10) Routing firm MPID
511 0         0 $ROE.="${sep}"; # 11) Routed order ID
512 0         0 $ROE.=sprintf("%08d%06s${sep}",$args{Date},$args{Time}); #12)Order received time
513 0         0 $ROE.="E${sep}"; # 13) received method code
514 0         0 $ROE.="$args{Symbol}${sep}"; # 14) Symbol
515 0         0 $ROE.="$args{Side}${sep}"; # 15) Buy/Sell code, B|S|SS|SX
516 0 0       0 if($args{PriceType} eq "LIM") {
517 0         0 $ROE.="$args{Price}${sep}"; # 16) Limit price
518             }
519             else {
520 0         0 $ROE.="${sep}"; # 16) Limit price
521             }
522 0         0 $ROE.="$args{Visible}${sep}"; # 17) Limit order display indicator
523 0         0 $ROE.="${sep}"; # 18) Stop price
524 0 0       0 if($args{PriceType} eq "LIM") {
525 0         0 $ROE.="DAY${sep}"; # 19) TIF
526             }
527             else {
528 0         0 $ROE.="${sep}"; # 19) TIF
529             }
530 0         0 $ROE.="${sep}"; # 20) Expiration date
531 0         0 $ROE.="${sep}"; # 21) Expiration time
532 0         0 $ROE.="${sep}"; # 22) Do not reduce/do not increase code
533 0         0 $ROE.="$args{IOC}${sep}"; # 23) First special handling code
534 0         0 $ROE.="${sep}"; # 24) 2nd special handling code
535 0         0 $ROE.="${sep}"; # 25) 3rd special handling code
536 0         0 $ROE.="${sep}"; # 26) 4th special handling code
537 0         0 $ROE.="${sep}"; # 27) 5th special handling code
538 0         0 $ROE.="${sep}"; # 28) receiving terminal ID
539 0         0 $ROE.="${sep}"; # 29) receiving dept ID
540 0         0 $ROE.="${sep}"; # 30) originating dept ID
541 0         0 $ROE.="W${sep}"; # 31) acct type code (Wholesale)
542 0         0 $ROE.="$args{ProgramTradingCode}${sep}"; # 32) program trading code
543 0         0 $ROE.="$args{IndexArbCode}${sep}"; # 33) arbitrage code
544 0         0 $ROE.="$args{OrderID}${sep}"; # 34) Sent to routed order ID
545 0         0 $ROE.="$args{MPID}${sep}"; # 35) Sent to firm MPID
546 0         0 $ROE.=sprintf("%08d%06s${sep}",$args{Date},$args{Time}); # 36)Order sent time
547 0         0 $ROE.="$args{Shares}${sep}"; # 37) Routed Shares Quantity
548 0         0 $ROE.="$args{RouteType}${sep}"; # 38) Routing method code (routed to ECN)
549             # E routed elec to member firm
550             # C routed to ECN
551             # L routed to SelectNet
552             # N routed non-electronic to memb firm
553             # M routed to non-member firm
554             # O routed to SuprtSOES
555             # P routed to Primex
556             # S routed to SOES
557 0         0 $ROE.="${sep}"; # 39: bunched order indicator
558 0         0 $ROE.=""; # 40: Original MPID (as of 20021213)
559 0         0 $ROE.="\n"; # 41: end of record marker (LF or CRLF)
560              
561 0         0 WriteROE($ROE);
562             }
563              
564              
565              
566             sub GetHeaderRecord
567             {
568 1     1 0 3 my $foreID = shift;
569 1         6 my $hdr;
570              
571             # Header record spec at page C-6 of OATS R.T.S.
572 1         4 $hdr.="#HD#${sep}"; # 1: Record type code #HD# (header)
573 1         3 $hdr.="OATS D1999-01${sep}"; # 2: Version description
574 1         4 $hdr.="$dateStamp${sep}"; # 3: Generation date
575 1         3 $hdr.="$foreID${sep}"; # 4: Firm FORE ID
576 1         3 $hdr.="$OSOID${sep}"; # 5: Reporting/transmitting OSO ID
577 1         3 $hdr.="$UserID${sep}"; # 6: USer ID
578 1         2 $hdr.="$Password${sep}"; # 7: User password
579 1         2 $hdr.="$MPID"; # 8: Order receiving firm MPID
580 1         4 $hdr.="\n"; # 9: End of record marker (LF or CRLF)
581             }
582              
583             my $FOREFileOpen = 0;
584             my $FOREPath;
585             my $FOREBytes = 0;
586             my $FORERecords = 0;
587              
588             my ($foreID, $forePath);
589              
590             sub OpenFOREFile {
591 1   50 1 0 8 $FOREPath = shift || ".";
592 1 50       6 $FOREPath.="/" unless $FOREPath=~/\/$/;
593              
594              
595 1         2 do {
596 2         6 $foreID = GetNextFOREId();
597 2         56 $forePath = "$FOREPath$foreID";
598             } while (-e $forePath);
599              
600 1         5 my $hdr = GetHeaderRecord($foreID);
601              
602 1 50       132 open(FORE, ">$forePath") or confess "Can't open $forePath, error $!";
603              
604 1         3 $FOREBytes=length $hdr;
605              
606 1         22 print FORE $hdr;
607              
608 1         3 $FORERecords = 0;
609              
610 1         4 $FOREFileOpen = 1;
611             }
612              
613             sub WriteROE {
614 0     0 0 0 my $roe = shift;
615              
616 0 0       0 OpenFOREFile() unless $FOREFileOpen;
617              
618 0 0       0 if($FOREBytes>=$FOREByteLimit) {
619 0         0 CloseFOREFile();
620 0         0 OpenFOREFile();
621             }
622              
623 0         0 print FORE $roe;
624              
625 0         0 $FOREBytes+=length $roe;
626 0         0 ++$FORERecords;
627             }
628              
629             sub CloseFOREFile {
630 1 50   1 0 7 OpenFOREFile() unless $FOREFileOpen;
631              
632 1         3 print FORE "#TR#,$FORERecords,\n";
633 1         64 close(FORE);
634             }
635              
636             END {
637 1     1   7 CloseFOREFile();
638             }
639              
640              
641             1;
642             __END__