From 3ec67e18913da45ada9a2c60fd0bb2e873135524 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Fri, 16 Mar 2018 17:49:30 +0100 Subject: [PATCH] Extraction Bot Added to Platform --- .vs/AACloud/v15/.suo | Bin 83968 -> 81408 bytes Extraction Bot Main Loop.js | 205 ++++++++++++++++++++++++++++++++++++ Project.njsproj | 5 +- Run.js | 50 ++++++++- this.config.json | 2 +- 5 files changed, 256 insertions(+), 6 deletions(-) create mode 100644 Extraction Bot Main Loop.js diff --git a/.vs/AACloud/v15/.suo b/.vs/AACloud/v15/.suo index 7b1ba2e916d9bf90ac04d78b88c7c0622f739ed0..e9ba96e1d3c8a8d06ac87a86c900984e2dc20427 100644 GIT binary patch delta 6132 zcmeI0dvMg%7037d_L0{Tc9SIud2SLOiFvSjAc4F#uZ@q82ZV#02q7ek z%0sa&*<<-tEE*T9fQ*l9ORO{2MX9yanL@RW)1gS!89SCDGKdYMq~E*zHpD5)6q)KD zUgpC&_x{ekd+$Bxp5Oh&wL|OrLbIcY^e+_8kit9jp7?du%WqM=N~N+cCo)1$~B6H!Ct6G6HPm22J#WUT71PCyj~} zy|Wd4wj!eySq2#kZUBWK69{_~WG&bPrVTVi7MCjz#00I-= zL#AT@svBsC&bbM-NH7nGpP3Jt02V6s#frRLk<9}QNy#m!h} zl93sO+C5+$SPwP;(c@9b5YPwufdROs8VceDwRyte`4@$6^3XWmH^HK(n5;Z#BQskh zJ+D*u_K)|Lun5H`V(iHa`#mjuip0|flH47wO+GGrP^1=GP& zAjSw&shU+qsAz!^2$u$SJQuofshGf2$bd^lN8!?B5O8TL^l3o&!2%|NnLyaifu|-3 zhlomvA}b-Y@PG~4V5;WH+9XX5nz%?CLs7gyo0PB{Rk6p*fgOlF79)t#j-J6Q(Xa^c z0j-&O1{&hXg>dL6QmG^$rmcb0DtZuPu%d@ThADa^WH^`z48RB?faq^hWE5nyqEA+2 z9ArF50Er+8m6d1z+6yEIGS}(>Va71JjnT=QK^fzF$V09 z|FEame^1@|iVzZ6RRV#G5Ul$VYA4LxqwkRx5uexhNehX)C)5Uu(6ba5=jDnup?1W^a{POt`a0SDkWC+81^ zJ4wuQVm~!|KTDcVn%nSX?3dY@T(7YU+hfmVYSXaZN4+C)L6ZEcg<|ESiL^p?6_J&# z8P)RX1d8EL<{L#$dE%Kub+)RR%Q9?oZ8F6teENB>>umVR-A_LA$a}8kyC1=jW4UD1 zGbPw<%coxqG!$z66Mn(IojlnZcg;Ck&YuM7w_6i<=l&W+cIp}pqZ`^kJ7jsFCvz`uZa zaz>FCA^C7#zAhHSs>pkBnIr|_xhP!xOgdY923p}?S$RI0jXA$OdAzyrXkOiEJdM(I^_yp@kIAhz(~X?GWIDgGEK@rP z^L~Iw%;}txJ`c$pFGwC(ID-cl#`7j;DWq9ID%6UUu1(W5%dy%qze{Swd~znI)TQuY z$)eR^l&!ozIh{SmVw7Yq-lHy{imos4n*;EOP(Id(BE_!-ybs;o^eNUUT zt++2bE1h6eKMw+Pi(cYYwvS(mM#07)awtLc_Czy4F*bK_5KB6 zD=|Qe$|>$xO#8A8XE6c>@Y7nMn&W-t#ZB~7F_F9W4UM>=jm3`lT&a{-W zBhN#+p&=i!)t717i1FrOC--fa(OIe<+D%Z0`;!TGeLNEU$ zKk-@=cmFOmA?|XU8PhP&wYRS}*K~ArX0LRV$ZM)8HU6p=Z`u?w zn?YW4*v`9Ni{WG`mUryd^WY=zc)!@DA*K^)y!ZIqMsX**RHpjGovMUi{<4BQkEHTr z@5i$1cpCD;Uyc0%Bh^%&IAU_OXC9&2VK_K@Jsh{o$BzICvt67v+}EQvdU-W=Vj&OR9dpis&dM* zES54$#cYesW~<2C*jqHW-O*xeXWv1eZdIG3q_>6F9Eq*C4iUtbzhvT!bRO>9<3b!` z&a?-9Nn+n2D>ocLlwY)}^{q{peXT@DBK?-jOr^4WI(2)ycRi@4+r>#^_tPfhfyd82 z7g6%T=LK^MHhdV?)hM#FZbR$r+4hZm=*!ZtII!R~4?p(m%%Q=LzgH=MU)jHjT_3fH z8@u?9@t1b%wfXJ(yUg0FQ&oOXCX+Grj*AQ%d&2@r2^pf7=A*BmEa?sioRmp+xD zEryeP!jDzuD)F5n$`9H5o8JH5HhVuklt|LIOWb^DUm73vL=2z0fnHbtkTS1+X@k?g zqm;>=yF-UVL+QMBcqp45lJM0o4x)@tDl?VH{T3>eI}M~6?#ZJqnw?g%9W;iHZmw*zWy)Xu|CQd@YU+1`VU=^f`kA7 delta 5261 zcmdT{eNa@_6@T~b2P`bGi@<`QtSb_TpetZRg1W%Q=$I(@-PBP~5w#QzEXLpmn>N)n zXd-)5RMe1H+ew^s6kb}Y9i26?Gnwerq;*pNaIEnU+uGKcjwXW>p}({HmMntPA)RK@ zv-8_??z#7!d(X$c_dV}ddhZ^?o?;Q*Ic=gGd%agmn|$Vv!YxUXcMdhlO+rWa? zP|O0TWBC|z%F(o0x7E5HiYo$tAT#iwwaP|mdUJMfUyvq2$jhrgS~eL&c_Kv4j?x(hHL?!USvrs({r14`KR2n5;lv z2XLf#YI?_H9~D{y4}LLha0g^>YlY1x*T$Z#`cohgQ(5d^gV#Dc> zQ-K+P5y${|OtQx98lRwXCwM3wD;HiCmqclY>cnMGnlmWAlF)%3GYeo8)?PyeMiZ$T1z<~78+lKK4FK8n+gKyDf zHnA1*Hh?{A20sD_Yz-NpjX61qu@K?_3t$D}f!@}tCDaj>+_`#|@Wqx?`z$dbP2zMJNe! zK}-sy*p&CdIDW(-sE29MLRl)O({A2t5~KXfS!w%OkOrKF(%HY0g4e z+o53c70%Mj;Gs@YPmP7YHwk`-t1_e~Ps%POBhpuwVBG=rPT&>br$8$zV-i8&XZC{c z1NH-Lz(IiZhrkbOGCN5rpRwNHOp*tz@fX#E5DClHENh|~EQ z1rgkkghUlfMyT-xw{^aacSSYb%lol>J(`;Gcl^(?r4-AGUG^1u41p!ki}hQKTnXnA z=zjfua|17&0}4_$%Swjq%PB~F4XxLKJ%A6u;`2m0ACAIh+L_o!JY<$A>}D~o02N3!yqp1gA%T@XB1*EihhAek2eP7V~J0}_V%+OQM z)GeXl6>TwALdU@?x^D~yPrbj>DDx_2$-bBEWUtH^=JbZZ^lDFQ1ZKV~g0reUZ$#*o zm9kPRE30K?ldPds_LMhw76p>_Y{*3mvTvRWt+* z_YCZhAYY41b?xyBn$R3emAekB$M?E)IvjHJ($x_(f7fv+77KD*&1>th2_q%7#FFJk zM$`#7oD7_hXje;V%qyRt+47O`6mu{iuMTF~(`u%U-A|Bxw}nb?F`GLkF&%H?`-PPXYMU22t~YMEa;zPvyJK0Ta$^w6Sg9PFzkk2C>i)q1G`CsjR8to71mn8tY#!0Ixo2os$vS3105XBsYHC+9v(X>lZpsTTJO#$~-)h{O4TJ=Mp4o1e8&d zkF5Txh_VfJp6bmWvUZNA3l}ES@(Z~!3p`bx#s>TR>Wv%fgFV?76tS1bn@SoQ)-`yl z>VkTUe}pnP;x6t+p@lY^blQsis4}%cR%eHHiJ(Wq4}ysuRb? z%4diBM!A;@$$ILT*cb4|UA?lg#{SHP8jQ)Lc^8Vmp?}c<|Asf677glrH-Y!6^yk#u z3mX=GJZ^l^p{)L8Rh-PyExi;)W8_4-Qkq5nGg;i7#nttgp5Y zNB}ZwOB}49u)d)XbB;}Vbk|VUDo)N!yvxfBki~D}9Sd?(um;X1RRk4*e?Eno+=GhD z9Hmtp){)EWh<>PT47REKWJ%X2USUg?1TH&%(+Scz|634NQ^)CbiSDUWOSWyrO87M^ zKpZ5QjWhrMvp$Hta0I+2h-)TOO~OO1J5}vUM34Ba{~PvB9NU{Z4Lj`MhH}% z;cb|jq9P$8!3dE*Ld*c4@Jv)uFp_S5m`W3VRW@Ab?Sq^zD_XXwp}M}||F!Cp`l}A7 zXCOY)q(~`~I@|MA*L%1ZakYJSi!tSq`RF?D6?_S#IC0(QOEaaX@I{}Co4^S^3DQ|A zNthv~sp3kX;F7Q|`%aed*r7_etad}=>SbT=XWU@l^bDZUr}AQkO1(?>pTnnIl|vCM zZ7w3`-!j$8YaP0-t23k2_`jSMT{mXxyW__Sr@s6AW8zf<#ousr-_8)%1SwyR?yk)h zw*+1OqK)t2Z3R1+5?zuKGT?7@~tk9F=dTIApDdMc4OHjng>PLs2Lg$g3ZEq$CTleLBaZ~rmabZTU6^g6A<^KJ}!a|>& YO85OMi)<^h>DsBzIKDnYv_g{p4eU`nxc~qF diff --git a/Extraction Bot Main Loop.js b/Extraction Bot Main Loop.js new file mode 100644 index 000000000..6c11cfa21 --- /dev/null +++ b/Extraction Bot Main Loop.js @@ -0,0 +1,205 @@ +exports.newExtractionBotMainLoop = function newExtractionBotMainLoop(BOT) { + + let bot = BOT; + const ROOT_DIR = './'; + + const MODULE_NAME = "Extraction Bot Main Loop"; + const FULL_LOG = true; + + let USER_BOT_MODULE; + let COMMONS_MODULE; + + const DEBUG_MODULE = require(ROOT_DIR + 'Debug Log'); + const logger = DEBUG_MODULE.newDebugLog(); + logger.fileName = MODULE_NAME; + logger.bot = bot; + + let thisObject = { + initialize: initialize, + run: run + }; + + let processConfig; + + return thisObject; + + function initialize(pBotPath, pProcessConfig, callBackFunction) { + + try { + if (FULL_LOG === true) { logger.write("[INFO] initialize -> Entering function."); } + processConfig = pProcessConfig; + + USER_BOT_MODULE = require(pBotPath + "/" + pProcessConfig.name + "/" + 'User.Bot'); + + try { + COMMONS_MODULE = require(pBotPath + "/" + 'Commons'); + } catch (err) { + // Nothing happens since COMMONS modules are optional. + } + + callBackFunction(global.DEFAULT_OK_RESPONSE); + + } catch (err) { + logger.write("[ERROR] initialize -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function run(callBackFunction) { + + try { + if (FULL_LOG === true) { logger.write("[INFO] run -> Entering function."); } + + loop(); + + function loop() { + + try { + if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Entering function."); } + + /* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */ + + const UTILITIES = require(ROOT_DIR + 'Utilities'); + const FILE_STORAGE = require(ROOT_DIR + 'File Storage'); + const DEBUG_MODULE = require(ROOT_DIR + 'Debug Log'); + const STATUS_REPORT = require(ROOT_DIR + 'Status Report'); + const POLONIEX_CLIENT_MODULE = require(ROOT_DIR + 'Poloniex API Client'); + + /* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */ + + global.processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution. + + /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ + + let userBot; + + let nextWaitTime; + + initializeUserBot(); + + function initializeUserBot() { + + if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> initializeUserBot -> Entering function."); } + + usertBot = USER_BOT_MODULE.newUserBot(bot, COMMONS_MODULE, UTILITIES, DEBUG_MODULE, FILE_STORAGE, STATUS_REPORT, POLONIEX_CLIENT_MODULE); + + usertBot.initialize(undefined, undefined, onInizialized); + + function onInizialized(err) { + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write("[INFO] run -> loop -> initializeUserBot -> onInizialized > Execution finished well. :-)"); + startUserBot(); + return; + } + break; + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write("[ERROR] run -> loop -> initializeUserBot -> onInizialized > Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + break; + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + logger.write("[ERROR] run -> loop -> initializeUserBot -> onInizialized > Operation Failed. Aborting the process."); + callBackFunction(err); + return; + } + break; + } + } + } + + function startUserBot() { + + if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> startUserBot -> Entering function."); } + + usertBot.start(onFinished); + + function onFinished(err) { + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write("[INFO] run -> loop -> startUserBot -> onFinished > Execution finished well. :-)"); + nextWaitTime = 'Normal'; + loopControl(nextWaitTime); + return; + } + break; + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write("[ERROR] run -> loop -> startUserBot -> onFinished > Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + break; + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + logger.write("[ERROR] run -> loop -> startUserBot -> onFinished > Operation Failed. Aborting the process."); + callBackFunction(err); + return; + } + break; + } + } + } + + } catch (err) { + logger.write("[ERROR] run -> loop -> err = " + err.message); + callBackFunction(err); + } + } + + function loopControl(nextWaitTime) { + + if (FULL_LOG === true) { logger.write("[INFO] run -> loopControl -> nextWaitTime = " + nextWaitTime); } + + /* Here we check if we must stop the loop gracefully. */ + + if (shallWeStop() === true) { + + if (FULL_LOG === true) { logger.write("[INFO] run -> loopControl -> Stopping the Loop Gracefully. See you next time! :-)"); } + callBackFunction(global.DEFAULT_OK_RESPONSE); + return; + + } + + /* Extraction bots are going to be executed after a configured period of time after the last execution ended. This is to avoid overlapping executions. */ + + switch (nextWaitTime) { + case 'Normal': { + if (FULL_LOG === true) { logger.write("[INFO] run -> loopControl -> Restarting Loop in " + (processConfig.executionWaitTime / 1000) + " seconds."); } + setTimeout(loop, processConfig.executionWaitTime); + } + break; + case 'Retry': { + if (FULL_LOG === true) { logger.write("[INFO] run -> loopControl -> Restarting Loop in " + (processConfig.retryWaitTime / 1000) + " seconds."); } + setTimeout(loop, processConfig.retryWaitTime); + } + break; + } + } + + function shallWeStop() { + + var fs = require('fs'); + + try { + + global.PLATFORM_CONFIG = JSON.parse(fs.readFileSync('this.config.json', 'utf8')); + return JSON.parse(global.PLATFORM_CONFIG.stopGracefully); + } + catch (err) { + const logText = "[ERROR] 'readConfig' - ERROR : " + err.message; + console.log(logText); + + return; + } + } + } + + catch (err) { + logger.write("[ERROR] run -> err = " + err.message); + } + } +}; diff --git a/Project.njsproj b/Project.njsproj index 6af1a8042..1e4cc3cba 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -13,7 +13,7 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) Project - Trading-Process + Poloniex-Live-Trades C:\Program Files\nodejs\node.exe False @@ -23,6 +23,9 @@ Code + + Code + diff --git a/Run.js b/Run.js index c5238708c..616bd6b7b 100644 --- a/Run.js +++ b/Run.js @@ -3,7 +3,7 @@ const FULL_LOG = true; /* The following global variable tells the system if it is running on test mode or production. */ -global.RUNNING_MODE = 'Production'; // 'Testnet', 'Mixed' or 'Production' +global.RUNNING_MODE = 'Testnet'; // 'Testnet', 'Mixed' or 'Production' /* You do not have funds at the exchange and still want run your bot? No problem activate the exchange simulation mode: */ @@ -149,6 +149,7 @@ global.FILE_PATH_ROOT = botConfig.devTeam + "/" + botConfig.codeName + "." + bot const INTERVAL_EXECUTOR_MODULE = require('./Interval Executor'); const TRADING_BOT_MAIN_LOOP_MODULE = require('./Trading Bot Main Loop'); const INDICATOR_BOT_MAIN_LOOP_MODULE = require('./Indicator Bot Main Loop'); +const EXTRACTION_BOT_MAIN_LOOP_MODULE = require('./Extraction Bot Main Loop'); /* Now we will see which are the script Arguments. We expect the name of the process to run, since that is what it should be defined at the Task Scheduller. */ @@ -214,14 +215,18 @@ for (let i = 0; i < botConfig.processes.length; i++) { function startProcess() { switch (bot.type) { - case 'Trading': { - runTradingBot(processConfig); + case 'Extraction': { + runExtractionBot(processConfig); return; } case 'Indicator': { runIndicatorBot(processConfig); return; } + case 'Trading': { + runTradingBot(processConfig); + return; + } } } } @@ -233,7 +238,45 @@ for (let i = 0; i < botConfig.processes.length; i++) { } } +function runExtractionBot(pProcessConfig) { + try { + if (FULL_LOG === true) { logger.write("[INFO] runExtractionBot -> Entering function."); } + + let extractionBotMainLoop = EXTRACTION_BOT_MAIN_LOOP_MODULE.newExtractionBotMainLoop(botConfig); + extractionBotMainLoop.initialize(global.PLATFORM_CONFIG.bot.path, pProcessConfig, onInitializeReady); + + function onInitializeReady(err) { + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + extractionBotMainLoop.run(whenRunFinishes); + + function whenRunFinishes(err) { + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + logger.write("[INFO] runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully. :-)"); + console.log("Bot execution finished sucessfully. :-)"); + + } else { + + logger.write("[ERROR] runExtractionBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message); + logger.write("[ERROR] runExtractionBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); + logger.write("[ERROR] runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bye. :-("); + } + } + + } else { + logger.write("[ERROR] runExtractionBot -> onInitializeReady -> err = " + err.message); + logger.write("[ERROR] runExtractionBot -> onInitializeReady -> Bot will not be started. "); + } + } + } + catch (err) { + logger.write("[ERROR] runExtractionBot -> err = " + err.message); + } +} function runIndicatorBot(pProcessConfig) { @@ -275,7 +318,6 @@ function runIndicatorBot(pProcessConfig) { } } - function runTradingBot(pProcessConfig) { try { diff --git a/this.config.json b/this.config.json index 53b059787..5d0bc2469 100644 --- a/this.config.json +++ b/this.config.json @@ -6,7 +6,7 @@ "patch": 0 }, "bot": { - "path": "../Bots/AAMasters/AAMariam-Trading-Bot" + "path": "../Bots/AAMasters/AACharly-Extraction-Bot" }, "stopGracefully": "false" } \ No newline at end of file