File Coverage

lib/Amibroker/OLE/APXCreator.pm
Criterion Covered Total %
statement 73 85 85.8
branch 13 26 50.0
condition n/a
subroutine 11 11 100.0
pod 0 3 0.0
total 97 125 77.6


line stmt bran cond sub pod time code
1             package Amibroker::OLE::APXCreator;
2            
3 1     1   23992 use 5.006;
  1         3  
4 1     1   5 use strict;
  1         1  
  1         18  
5 1     1   4 use warnings;
  1         15  
  1         34  
6 1     1   1110 use Path::Tiny;
  1         12259  
  1         59  
7 1     1   970 use File::Slurp;
  1         16245  
  1         84  
8 1     1   9 use Carp;
  1         2  
  1         51  
9 1     1   979 use IO::File;
  1         10002  
  1         1251  
10            
11             =head1 NAME
12            
13             Amibroker::OLE::APXCreator - A simple interface to create .apx extension file for accessing Amibroker analysis document from external scripts.
14            
15             =head1 VERSION
16            
17             Version 0.03
18            
19             =cut
20            
21             our $VERSION = '0.03';
22            
23             =head1 SYNOPSIS
24            
25             use Amibroker::OLE::APXCreator;
26             my $new_apx_file = create_apx_file( {
27             afl_file => 'test_afl.afl',
28             symbol => 'ADANIPORTS-I',
29             timeframe => '20-minute',
30             from => '01-09-2015',
31             to => '20-09-2015',
32             range_type => 0,
33             apply_to => 1
34             } );
35            
36             =head1 DESCRIPTION
37            
38             This module helps in creating apx file (i.e. file with .apx extention), which is the basic input file for running Amibroker analysis externally through OLE automation.
39            
40             Creating this file automatically is a challenge as Amibroker is very sensitive to any changes with respect to apx file.
41             If there is even a space missed in creating it, then it will not process it.
42             So, to make life easier, this module handles the creation of the file as required by the amibroker.
43            
44             NOTE: Please ensure to provide all the required necessary fields.
45            
46             use Amibroker::OLE::APXCreator;
47             my $new_apx_file = create_apx_file( {
48             afl_file => 'path_to_the_location_of_the_afl_file',
49             symbol => 'symbol_name',
50             timeframe => 'timeframe',
51             from => 'from_date',
52             to => 'to_date',
53             range_type => range_type_in_number,
54             apply_to => apply_to_in_number
55             } );
56            
57             =head2 REQUIRED PARAMETERS
58            
59             =over 8
60            
61             =item B
62            
63             Complete Path to the AFL file, that you need to backtest or optimize or scan etc.
64             Eg: afl_file => 'C:/Amibroker/Stratergy/Release/IBM.afl'
65            
66             =item B
67            
68             The Symbol name should match with the symbol names in the Amibroker database
69             Eg: symbol => 'IBM-I' or
70             symbol => 'IBM'
71             (The name should exactly match with your database symbol)
72            
73             =item B
74            
75             Default available timeframe with Amibroker.
76             yearly
77             quarterly
78             monthly
79             weekly
80             daily
81             day/night
82             hourly
83             15-minute
84             5-minute
85             1-minute
86             3-minute
87             7-minute
88             10-minute
89             12-minute
90             20-minute
91            
92             If you want to have your custom defined timeframe then you need to update here
93             Amibroker -> Tools -> Preferences -> Intraday Tab -> Custom Time Intervals
94            
95             =item B
96            
97             from date, Eg: from => '01-12-2010' (for 1st December 2010 date)
98             from => '2010-12-01' (for 1st December 2010 date)
99             from => '2010-01-12' (for 1st December 2010 date)
100             from => '12-01-2010' (for 1st December 2010 date)
101             from => '12-2010-01' (for 1st December 2010 date)
102             Date format should match your Amibroker date format : Usually it is windows system time settings
103             Please check your amibroker date format and send the appropriate date format
104            
105             =item B
106            
107             to date, Eg: to => '31-05-2015' (for 31st May 2015 date)
108             Date format should match your Amibroker date format : Usually it is windows system time settings
109             Please check your amibroker date format and send the appropriate date format
110            
111             =item B
112            
113             complete path of the apx file where you want to create this file.
114             Eg: apx_file => 'C:/IBM.apx'
115            
116             =item B
117            
118             Range in Amibroker analysis refers to
119             'All Quotes' = 0
120             '1 recent bar(s)' = 1
121             '1 recent day(s)' = 2
122             'From-To-dates' = 3
123             So provide range number accordingly
124            
125             =item B
126            
127             Apply the settings to
128             '*All Symbols' = 0
129             '*Current' = 1
130             '*Filter' = 2
131            
132             =back
133            
134             =head2 OPTIONAL PARAMETERS
135            
136             =over 1
137            
138             =item B
139            
140             This module assumes that there is no change in the amibroker custom time interval settings.
141             i.e Amibroker -> Tools -> Preferences -> Intraday Tab -> Custom Time Intervals.
142            
143             Amibroker assigns a value to every intervals
144             Eg: (Below are the default Amibroker intervals provided and their default values)
145             yearly = -4
146             quarterly = -3
147             monthly = -2
148             weekly = -1
149             daily = 0
150             day/night = 1
151             hourly = 2
152             15-minute = 3
153             5-minute = 4
154             1-minute = 5
155             3-minute = 10
156             7-minute = 11
157             10-minute = 12
158             12-minute = 13
159             20-minute = 14
160            
161             If you happen to change the custom time intervals, then the amibroker default values may change.
162             In that case you have to find out the actual value of the custom interval and pass as the parameter.
163            
164             Eg:
165             periodicity => -5
166             (you can find this out by manually saving the apx file and checking the periodicity field)
167            
168             How to create apx file manually:
169            
170             =over 3
171            
172             =item * Open Amibroker -> Analysis window -> Settings
173            
174             =item * Edit settings as per your requirement
175            
176             =item * Menu-> File-> Save_AS -> select (.apx extenstion)
177            
178             =back
179            
180             For more infor on apx file, check this forum : L
181            
182             =back
183            
184             =cut
185            
186             #
187             # Create the apx file that goes as input to the amibroker engine
188             #
189             my %periods = (
190             'yearly' => -4,
191             'quarterly' => -3,
192             'monthly' => -2,
193             'weekly' => -1,
194             'daily' => 0,
195             'day/night' => 1,
196             'hourly' => 2,
197             '15-minute' => 3,
198             '5-minute' => 4,
199             '1-minute' => 5,
200             '3-minute' => 10,
201             '7-minute' => 11,
202             '10-minute' => 12,
203             '12-minute' => 13,
204             '20-minute' => 14
205             );
206            
207             sub create_apx_file {
208 1     1 0 20 my @list = @_;
209 1         4 my $args = _check_valid_args(@list);
210 1 50       5 if ( !$args->{timeframe} ) {
211 0         0 croak( '[ERROR}: No timeframe passed (Required parameter) : ' . "\n" );
212             }
213 1 50       3 if ( !$args->{periodicity} ) {
214 1         5 $args->{periodicity} = lc( $args->{timeframe} );
215             }
216 1 50       4 if ( !$args->{periodicity} ) {
217             croak( '[ERROR}: No periodicity found for given timeframe '
218             . $args->{timeframe}
219 0         0 . "\n" );
220             }
221 1 50       31 if ( !-e $args->{afl_file} ) {
222 0         0 croak( '[ERROR}: AFL file not present at:' . $args->{afl_file} . "\n" );
223             }
224 1 50       4 if ( !$args->{symbol} ) {
225 0         0 croak( '[ERROR}: Symbol name not passed (Required parameter):' . "\n" );
226             }
227 1 50       11 if ( !$args->{from} ) {
228 0         0 croak(
229             '[ERROR}: from date is not passed (Required parameter):' . "\n" );
230             }
231 1 50       3 if ( !$args->{to} ) {
232 0         0 croak( '[ERROR}: to date is not passed (Required parameter):' . "\n" );
233             }
234 1 50       4 if ( !$args->{apx_file} ) {
235             print
236             '[WARN]: apx_file is not passed, by default your apx file name will be : C:/'
237 1         29 . $args->{symbol} . '.apx' . "\n";
238 1         4 $args->{apx_file} = 'C:/' . $args->{symbol} . '.apx';
239             }
240 1 50       3 if ( !defined( $args->{range_type} ) ) {
241 0         0 croak( '[ERROR}: range_type value is not passed, (Required parameter):'
242             . "\n" );
243             }
244 1 50       4 if ( !defined( $args->{apply_to} ) ) {
245 0         0 croak( '[ERROR}: apply_to value is not passed, (Required parameter):'
246             . "\n" );
247             }
248 1         2 my $text_dummy = 'XXXX';
249            
250 1         3 $args->{from} = $args->{from} . ' 00:00:00';
251 1         3 my $afl_data = slurp_afl( $args->{afl_file} );
252 1         8 $args->{afl_file} =~ s/\//\\/gx;
253 1         5 $args->{afl_file} =~ s/\\/\\\\/gx;
254 1         4 my $afl = convert_afl_text_for_amibroker($afl_data);
255 1         10 my $fh = IO::File->new("> $args->{apx_file}");
256 1         92 while ( my $data = ) {
257 1         21 $data =~ s/
258             \
259             $text_dummy
260             \<\/Symbol\>
261             /
262             \
263             $args->{symbol}
264             \<\/Symbol\>
265             /gx;
266 1         11 $data =~ s/
267             \
268             $text_dummy
269             \<\/FormulaPath\>
270             /
271             \
272             $args->{afl_file}
273             \<\/FormulaPath\>
274             /gx;
275 1         27 $data =~ s/
276             \
277             $text_dummy
278             \<\/FormulaContent\>
279             /
280             \
281             $afl\<\/FormulaContent\>
282             /gx;
283 1         10 $data =~ s/
284             \
285             $text_dummy
286             \<\/Periodicity\>
287             /
288             \
289             $periods{$args->{periodicity}}
290             \<\/Periodicity\>
291             /gx;
292 1         9 $data =~ s/
293             \
294             $text_dummy
295             \<\/FromDate\>
296             /
297             \
298             $args->{from}
299             \<\/FromDate\>
300             /gx;
301 1         8 $data =~ s/
302             \
303             $text_dummy
304             \<\/ToDate\>
305             /
306             \
307             $args->{to}
308             \<\/ToDate\>
309             /gx;
310 1         32 $data =~ s/
311             \
312             $text_dummy
313             \<\/ApplyTo\>
314             /
315             \
316             $args->{apply_to}
317             \<\/ApplyTo\>
318             /gx;
319 1         10 $data =~ s/
320             \
321             $text_dummy
322             \<\/RangeType\>
323             /
324             \
325             $args->{range_type}
326             \<\/RangeType\>
327             /gx;
328 1         59 print $fh $data;
329             }
330 0         0 undef $fh; # automatically closes the file
331 0         0 autoflush STDOUT 1;
332 0         0 return $args->{apx_file};
333             }
334            
335             #
336             # Gulp the file into a string
337             #
338             sub slurp_afl {
339 1     1 0 7 my $text = File::Slurp::read_file(shift);
340 1         100 return $text;
341             }
342            
343             #
344             # Convert text that is gulped into a scalar variable and modifiy accordingly to be loaded to Amibroker.
345             #
346             sub convert_afl_text_for_amibroker {
347 1     1 0 1 my $text = shift;
348 1         24 $text =~ s/\&/\&\;/g;
349 1         24 $text =~ s/\\n/\\\\n/g;
350 1         206 $text =~ s/\R/\\r\\n/g;
351 1         51 $text =~ s/\t/\\t/g;
352 1         30 $text =~ s/\
353 1         25 $text =~ s/\>/\>\;/g;
354 1 50       7 unless ( $text =~ /\\r\\n$/ ) {
355 0         0 $text =~ s/$/\\r\\n/g;
356             }
357 1         2 return $text;
358             }
359            
360             sub _check_valid_args {
361 1     1   3 my @list = @_;
362 1         4 my %args_permitted = map { $_ => 1 } (
  9         18  
363             qw|
364             afl_file
365             symbol
366             timeframe
367             from
368             to
369             apx_file
370             periodicity
371             apply_to
372             range_type
373             |
374             );
375 1         3 my @bad_args = ();
376 1         2 my $arg = pop @list;
377 1         2 for my $k ( sort keys %{$arg} ) {
  1         9  
378 7 50       18 push @bad_args, $k unless $args_permitted{$k};
379             }
380 1 50       4 croak("Unrecognized option(s) passed to Amibroker OLE: @bad_args")
381             if @bad_args;
382 1         4 return $arg;
383             }
384            
385             =head1 AUTHOR
386            
387             Babu Prasad HP, C<< >>
388            
389             =head1 BUGS
390            
391             Please report any bugs or feature requests to C, or through
392             the web interface at L. I will be notified, and then you'll
393             automatically be notified of progress on your bug as I make changes.
394            
395             =head1 SUPPORT
396            
397             You can find documentation for this module with the perldoc command.
398            
399             perldoc Amibroker::OLE::APXCreator
400            
401            
402             You can also look for information at:
403            
404             =over 4
405            
406             =item * RT: CPAN's request tracker (report bugs here)
407            
408             L
409            
410             =item * AnnoCPAN: Annotated CPAN documentation
411            
412             L
413            
414             =item * CPAN Ratings
415            
416             L
417            
418             =item * Search CPAN
419            
420             L
421            
422             =back
423            
424            
425             =head1 ACKNOWLEDGEMENTS
426            
427             I would like to thank Mr.Pannag M for supporting me in writing this module.
428            
429             =head1 LICENSE AND COPYRIGHT
430            
431             Copyright 2015 Babu Prasad HP.
432            
433             This program is free software; you can redistribute it and/or modify it
434             under the terms of the the Artistic License (2.0). You may obtain a
435             copy of the full license at:
436            
437             L
438            
439             Any use, modification, and distribution of the Standard or Modified
440             Versions is governed by this Artistic License. By using, modifying or
441             distributing the Package, you accept this license. Do not use, modify,
442             or distribute the Package, if you do not accept this license.
443            
444             If your Modified Version has been derived from a Modified Version made
445             by someone other than you, you are nevertheless required to ensure that
446             your Modified Version complies with the requirements of this license.
447            
448             This license does not grant you the right to use any trademark, service
449             mark, tradename, or logo of the Copyright Holder.
450            
451             This license includes the non-exclusive, worldwide, free-of-charge
452             patent license to make, have made, use, offer to sell, sell, import and
453             otherwise transfer the Package with respect to any patent claims
454             licensable by the Copyright Holder that are necessarily infringed by the
455             Package. If you institute patent litigation (including a cross-claim or
456             counterclaim) against any party alleging that the Package constitutes
457             direct or contributory patent infringement, then this Artistic License
458             to you shall terminate on the date that such litigation is filed.
459            
460             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
461             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
462             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
463             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
464             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
465             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
466             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
467             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
468            
469            
470             =cut
471            
472             1; # End of Amibroker::OLE::APXCreator
473            
474             __DATA__