From 4810539989800245e4e9ce08cd8e4a6e15eb9fd4 Mon Sep 17 00:00:00 2001 From: Matias Benitez Date: Fri, 18 May 2018 16:32:42 -0300 Subject: [PATCH] Adding base version --- .gitattributes | 2 + .gitignore | 11 + AAGauss-Indicator-Bot.sln | 24 ++ Gauss.png | Bin 0 -> 48903 bytes LICENSE | 661 ++++++++++++++++++++++++++++ Multi-Period-Daily/LRCIndicator.js | 112 +++++ Multi-Period-Daily/User.bot.js | 580 +++++++++++++++++++++++++ Project.njsproj | 83 ++++ package-lock.json | 670 +++++++++++++++++++++++++++++ this.bot.config.json | 91 ++++ 10 files changed, 2234 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 AAGauss-Indicator-Bot.sln create mode 100644 Gauss.png create mode 100644 LICENSE create mode 100644 Multi-Period-Daily/LRCIndicator.js create mode 100644 Multi-Period-Daily/User.bot.js create mode 100644 Project.njsproj create mode 100644 package-lock.json create mode 100644 this.bot.config.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..dfe077042 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..82c487bdd --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ + +.vs/* +obj/* + +bin/* + +*.config +*.log +*.cache +node_modules/* + diff --git a/AAGauss-Indicator-Bot.sln b/AAGauss-Indicator-Bot.sln new file mode 100644 index 000000000..136f55636 --- /dev/null +++ b/AAGauss-Indicator-Bot.sln @@ -0,0 +1,24 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26403.7 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "Project", "Project.njsproj", "{AA2901BC-8F81-40F0-A402-5CA79A3F22AD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AA2901BC-8F81-40F0-A402-5CA79A3F22AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA2901BC-8F81-40F0-A402-5CA79A3F22AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA2901BC-8F81-40F0-A402-5CA79A3F22AD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B4BDAEAF-E863-458A-87C1-CC6D8C490784} + EndGlobalSection +EndGlobal diff --git a/Gauss.png b/Gauss.png new file mode 100644 index 0000000000000000000000000000000000000000..a30f030ca220f26cfdcc45e744ab179b9c2f4283 GIT binary patch literal 48903 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�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 X*}Ud5sj!PcLcA1Z)u7eV<`Mq~q&!P% literal 0 HcmV?d00001 diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..dbbe35581 --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/Multi-Period-Daily/LRCIndicator.js b/Multi-Period-Daily/LRCIndicator.js new file mode 100644 index 000000000..89f6d00c6 --- /dev/null +++ b/Multi-Period-Daily/LRCIndicator.js @@ -0,0 +1,112 @@ +/* + * Linear regression curve. SRC: Gekko + */ + +//var log = require('../../core/log'); + +var LRCIndicator = function(settings) { + this.input = 'price'; + this.depth = settings; + this.result = false; + this.age = 0; + this.history = []; + this.x = []; + /* + * Do not use array(depth) as it might not be implemented + */ + for (var i = 0; i < this.depth; i++) { + this.history.push(0.0); + this.x.push(i); + } + + // log.debug("Created LRC indicator with h: ", this.depth); +} + +LRCIndicator.prototype.update = function(price) { + // We need sufficient history to get the right result. + if(this.result === false && this.age < this.depth) { + + this.history[this.age] = price; + this.age++; + this.result = false; + // log.debug("Waiting for sufficient age: ", this.age, " out of ", this.depth); + return; + } + + this.age++; + // shift history + for (var i = 0; i < (this.depth - 1); i++) { + this.history[i] = this.history[i+1]; + } + this.history[this.depth-1] = price; + + this.calculate(price); + + // log.debug("Checking LRC: ", this.result.toFixed(8), "\tH: ", this.age); + return; +} + +/* + * Least squares linear regression fitting. + */ +function linreg(values_x, values_y) { + var sum_x = 0; + var sum_y = 0; + var sum_xy = 0; + var sum_xx = 0; + var count = 0; + + /* + * We'll use those variables for faster read/write access. + */ + var x = 0; + var y = 0; + var values_length = values_x.length; + + if (values_length != values_y.length) { + throw new Error('The parameters values_x and values_y need to have same size!'); + } + + /* + * Nothing to do. + */ + if (values_length === 0) { + return [ [], [] ]; + } + + /* + * Calculate the sum for each of the parts necessary. + */ + for (var v = 0; v < values_length; v++) { + x = values_x[v]; + y = values_y[v]; + sum_x += x; + sum_y += y; + sum_xx += x*x; + sum_xy += x*y; + count++; + } + + /* + * Calculate m and b for the formula: y = x * m + b + * + */ + var m = (count*sum_xy - sum_x*sum_y) / (count*sum_xx - sum_x*sum_x); + var b = (sum_y/count) - (m*sum_x)/count; + + return [m, b]; +} + + +/* + * Handle calculations + */ +LRCIndicator.prototype.calculate = function(price) { + // get the reg + var reg = linreg(this.x, this.history); + + // y = a * x + b + this.result = ((this.depth-1) * reg[0]) + reg[1]; +} + +module.exports = LRCIndicator; \ No newline at end of file diff --git a/Multi-Period-Daily/User.bot.js b/Multi-Period-Daily/User.bot.js new file mode 100644 index 000000000..5db94ce30 --- /dev/null +++ b/Multi-Period-Daily/User.bot.js @@ -0,0 +1,580 @@ +var LRCIndicator = require('./LRCIndicator'); + +exports.newUserBot = function newUserBot(BOT, COMMONS, UTILITIES, DEBUG_MODULE, BLOB_STORAGE, FILE_STORAGE) { + const FULL_LOG = true; + const LOG_FILE_CONTENT = false; + const USE_PARTIAL_LAST_CANDLE = true; // When running live the last candle generated is a partial candle. + + let bot = BOT; + + const ONE_MIN_IN_MILISECONDS = 60 * 1000; + + const MODULE_NAME = "User Bot"; + + const EXCHANGE_NAME = "Poloniex"; + + const logger = DEBUG_MODULE.newDebugLog(); + logger.fileName = MODULE_NAME; + logger.bot = bot; + + thisObject = { + initialize: initialize, + start: start + }; + + let gaussStorage = BLOB_STORAGE.newBlobStorage(bot); + + let utilities = UTILITIES.newUtilities(bot); + + let statusDependencies; + + return thisObject; + + function initialize(pStatusDependencies, pMonth, pYear, callBackFunction) { + + try { + + logger.fileName = MODULE_NAME; + + if (FULL_LOG === true) { logger.write("[INFO] initialize -> Entering function."); } + + statusDependencies = pStatusDependencies; + + gaussStorage.initialize({ bot: "AAGauss", devTeam: "AAMasters" }, onGaussInizialized); + + function onGaussInizialized(err) { + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + if (FULL_LOG === true) { logger.write("[INFO] initialize -> onGaussInizialized -> Initialization Succeed."); } + callBackFunction(global.DEFAULT_OK_RESPONSE); + + } else { + logger.write("[ERROR] initialize -> onGaussInizialized -> err = " + err.message); + callBackFunction(err); + } + } + + } catch (err) { + logger.write("[ERROR] initialize -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + /* + TODO Create Description + */ + + function start(callBackFunction) { + + try { + + if (FULL_LOG === true) { logger.write("[INFO] start -> Entering function."); } + + let market = global.MARKET; + let reportFilePath = EXCHANGE_NAME + "/Processes/" + bot.process; + let executionTime; + let maxCandleTime; + let lastCandles; + + getContextVariables(); + + function getContextVariables() { + + try { + + if (FULL_LOG === true) { logger.write("[INFO] start -> getContextVariables -> Entering function."); } + + let reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1"; + if (FULL_LOG === true) { logger.write("[INFO] start -> getContextVariables -> reportKey = " + reportKey); } + + if (statusDependencies.statusReports.get(reportKey).status === "Status Report is corrupt.") { + logger.write("[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process."); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + + let thisReport = statusDependencies.statusReports.get(reportKey).file; + + if (thisReport.lastFile === undefined) { + logger.write("[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + + let customOK = { + result: global.CUSTOM_OK_RESPONSE.result, + message: "Dependency not ready." + } + logger.write("[WARN] start -> getContextVariables -> customOK = " + customOK.message); + callBackFunction(customOK); + return; + } + + maxCandleTime = new Date(Date.UTC(thisReport.lastFile.year, thisReport.lastFile.month - 1, thisReport.lastFile.days, thisReport.lastFile.hours, thisReport.lastFile.minutes)); + + reportKey = "AAMasters" + "-" + "AAGauss" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1"; + if (FULL_LOG === true) { logger.write("[INFO] start -> getContextVariables -> reportKey = " + reportKey); } + + if (statusDependencies.statusReports.get(reportKey).status === "Status Report is corrupt.") { + logger.write("[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process."); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + + thisReport = statusDependencies.statusReports.get(reportKey).file; + if (thisReport.lastCandles !== undefined) { + logger.write("[INFO] start -> getContextVariables -> thisReport.lastCandles: " + JSON.stringify(thisReport.lastCandles)); + lastCandles = thisReport.lastCandles; + + buildLRCPoints(); + + } else { + + if (FULL_LOG === true) { logger.write("[INFO] start -> getContextVariables -> First time running the bot."); } + + lastCandles = []; + + for (n = 0; n < global.dailyFilePeriods.length; n++) { + lastCandles.push(0); + } + + lastCandles[10] = new Date(Date.UTC(2018, 3).valueOf()); + + if (FULL_LOG === true) { logger.write("[INFO] start -> getContextVariables -> Starting at: " + new Date(lastCandles[10]).toISOString()); } + + buildLRCPoints(); + + } + + } catch (err) { + logger.write("[ERROR] start -> getContextVariables -> err = " + err.message); + if (err.message === "Cannot read property 'file' of undefined") { + logger.write("[HINT] start -> getContextVariables -> Check the bot configuration to see if all of its statusDependencies declarations are correct. "); + logger.write("[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)); + } + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildLRCPoints() { + + if (FULL_LOG === true) { logger.write("[INFO] start -> buildLRCPoints -> Entering function."); } + + advanceTime(); + + function advanceTime() { + + if (FULL_LOG === true) { logger.write("[INFO] start -> buildLRCPoints -> advanceTime -> Entering function."); } + + executionTime = new Date(lastCandles[10].valueOf() + ONE_MIN_IN_MILISECONDS); + + if (FULL_LOG === true) { logger.write("[INFO] start -> buildLRCPoints -> advanceTime -> New processing time @ " + executionTime.toISOString()); } + + /* Validation that we are not going past the head of the market. */ + + if (executionTime.valueOf() > maxCandleTime.valueOf()) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> buildLRCPoints -> advanceTime -> Head of the market found @ " + maxCandleTime.toISOString()); } + + callBackFunction(global.DEFAULT_OK_RESPONSE); // Here is where we finish processing and wait for the platform to run this module again. + return; + } + + periodsLoop(); + + } + } + + function periodsLoop() { + + let n = 0 // loop Variable representing each possible period as defined at the periods array. + + loopBody(); + + function loopBody() { + + if (FULL_LOG === true) { logger.write("[INFO] start -> buildLRCChannels -> periodsLoop -> loopBody -> Entering function. Time: " + executionTime.toISOString() + ". Loop: "+n); } + + const outputPeriod = global.dailyFilePeriods[n][0]; + const folderName = global.dailyFilePeriods[n][1]; + + isTimeToRun(); + + function isTimeToRun() { + let nextExecution = lastCandles[n].valueOf() + outputPeriod; + if (executionTime.valueOf() >= nextExecution) { + getLRCPoints(); + } else { + + if (FULL_LOG === true) logger.write("[INFO] start -> periodsLoop -> loopBody -> It's not time to run this period. Next Execution: " + new Date(nextExecution).toISOString()); + + controlLoop(); + } + } + + function getLRCPoints() { + + if (FULL_LOG === true) { logger.write("[INFO] start -> getLRCPoints -> Entering function."); } + + const maxLRCDepth = 63; + const maxBackwardsCount = 60; + + let backwardsCount = 0; + let candleArray = []; + + let queryDate = new Date(executionTime); + let candleFile = getDailyFile(queryDate, onDailyFileReceived); + + function onDailyFileReceived(err, candleFile) { + if (FULL_LOG === true) { logger.write("[INFO] start -> getLRCPoints -> onDailyFileReceived."); } + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + for (let i = 0; i < candleFile.length; i++) { + let candle = { + open: undefined, + close: undefined, + min: 10000000000000, + max: 0, + begin: undefined, + end: undefined + }; + + candle.min = candleFile[i][0]; + candle.max = candleFile[i][1]; + + candle.open = candleFile[i][2]; + candle.close = candleFile[i][3]; + + candle.begin = candleFile[i][4]; + candle.end = candleFile[i][5]; + + if (LOG_FILE_CONTENT === true) { logger.write("[INFO] Candle Date: " + new Date(candle.begin).toISOString() + ". Process Date: " + executionTime.toISOString()); } + + if (candleArray.length < maxLRCDepth && candle.begin <= executionTime.valueOf()) { + candleArray.push(candleFile[i]); + } + } + + if (FULL_LOG === true) { logger.write("[INFO] start -> getLRCPoints -> Candle Array Length: " + candleArray.length); } + + if (candleArray.length >= maxLRCDepth) { + if (FULL_LOG === true) { logger.write("[INFO] start -> getLRCPoints -> All candles available proceed with LRC calculations."); } + + let lrcChannel = performLRCCalculations(candleArray); + saveChannel(lrcChannel); + + } else if (backwardsCount <= maxBackwardsCount) { + if (FULL_LOG === true) { logger.write("[INFO] start -> getChannelTilt -> Getting file for day before."); } + + queryDate.setDate(queryDate.getDate() - 1); + getDailyFile(queryDate, onDailyFileReceived); + backwardsCount++; + } else { + logger.write("[ERROR] start -> getChannelTilt -> Not enough history to calculate LRC."); + callBack(global.DEFAULT_RETRY_RESPONSE); + } + } + } + + function getDailyFile(dateTime, onDailyFileReceived) { + try { + if (FULL_LOG === true) { logger.write("[INFO] start -> getLRCPoints -> getDailyFile -> Entering function."); } + + let datePath = dateTime.getUTCFullYear() + "/" + utilities.pad(dateTime.getUTCMonth() + 1, 2) + "/" + utilities.pad(dateTime.getUTCDate(), 2); + let filePath = "AAMasters/AAOlivia.1.0/AACloud.1.1/Poloniex/dataSet.V1/Output/Candles/Multi-Period-Daily/" + folderName + "/" + datePath; + let fileName = market.assetA + '_' + market.assetB + ".json" + + gaussStorage.getTextFile(filePath, fileName, onFileReceived); + + function onFileReceived(err, text) { + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + if (FULL_LOG === true) { logger.write("[INFO] start -> getLRCPoints -> getDailyFile -> onFileReceived > Entering Function."); } + + let candleFile = JSON.parse(text); + onDailyFileReceived(global.DEFAULT_OK_RESPONSE, candleFile); + } else { + logger.write("[ERROR] start -> getLRCPoints -> getDailyFile -> onFileReceived -> Failed to get the file. Will abort the process and request a retry."); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + } + } catch (err) { + logger.write("[ERROR] start -> getLRCPoints -> getDailyFile -> err = " + err.message); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + } + } + + function performLRCCalculations(candleArray) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> performLRCCalculations -> Entering function."); } + + /* + * It's needed to order since it's possible that we need to get another file and it will put an older candle at the end of the array. + */ + candleArray.sort(function (a, b) { + return a[4] - b[4]; + }); + + if (USE_PARTIAL_LAST_CANDLE === false) candleArray = candleArray.slice(0, candleArray.length - 1); + + let lrcPoints = []; + lrcPoints.push(0); //firstCandleBeginTime 0 + lrcPoints.push(0); //firstCandleEndTime 1 + lrcPoints.push(0); //lastCandleBeginTime 2 + lrcPoints.push(0); //lastCandleEndTime 3 + lrcPoints.push(0); //minimumChannelValue 4 + lrcPoints.push(0); //middleChannelValue 5 + lrcPoints.push(0); //maximumChannelValue 6 + + if (LOG_FILE_CONTENT === true) + lrcPoints.push(candleArray); //Entire candle array 7 + + calculateLRC(candleArray, lrcPoints); + + let lastCandle = candleArray[0]; + let firstCandle = candleArray[candleArray.length - 1]; + lrcPoints[0] = firstCandle[4]; + lrcPoints[1] = firstCandle[5]; + lrcPoints[2] = lastCandle[4]; + lrcPoints[3] = lastCandle[5]; + + if (FULL_LOG === true) { + logger.write("[INFO] start -> getChannelTilt -> performLRCCalculations -> LRC Points calculation results: " + JSON.stringify(lrcPoints)); } + + return lrcPoints; + } + + function calculateLRC(candlesArray, lrcPoints) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> getChannelTilt -> calculateLRC -> Entering function."); } + + let lrcMinIndicator = new LRCIndicator(15); + let lrcMidIndicator = new LRCIndicator(30); + let lrcMaxIndicator = new LRCIndicator(60); + + for (let i = 0; i < candlesArray.length; i++) { + let tempCandle = candlesArray[i]; + let averagePrice = (tempCandle[0] + tempCandle[1] + tempCandle[2] + tempCandle[3]) / 4; // TODO Check which price should be take to get the LRC + + lrcMinIndicator.update(averagePrice); + lrcMidIndicator.update(averagePrice); + lrcMaxIndicator.update(averagePrice); + } + + /* + * Only if there is enough history the result will be calculated + */ + if (lrcMinIndicator.result != false && lrcMidIndicator.result != false && lrcMaxIndicator.result != false) { + lrcPoints[4] = lrcMinIndicator.result; + lrcPoints[5] = lrcMidIndicator.result; + lrcPoints[6] = lrcMaxIndicator.result; + + return lrcPoints; + } else { + logger.write("[ERROR] start -> getChannelTilt -> calculateLRC -> There is not enough history to calculate the LRC."); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function saveChannel(lrcChannel) { + + try { + + if (FULL_LOG === true) { logger.write("[INFO] start -> saveChannel -> Entering function."); } + let fileContent; + let datePath = executionTime.getUTCFullYear() + "/" + utilities.pad(executionTime.getUTCMonth() + 1, 2) + "/" + utilities.pad(executionTime.getUTCDate(), 2); + let filePath = bot.filePathRoot + "/Output/LRC-Channel/Multi-Period-Daily/" + folderName + "/" + datePath; + let fileName = market.assetA + '_' + market.assetB + ".json" + + if (FULL_LOG === true) { logger.write("[INFO] start -> buildLRCChannels -> periodsLoop -> loopBody -> getCurrentContent -> fileName = " + fileName); } + if (FULL_LOG === true) { logger.write("[INFO] start -> buildLRCChannels -> periodsLoop -> loopBody -> getCurrentContent -> filePath = " + filePath); } + + gaussStorage.getTextFile(filePath, fileName, onFileRetrieved); + + function onFileRetrieved(err, text) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> onFileRetrieved -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + if (err.message === "File does not exist.") { + if (FULL_LOG === true) { logger.write("[INFO] start -> onFileRetrieved -> Daily file does not exist, creating folders."); } + + createFolders(filePath); + return; + } else { + logger.write("[ERROR] start -> onFileRetrieved -> err = " + err.message); + callBackFunction(err); + return; + } + } + + if (FULL_LOG === true) { logger.write("[INFO] start -> onFileRetrieved -> Daily file exist, appending content."); } + + fileContent = JSON.parse(text); + appendToFile(fileContent); + } + + + function createFolders(filePath) { + + try { + + if (FULL_LOG === true) { logger.write("[INFO] start -> createFolders -> Entering function."); } + + utilities.createFolderIfNeeded(filePath, gaussStorage, onFolderACreated); + + function onFolderACreated(err) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> createFolders -> onFolderACreated -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + logger.write("[ERROR] start -> createFolders -> onFolderACreated -> err = " + err.message); + callBackFunction(err); + return; + } + + utilities.createFolderIfNeeded(reportFilePath, gaussStorage, onFolderCreated); + } + + function onFolderCreated(err) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> createFolders -> onFolderCreated -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + logger.write("[ERROR] start -> createFolders -> onFolderCreated -> err = " + err.message); + callBackFunction(err); + return; + } + createFile(); + } + + } catch (err) { + logger.write("[ERROR] start -> createFolders -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function createFile() { + + if (FULL_LOG === true) { logger.write("[INFO] start -> saveChannel -> createFile -> Entering function."); } + + let existingContent = []; + existingContent.push(lrcChannel); + + gaussStorage.createTextFile(filePath, fileName, JSON.stringify(existingContent), onFileCreated); + + function onFileCreated(err) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> saveChannel -> onFileCreated -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + logger.write("[ERROR] start -> saveChannel -> onFileCreated -> err = " + err.message); + callBackFunction(err); + return; + } + + if (LOG_FILE_CONTENT === true) { + logger.write("[INFO] start -> saveChannel -> onFileCreated -> Content written = " + JSON.stringify(existingContent)); + } + + // We keep a record of the last candle used for the time period + lastCandles[n] = lrcChannel[0]; + + controlLoop(); + } + } + + function appendToFile(fileContent) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> saveChannel -> appendToFile -> Entering function."); } + + fileContent.push(lrcChannel); + + gaussStorage.createTextFile(filePath, fileName, JSON.stringify(fileContent), onExistingFileUpdated); + + function onExistingFileUpdated(err) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> saveChannel -> onExistingFileUpdated -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + logger.write("[ERROR] start -> saveChannel -> onExistingFileUpdated -> err = " + err.message); + callBackFunction(err); + return; + } + + if (LOG_FILE_CONTENT === true) { + logger.write("[INFO] start -> saveChannel -> onExistingFileUpdated -> Content written = " + JSON.stringify(fileContent)); + } + + // We keep a record of the last candle used for the time period + lastCandles[n] = lrcChannel[0]; + + controlLoop(); + } + } + } catch (err) { + logger.write("[ERROR] start -> saveChannel -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + } + + function controlLoop() { + + if (FULL_LOG === true) { logger.write("[INFO] start -> buildLRCChannels -> periodsLoop -> controlLoop -> Entering function."); } + + n++; + + if (n < global.dailyFilePeriods.length) { + + loopBody(); + + } else { + + writeStatusReport(); + + } + } + + } + + function writeStatusReport() { + + try { + + if (FULL_LOG === true) { logger.write("[INFO] start -> writeStatusReport -> Entering function."); } + + let key = bot.devTeam + "-" + bot.codeName + "-" + bot.process + "-" + bot.dataSetVersion; + + let statusReport = statusDependencies.statusReports.get(key); + + statusReport.file.lastExecution = bot.processDatetime; + statusReport.file.lastCandles = lastCandles; + statusReport.save(onSaved); + + function onSaved(err) { + + if (FULL_LOG === true) { logger.write("[INFO] start -> writeStatusReport -> onSaved -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + logger.write("[ERROR] start -> writeStatusReport -> onSaved -> err = " + err.message); + callBackFunction(err); + return; + } + + callBackFunction(global.DEFAULT_OK_RESPONSE); + } + + } catch (err) { + logger.write("[ERROR] start -> writeStatusReport -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + + } catch (err) { + logger.write("[ERROR] start -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } +}; diff --git a/Project.njsproj b/Project.njsproj new file mode 100644 index 000000000..cdb446a78 --- /dev/null +++ b/Project.njsproj @@ -0,0 +1,83 @@ + + + + Debug + 2.0 + {aa2901bc-8f81-40f0-a402-5ca79a3f22ad} + + ShowAllFiles + + + + + . + {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + Project + + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + False + True + 0 + / + http://localhost:48022/ + False + True + http://localhost:1337 + False + + + + + + + CurrentPage + True + False + False + False + + + + + + + + + False + False + + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..87c40254f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,670 @@ +{ + "name": "AACharly", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ajv": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.0.tgz", + "integrity": "sha1-6yhAdG6dxIvV4GOjbj/UAMXqtak=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "azure-storage": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.6.0.tgz", + "integrity": "sha1-hHR+5UpL0ZS7lg+J8+/4nWes8c8=", + "requires": { + "browserify-mime": "1.2.9", + "extend": "1.2.1", + "json-edm-parser": "0.1.2", + "md5.js": "1.3.4", + "readable-stream": "2.0.6", + "request": "2.81.0", + "underscore": "1.8.3", + "uuid": "3.1.0", + "validator": "3.35.0", + "xml2js": "0.2.7", + "xmlbuilder": "0.4.3" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.16.3" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.10.1" + } + }, + "extend": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz", + "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=" + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + }, + "dependencies": { + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + } + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.16.3" + } + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "browserify-mime": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz", + "integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.0", + "har-schema": "2.0.0" + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-edm-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", + "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", + "requires": { + "jsonparse": "1.2.0" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonparse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz", + "integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "nonce": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nonce/-/nonce-1.0.4.tgz", + "integrity": "sha1-7nMCrejBvvR28wG4yR9cxRpIdhI=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sax": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.2.tgz", + "integrity": "sha1-c1/6o5oc/4/7lZjwIjq9sDqfsuo=" + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "validator": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-3.35.0.tgz", + "integrity": "sha1-PwcklALB/I/Ak8MsbkPXKnnModw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "xml2js": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.7.tgz", + "integrity": "sha1-GDhRi7AXQcrgh4urSRXklMMjBq8=", + "requires": { + "sax": "0.5.2" + } + }, + "xmlbuilder": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-0.4.3.tgz", + "integrity": "sha1-xGFLp04K0ZbmCcknLNnh3bKKilg=" + } + } +} diff --git a/this.bot.config.json b/this.bot.config.json new file mode 100644 index 000000000..592d52268 --- /dev/null +++ b/this.bot.config.json @@ -0,0 +1,91 @@ +{ + "displayName": "Gauss", + "codeName": "AAGauss", + "type": "Indicator", + "version": { + "major": 1, + "minor": 0, + "patch": 0 + }, + "devTeam": "AAMasters", + "dataSetVersion": "dataSet.V1", + "processes": [ + { + "name": "Multi-Period-Daily", + "description": "Produces files with the LRC Channel on a daily format.", + "startMode": { + "allMonths": { + "run": "false", + "minYear": "", + "maxYear": "" + }, + "oneMonth": { + "run": "false", + "year": "", + "month": "" + }, + "noTime": { + "run": "true" + }, + "fixedInterval": { + "run": "false", + "interval": 0 + } + }, + "normalWaitTime": 100, + "retryWaitTime": 10000, + "sleepWaitTime": 3600000, + "comaWaitTime": 86400000, + "statusDependencies": [ + { + "devTeam": "AAMasters", + "bot": "AAGauss", + "botVersion": { + "major": 1, + "minor": 0 + }, + "process": "Multi-Period-Daily", + "dataSetVersion": "dataSet.V1" + }, + { + "devTeam": "AAMasters", + "bot": "AAOlivia", + "botVersion": { + "major": 1, + "minor": 0 + }, + "process": "Multi-Period-Daily", + "dataSetVersion": "dataSet.V1" + } + ] + } + ], + "products": [ + { + "codeName": "LRCChannel", + "displayName": "LRCChannel", + "description": "Two sets of files per period that contains candles.", + "storageAccount": "aagauss", + "dataSets": [ + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ], + "filePath": "AAMasters/AAGauss.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/LRC-Channel/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json" + } + ], + "exchangeList": [ + { + "name": "Poloniex" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "Plotter", + "moduleName": "LRCChannel" + } + } + ] + +} \ No newline at end of file