| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391 |
- /*
- copyright (c) 2018 jones
- http://www.apache.org/licenses/LICENSE-2.0
- 开源项目 https://github.com/jones2000/HQChart
- jones_2000@163.com
- 分析家语法编译器
- */
- //日志
- import { JSConsole } from "./umychart.console.wechat.js"
- import { JSCommonData } from "./umychart.data.wechat.js"; //行情数据结构体 及涉及到的行情算法(复权,周期等)
- import { JSNetwork } from "./umychart.network.wechart.js"
- //配色资源
- import {
- g_JSChartResource,
- JSCHART_LANGUAGE_ID,
- g_JSChartLocalization,
- } from './umychart.resource.wechat.js'
- import
- {
- IFrameSplitOperator,
- } from './umychart.framesplit.wechat.js'
- import
- {
- JSIndexScript,
- } from './umychart.index.data.wechat.js'
- import {
- HQ_DATA_TYPE,
- ChartData, HistoryData,
- SingleData, MinuteData,
- } from "./umychart.data.wechat.js";
- import
- {
- g_MinuteCoordinateData,
- MARKET_SUFFIX_NAME ,
- } from "./umychart.coordinatedata.wechat.js";
- var g_JSComplierResource=
- {
- Domain : "http://127.0.0.1:8080", //API域名
- CacheDomain : "http://127.0.0.1:8087", //缓存域名
- CustomFunction: //定制函数
- {
- Data:new Map() //自定义函数 key=函数名, Value:{ID:函数名, Callback: }
- },
- CustomDataFunction: //自定义数据函数
- {
- //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息, ArgCount:参数个数 }
- Data:new Map(
- [
- [
- "L2_VOLNUM",
- {
- Name:"L2_VOLNUM",
- Description:"单数分档,按: N(0--1):(超大+大)/(中+小),M(0--1):买/卖二类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
- ArgCount:2
- }
- ],
- [
- "L2_VOL",
- {
- Name:"L2_VOL",
- Description:"成交量分档,按: N(0--3):超大/大/中/小四档处理,M(0--3):买入/卖出/主买/主卖四类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
- ArgCount:2
- }
- ],
- [
- "L2_AMO",
- {
- Name:"L2_AMO",
- Description:"成交额分档,按: N(0--3):超大/大/中/小四档处理,M(0--3):买入/卖出/主买/主卖四类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
- ArgCount:2
- }
- ]
- ])
- },
- CustomVariant: //自定义变量
- {
- Data:new Map() //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息 }
- },
- IsCustomFunction:function(name)
- {
- if (g_JSComplierResource.CustomFunction.Data.has(name)) return true;
- return false;
- },
- IsCustomDataFunction:function(name)
- {
- if (g_JSComplierResource.CustomDataFunction.Data.has(name)) return true;
- return false;
- },
- IsCustomVariant:function(name)
- {
- if (g_JSComplierResource.CustomVariant.Data.has(name)) return true;
- return false;
- },
- GetDrawTextIcon:function(id)
- {
- //图标对应的字符代码
- let mapIcon=new Map(
- [
- [1,{Symbol:'↑',Color:'rgb(238,44,44)'} ],[2,{Symbol:'↓',Color:'rgb(0,139,69)'} ],
- [3,{Symbol:'😧'} ],[4,{Symbol:'😨'} ],[5,{Symbol:'😁'} ],[6,{Symbol:'😱'} ],
- [7,{Symbol:'B',Color:'rgb(238,44,44)'} ],[8,{Symbol:'S',Color:'rgb(0,139,69)'} ],
- [9,{Symbol:'💰'} ],[10,{Symbol:'📪'} ],[11,{Symbol:'👆'} ],[12,{Symbol:'👇'} ],
- [13,{Symbol:'B',Color:'rgb(178,34,34)'}, ],[14,{Symbol:'S',Color:'rgb(0,139,69)'} ],
- [36,{Symbol:'Χ',Color:'rgb(238,44,44)'} ],[37,{Symbol:'X',Color:'rgb(0,139,69)'} ],
- [38,{Symbol:'▲',Color:'rgb(238,44,44)'} ],[39,{Symbol:'▼',Color:'rgb(0,139,69)'} ],
- [40,{Symbol:'◉',Color:'rgb(238,44,44)'}], [41,{Symbol:'◈',Color:'rgb(238,44,44)'}],
- [42,{Symbol:'📌'}], [43,{Symbol:'💎'}], [44,{Symbol:'🥇'}],[45,{Symbol:'🥈'}],[46,{Symbol:'🥉'}],[47,{Symbol:'🏅'}]
- ]);
- var icon=mapIcon.get(id);
- return icon;
- },
- }
- var Messages = {
- BadGetterArity: 'Getter must not have any formal parameters',
- BadSetterArity: 'Setter must have exactly one formal parameter',
- BadSetterRestParameter: 'Setter function argument must not be a rest parameter',
- ConstructorIsAsync: 'Class constructor may not be an async method',
- ConstructorSpecialMethod: 'Class constructor may not be an accessor',
- DeclarationMissingInitializer: 'Missing initializer in %0 declaration',
- DefaultRestParameter: 'Unexpected token =',
- DuplicateBinding: 'Duplicate binding %0',
- DuplicateConstructor: 'A class may only have one constructor',
- DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
- ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer',
- GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts',
- IllegalBreak: 'Illegal break statement',
- IllegalContinue: 'Illegal continue statement',
- IllegalExportDeclaration: 'Unexpected token',
- IllegalImportDeclaration: 'Unexpected token',
- IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list',
- IllegalReturn: 'Illegal return statement',
- InvalidEscapedReservedWord: 'Keyword must not contain escaped characters',
- InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence',
- InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
- InvalidLHSInForIn: 'Invalid left-hand side in for-in',
- InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
- InvalidModuleSpecifier: 'Unexpected token',
- InvalidRegExp: 'Invalid regular expression',
- LetInLexicalBinding: 'let is disallowed as a lexically bound name',
- MissingFromClause: 'Unexpected token',
- MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
- NewlineAfterThrow: 'Illegal newline after throw',
- NoAsAfterImportNamespace: 'Unexpected token',
- NoCatchOrFinally: 'Missing catch or finally after try',
- ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
- Redeclaration: '%0 \'%1\' has already been declared',
- StaticPrototype: 'Classes may not have static property named prototype',
- StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
- StrictDelete: 'Delete of an unqualified identifier in strict mode.',
- StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block',
- StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
- StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
- StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
- StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
- StrictModeWith: 'Strict mode code may not include a with statement',
- StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
- StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
- StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
- StrictReservedWord: 'Use of future reserved word in strict mode',
- StrictVarName: 'Variable name may not be eval or arguments in strict mode',
- TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
- UnexpectedEOS: 'Unexpected end of input',
- UnexpectedIdentifier: 'Unexpected identifier',
- UnexpectedNumber: 'Unexpected number',
- UnexpectedReserved: 'Unexpected reserved word',
- UnexpectedString: 'Unexpected string',
- UnexpectedTemplate: 'Unexpected quasi %0',
- UnexpectedToken: 'Unexpected token %0',
- UnexpectedTokenIllegal: 'Unexpected token ILLEGAL',
- UnknownLabel: 'Undefined label \'%0\'',
- UnterminatedRegExp: 'Invalid regular expression: missing /'
- };
- var Regex = {
- // Unicode v8.0.0 NonAsciiIdentifierStart:
- NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/,
- // Unicode v8.0.0 NonAsciiIdentifierPart:
- NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
- }
- var Character =
- {
- FromCodePoint: function (cp) {
- return (cp < 0x10000) ? String.fromCharCode(cp) :
- String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
- String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
- },
- //是否是空格 https://tc39.github.io/ecma262/#sec-white-space
- IsWhiteSpace:function(cp)
- {
- return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) ||
- (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0);
- },
- //是否换行 https://tc39.github.io/ecma262/#sec-line-terminators
- IsLineTerminator:function(cp)
- {
- return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029);
- },
- // https://tc39.github.io/ecma262/#sec-names-and-keywords
- IsIdentifierStart:function(cp)
- {
- return (cp === 0x24) || (cp === 0x5F) ||
- (cp >= 0x41 && cp <= 0x5A) ||
- (cp >= 0x61 && cp <= 0x7A) ||
- (cp === 0x5C) ||
- //【】▲▼
- (cp===0x3010 || cp===0x3011 || cp===0x25B2 || cp===0x25BC) ||
- ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(Character.FromCodePoint(cp)));
- },
- IsIdentifierPart: function (cp)
- {
- return (cp === 0x24) || (cp === 0x5F) ||
- (cp >= 0x41 && cp <= 0x5A) ||
- (cp >= 0x61 && cp <= 0x7A) ||
- (cp >= 0x30 && cp <= 0x39) ||
- (cp === 0x5C) || (cp===0x23) ||
- //【】▲▼
- (cp===0x3010 || cp===0x3011 || cp===0x25B2 || cp===0x25BC) ||
- ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(Character.FromCodePoint(cp)));
- },
- // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
- IsDecimalDigit: function (cp)
- {
- return (cp >= 0x30 && cp <= 0x39); // 0..9
- },
- IsHexDigit: function (cp)
- {
- return (cp >= 0x30 && cp <= 0x39) || (cp >= 0x41 && cp <= 0x46) || (cp >= 0x61 && cp <= 0x66); // a..f
- },
- IsOctalDigit: function (cp)
- {
- return (cp >= 0x30 && cp <= 0x37); // 0..7
- }
- }
- function HexValue(ch)
- {
- return '0123456789abcdef'.indexOf(ch.toLowerCase());
- }
- function OctalValue(ch)
- {
- return '01234567'.indexOf(ch);
- }
- var TOKEN_NAME={};
- TOKEN_NAME[1 /* BooleanLiteral */] = 'Boolean';
- TOKEN_NAME[2 /* EOF */] = '<end>';
- TOKEN_NAME[3 /* Identifier */] = 'Identifier';
- TOKEN_NAME[4 /* Keyword */] = 'Keyword';
- TOKEN_NAME[5 /* NullLiteral */] = 'Null';
- TOKEN_NAME[6 /* NumericLiteral */] = 'Numeric';
- TOKEN_NAME[7 /* Punctuator */] = 'Punctuator';
- TOKEN_NAME[8 /* StringLiteral */] = 'String';
- TOKEN_NAME[9 /* RegularExpression */] = 'RegularExpression';
- TOKEN_NAME[10 /* Template */] = 'Template';
- //DYNAINFO() 转换
- //["DYNA_NOW",null], //DYNA_NOW 现价 DYNAINFO(7) 即时行情数据 没有现价时(比如在开盘前),返回昨收盘价
- //["DYNA_ZAF",null], //DYNA_ZAF 涨幅 DYNAINFO(14) 即时行情数据(沪深京早盘竞价期间使用匹配价的涨幅) 转换成幅度需要乘100
- //["DYNA_LB", null], //DYNA_LB DYNAINFO(17) 量比 即时行情数据
- //["DYNA_ZAS",null], //DYNA_ZAS DYNAINFO(24) 返回涨速 报价界面行情数据 转换成幅度需要乘100
- //["SELLVOL", null], //返回内盘,即DYNAINFO(22) 即时行情数据
- //["BUYVOL", null], //返回外盘,即DYNAINFO(21) 即时行情数据
- const MAP_DYNAINFO_SHORTCUT=new Map(
- [
- ['DYNA_NOW', { Name:"DYNA_NOW", ID:7 } ],
- ['DYNA_LB', { Name:"DYNA_LB", ID:17 } ],
- ['DYNA_ZAS', { Name:"DYNA_ZAS", ID:24 } ],
- ['SELLVOL', { Name:"SELLVOL", ID:22 }],
- ['BUYVOL', { Name:"BUYVOL", ID:21 } ],
- ]
- );
- //编译异常, 错误类
- function ErrorHandler()
- {
- this.Error=[];
- this.IsTolerant=false;
- this.RecordError=function(error)
- {
- this.Error.push(error);
- }
- this.ConstructError=function(msg,column)
- {
- let error=new Error(msg);
- //通过自己抛异常并自己截获 来获取调用堆栈信息
- try
- {
- throw error;
- }
- catch(base)
- {
- if (Object.create && Object.defineProperties)
- {
- error=Object.create(base);
- error.Column=column;
- }
- }
- return error;
- }
- this.CreateError=function(index, line, col, description)
- {
- let msg='Line ' + line + ': ' + description;
- let error=this.ConstructError(msg,col);
- error.Index=index;
- error.LineNumber=line;
- error.Description=description;
- return error;
- }
- this.ThrowError=function(index, line, col, description)
- {
- let error=this.CreateError(index,line,col,description);
- throw error;
- }
- this.TolerateError=function(index, line, col, description)
- {
- const error = this.CreateError(index, line, col, description);
- if (this.IsTolerant) this.RecordError(error);
- else throw error;
- }
- }
- //扫描类
- function Scanner(code, ErrorHandler)
- {
- this.Source=code;
- this.ErrorHandler=ErrorHandler;
- this.Length=code.length;
- this.Index=0;
- this.LineNumber=(code.length>0)?1:0;
- this.LineStart=0;
- this.CurlyStack=[];
- this.SaveState=function() //保存当前扫描状态
- {
- return { Index:this.Index, LineNumber:this.LineNumber, LineStart:this.LineStart };
- }
- this.RestoreState=function(state) //还原扫描状态
- {
- this.Index=state.Index;
- this.LineNumber=state.LineNumber;
- this.LineStart=state.LineStart;
- }
- this.IsEOF=function() //否是已经结束
- {
- return this.Index>=this.Length;
- }
- this.ThrowUnexpectedToken=function(message=Messages.UnexpectedTokenIllegal)
- {
- return this.ErrorHandler.ThrowError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message);
- }
- this.TolerateUnexpectedToken=function(message = Messages.UnexpectedTokenIllegal)
- {
- this.ErrorHandler.TolerateError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message);
- }
- this.IsKeyword=function(id)
- {
- return false;
- }
- this.CodePointAt = function (i)
- {
- let cp = this.Source.charCodeAt(i);
- if (cp >= 0xD800 && cp <= 0xDBFF)
- {
- let second = this.Source.charCodeAt(i + 1);
- if (second >= 0xDC00 && second <= 0xDFFF) {
- var first = cp;
- cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
- }
- }
- return cp;
- }
- //8进制->10进制
- this.OctalToDecimal=function(ch)
- {
- // \0 is not octal escape sequence
- let octal = (ch !== '0');
- let code = OctalValue(ch);
- if (!this.IsEOF() && Character.IsOctalDigit(this.Source.charCodeAt(this.Index)))
- {
- octal = true;
- code = code * 8 + OctalValue(this.Source[this.Index++]);
- // 3 digits are only allowed when string starts
- // with 0, 1, 2, 3
- if ('0123'.indexOf(ch) >= 0 && !this.IsEOF() && Character.IsOctalDigit(this.Source.charCodeAt(this.Index)))
- code = code * 8 + OctalValue(this.Source[this.Index++]);
- }
- return { Code: code, Octal: octal };
- }
- this.Lex=function()
- {
- if (this.IsEOF()) return { Type:2/*EOF*/, Value:'', LineNumber:this.LineNumber, LineStart:this.LineStart, Start:this.Index, End:this.Index };
- let cp=this.Source.charCodeAt(this.Index);
- //变量名 或 关键字
- if (Character.IsIdentifierStart(cp)) return this.ScanIdentifier();
- //( ) ; 开头 操作符扫描
- if (cp === 0x28 || cp === 0x29 || cp === 0x3B) return this.ScanPunctuator();
- //' " 开头 字符串扫描
- if (cp === 0x27 || cp === 0x22) return this.ScanStringLiteral();
- //. 开头 浮点型
- if (cp==0x2E)
- {
- if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index + 1)))
- return this.ScanNumericLiteral();
- return this.ScanPunctuator();
- }
- //数字
- if (Character.IsDecimalDigit(cp)) return this.ScanNumericLiteral();
-
- if (cp >= 0xD800 && cp < 0xDFFF)
- {
- if (Character.IsIdentifierStart(this.CodePointAt(this.Index))) return this.ScanIdentifier();
- }
- return this.ScanPunctuator();
- }
- //关键字 变量名 https://tc39.github.io/ecma262/#sec-names-and-keywords
- this.ScanIdentifier=function()
- {
- let type;
- let start=this.Index;
- //0x5C 反斜杠
- let id=((this.Source.charCodeAt(start)=== 0x5C) ? this.GetComplexIdentifier() : this.GetIdentifier());
- if (id.length) type=3; //Identifier
- else if (this.IsKeyword(id)) type=4; //Keyword
- else if (id==null) type=5; //NullLiteral
- else if (id=='true' || id=='false') type=1; //BooleanLiteral
- else type=3; //Identifier
- if (type!=3 && (start+id.length!=this.Index))
- {
- let restore=this.Index;
- this.Index=start;
- throw Messages.InvalidEscapedReservedWord;
- this.Index=restore;
- }
- if (id=='AND' || id=='OR') type=7 /*Punctuator*/;
- return { Type:type, Value:id, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index};
- }
- this.GetIdentifier=function()
- {
- let start=this.Index++; //start 保存进来的位置
- while(!this.IsEOF())
- {
- let ch=this.Source.charCodeAt(this.Index);
- if (ch==0x5C)
- {
- this.Index=start;
- return this.GetComplexIdentifier();
- }
- else if (ch >= 0xD800 && ch < 0xDFFF)
- {
- this.Index=start;
- return this.GetComplexIdentifier();
- }
- if (Character.IsIdentifierPart(ch)) ++this.Index;
- else break;
- }
- return this.Source.slice(start,this.Index);
- }
- this.GetComplexIdentifier=function()
- {
- let cp = this.CodePointAt(this.Index);
- let id = Character.FromCodePoint(cp);
- this.Index += id.length;
- // '\u' (U+005C, U+0075) denotes an escaped character.
- let ch;
- if (cp === 0x5C)
- {
- if (this.Source.charCodeAt(this.Index) !== 0x75)
- this.ThrowUnexpectedToken();
- ++this.Index;
- if (this.Source[this.Index] === '{')
- {
- ++this.Index;
- ch = this.ScanUnicodeCodePointEscape();
- }
- else
- {
- ch = this.ScanHexEscape('u');
- if (ch === null || ch === '\\' || !Character.IsIdentifierStart(ch.charCodeAt(0)))
- this.ThrowUnexpectedToken();
- }
- id = ch;
- }
- while (!this.IsEOF())
- {
- cp = this.CodePointAt(this.Index);
- if (!Character.IsIdentifierPart(cp))
- break;
- ch = Character.FromCodePoint(cp);
- id += ch;
- this.Index += ch.length;
- // '\u' (U+005C, U+0075) denotes an escaped character.
- if (cp === 0x5C)
- {
- id = id.substring(0, id.length - 1);
- if (this.Source.charCodeAt(this.Index) !== 0x75)
- this.ThrowUnexpectedToken();
- ++this.Index;
- if (this.Source[this.Index] === '{')
- {
- ++this.Index;
- ch = this.ScanUnicodeCodePointEscape();
- }
- else
- {
- ch = this.ScanHexEscape('u');
- if (ch === null || ch === '\\' || !Character.IsIdentifierPart(ch.charCodeAt(0)))
- this.ThrowUnexpectedToken();
- }
- id += ch;
- }
- }
- return id;
- }
- this.ScanUnicodeCodePointEscape=function()
- {
- const result = this.TryToScanUnicodeCodePointEscape();
- if (result === null)
- return this.ThrowUnexpectedToken();
-
- return result;
- }
- this.TryToScanUnicodeCodePointEscape=function()
- {
- let ch = this.Source[this.Index];
- let code = 0;
- // At least, one hex digit is required.
- if (ch === '}')
- return null;
- while (!this.IsEOF())
- {
- ch = this.Source[this.Index++];
- if (!Character.IsHexDigit(ch.charCodeAt(0)))
- break;
-
- code = code * 16 + HexValue(ch);
- }
- if (code > 0x10FFFF || ch !== '}')
- return null;
-
- return Character.FromCodePoint(code);
- }
- this.ScanHexEscape=function(prefix)
- {
- const len = (prefix === 'u') ? 4 : 2;
- let code = 0;
- for (let i = 0; i < len; ++i)
- {
- if (!this.IsEOF() && Character.IsHexDigit(this.Source.charCodeAt(this.Index)))
- {
- code = code * 16 + HexValue(this.source[this.Index++]);
- }
- else
- {
- return null;
- }
- }
- return String.fromCharCode(code);
- }
- //操作符 https://tc39.github.io/ecma262/#sec-punctuators
- this.ScanPunctuator=function()
- {
- let start=this.Index;
- let str=this.Source[this.Index];
- switch(str)
- {
- case '(':
- ++this.Index;
- break;
- case ')':
- case ';':
- case ',':
- ++this.Index;
- break;
- case '.':
- ++this.Index;
- /*if (this.Source[this.Index] === '.' && this.Source[this.Index + 1] === '.')
- {
- //Spread operator: ...
- this.Index += 2;
- str = '...';
- }
- */
- break;
- default:
- str=this.Source.substr(this.Index,3);
- if (str=='AND')
- {
- this.Index+=3;
- }
- else
- {
- str = this.Source.substr(this.Index, 2);
- if (str === '&&' || str === '||' || str === '==' || str === '!=' || str === '<>' || str === '<=' || str === '>=' || str === '=>' || str==':=' || str=='OR')
- {
- this.Index += 2;
- }
- else
- {
- str=this.Source[this.Index];
- if ('<>=!+-*%&|^/:'.indexOf(str) >= 0) ++this.Index;
- }
- }
- }
- if (this.Index==start)
- this.ThrowUnecpectedToken();
- return { Type:7/*Punctuator*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index };
- }
- //字符串 https://tc39.github.io/ecma262/#sec-literals-string-literals
- this.ScanStringLiteral=function()
- {
- let start=this.Index;
- let quote=this.Source[this.Index];
- ++this.Index;
- var octal=false;
- let str='';
- while(!this.IsEOF())
- {
- let ch=this.Source[this.Index++];
- if (ch==quote)
- {
- quote='';
- break;
- }
- else if (ch=='\\') //字符串转义
- {
- ch = this.Source[this.Index++];
- if (!ch || !Character.IsLineTerminator(ch.charCodeAt(0)))
- {
- switch (ch)
- {
- case 'u':
- if (this.Source[this.Index] === '{')
- {
- ++this.Index;
- str += this.ScanUnicodeCodePointEscape();
- }
- else
- {
- const unescapedChar = this.ScanHexEscape(ch);
- if (unescapedChar === null)
- this.ThrowUnexpectedToken();
-
- str += unescapedChar;
- }
- break;
- case 'x': //十六进制 它的转义规则:\x<hex>,\x后跟上2位十六进制数
- const unescaped = this.ScanHexEscape(ch);
- if (unescaped === null)
- this.ThrowUnexpectedToken(Messages.InvalidHexEscapeSequence);
-
- str += unescaped;
- break;
- case 'n': //换行符
- str += '\n';
- break;
- case 'r': //回车键
- str += '\r';
- break;
- case 't': //制表符
- str += '\t';
- break;
- case 'b': //后退键
- str += '\b';
- break;
- case 'f': //换页符
- str += '\f';
- break;
- case 'v': //垂直制表符
- str += '\x0B';
- break;
- case '8':
- case '9':
- str += ch;
- this.TolerateUnexpectedToken();
- break;
- default:
- if (ch && Character.IsOctalDigit(ch.charCodeAt(0))) //反斜杠后面跟3位八进制数,就代表一个转义字符
- {
- const octToDec = this.OctalToDecimal(ch);
- octal = octToDec.Octal || octal;
- str += String.fromCharCode(octToDec.Code);
- }
- else
- {
- str += ch;
- }
- break;
- }
- }
- }
- else if (Character.IsLineTerminator(ch.charCodeAt(0)))
- {
- break;
- }
- else
- {
- str+=ch;
- }
- }
- if (quote!='')
- {
- this.Index=start;
- this.ThrowUnecpectedToken();
- }
- return {Type:8/*StringLiteral*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index};
- }
- this.ScanNumericLiteral=function()
- {
- let start=this.Index;
- let ch=this.Source[this.Index];
- let num='';
- if (ch!='.')
- {
- num=this.Source[this.Index++];
- ch=this.Source[this.Index];
- // Hex number starts with '0x'. 16进制
- if (num=='0')
- {
- if (ch=='x' || ch=='X')
- {
- ++this.Index;
- return this.ScanHexLiteral(start);
- }
- }
- while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
- {
- num+=this.Source[this.Index++];
- }
-
- ch=this.Source[this.Index];
- }
- if (ch=='.')
- {
- num+=this.Source[this.Index++];
- while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
- {
- num+=this.Source[this.Index++];
- }
- ch=this.Source[this.Index];
- }
- //科学计数法
- if (ch=='e' || ch=='E')
- {
- num+=this.Source[this.Index++];
- ch=this.Source[this.Index];
- if (ch=='+' || ch=='-') num+=this.Source[this.Index];
- if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
- {
- while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
- {
- num+=this.Source[this.Index++];
- }
- }
- else
- {
- this.ThrowUnecpectedToken();
- }
- }
- if (Character.IsIdentifierStart(this.Source.charCodeAt(this.Index)))
- {
- this.ThrowUnecpectedToken();
- }
- return { Type:6/*NumericLiteral*/, Value:parseFloat(num), LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index };
- }
- //空格 或 注释
- this.ScanComments=function()
- {
- let comments;
- let start=(this.Index==0);
- while(!this.IsEOF())
- {
- let ch=this.Source.charCodeAt(this.Index);
- if (Character.IsWhiteSpace(ch)) //过滤掉空格
- {
- ++this.Index;
- }
- else if (Character.IsLineTerminator(ch))
- {
- ++this.Index;
- if (ch==0x0D && this.Source.charCodeAt(this.Index)==0x0A) ++this.Index; //回车+换行
- ++this.LineNumber;
- this.LineStart=this.Index;
- start=true;
- }
- else if (ch==0x2F) // //注释
- {
- ch=this.Source.charCodeAt(this.Index+1);
- if (ch==0x2F)
- {
- this.Index+=2;
- let comment=this.SkipSingleLineComment(2);
- start=true;
- }
- else
- {
- break;
- }
- }
- else if (ch == 0x7B) //{ } 注释
- {
- this.Index += 1;
- let comment = this.SkipMultiLineComment();
- }
- else
- {
- break;
- }
- }
- return comments;
- }
- this.SkipMultiLineComment = function ()
- {
- var comments = [];
- while (!this.IsEOF())
- {
- var ch = this.Source.charCodeAt(this.Index);
- if (Character.IsLineTerminator(ch))
- {
- ++this.LineNumber;
- ++this.Index;
- this.LineStart = this.Index;
- }
- else if (ch == 0x7D)
- {
- this.Index += 1;
- return comments;
- }
- else
- {
- ++this.Index;
- }
- }
- return comments;
- }
- //单行注释 https://tc39.github.io/ecma262/#sec-comments
- this.SkipSingleLineComment=function(offset)
- {
- let comments=[];
- while(!this.IsEOF())
- {
- let ch=this.Source.charCodeAt(this.Index);
- ++this.Index;
- if (Character.IsLineTerminator(ch))
- {
- if (ch === 13 && this.Source.charCodeAt(this.Index) === 10)
- ++this.Index;
- ++this.LineNumber;
- this.LineStart=this.Index;
- return comments;
- }
- }
- return comments;
- }
- this.ThrowUnecpectedToken=function(message)
- {
- if (!message) message = Messages.UnexpectedTokenIllegal;
- return this.ErrorHandler.ThrowError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message);
- }
- }
- function Tokenizer(code)
- {
- this.ErrorHandler=new ErrorHandler(); //错误信息处理类
- this.Scanner=new Scanner(code,this.ErrorHandler);
- this.Buffer=[];
- this.GetNextToken=function()
- {
- if (this.Buffer.length==0)
- {
- let comments=this.Scanner.ScanComments();
- if (!this.Scanner.IsEOF())
- {
- let token=this.Scanner.Lex();
- let entry={ Type:TOKEN_NAME[token.Type], Value:this.Scanner.Source.slice(token.Start, token.End)};
- this.Buffer.push(entry);
- }
- }
- return this.Buffer.shift();
- }
- }
- var Syntax = {
- AssignmentExpression: 'AssignmentExpression',
- AssignmentPattern: 'AssignmentPattern',
- ArrayExpression: 'ArrayExpression',
- ArrayPattern: 'ArrayPattern',
- ArrowFunctionExpression: 'ArrowFunctionExpression',
- AwaitExpression: 'AwaitExpression',
- BlockStatement: 'BlockStatement',
- BinaryExpression: 'BinaryExpression',
- BreakStatement: 'BreakStatement',
- CallExpression: 'CallExpression',
- CatchClause: 'CatchClause',
- ClassBody: 'ClassBody',
- ClassDeclaration: 'ClassDeclaration',
- ClassExpression: 'ClassExpression',
- ConditionalExpression: 'ConditionalExpression',
- ContinueStatement: 'ContinueStatement',
- DoWhileStatement: 'DoWhileStatement',
- DebuggerStatement: 'DebuggerStatement',
- EmptyStatement: 'EmptyStatement',
- ExportAllDeclaration: 'ExportAllDeclaration',
- ExportDefaultDeclaration: 'ExportDefaultDeclaration',
- ExportNamedDeclaration: 'ExportNamedDeclaration',
- ExportSpecifier: 'ExportSpecifier',
- ExpressionStatement: 'ExpressionStatement',
- ForStatement: 'ForStatement',
- ForOfStatement: 'ForOfStatement',
- ForInStatement: 'ForInStatement',
- FunctionDeclaration: 'FunctionDeclaration',
- FunctionExpression: 'FunctionExpression',
- Identifier: 'Identifier',
- IfStatement: 'IfStatement',
- ImportDeclaration: 'ImportDeclaration',
- ImportDefaultSpecifier: 'ImportDefaultSpecifier',
- ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
- ImportSpecifier: 'ImportSpecifier',
- Literal: 'Literal',
- LabeledStatement: 'LabeledStatement',
- LogicalExpression: 'LogicalExpression',
- MemberExpression: 'MemberExpression',
- MetaProperty: 'MetaProperty',
- MethodDefinition: 'MethodDefinition',
- NewExpression: 'NewExpression',
- ObjectExpression: 'ObjectExpression',
- ObjectPattern: 'ObjectPattern',
- Program: 'Program',
- Property: 'Property',
- RestElement: 'RestElement',
- ReturnStatement: 'ReturnStatement',
- SequenceExpression: 'SequenceExpression',
- SpreadElement: 'SpreadElement',
- Super: 'Super',
- SwitchCase: 'SwitchCase',
- SwitchStatement: 'SwitchStatement',
- TaggedTemplateExpression: 'TaggedTemplateExpression',
- TemplateElement: 'TemplateElement',
- TemplateLiteral: 'TemplateLiteral',
- ThisExpression: 'ThisExpression',
- ThrowStatement: 'ThrowStatement',
- TryStatement: 'TryStatement',
- UnaryExpression: 'UnaryExpression',
- UpdateExpression: 'UpdateExpression',
- VariableDeclaration: 'VariableDeclaration',
- VariableDeclarator: 'VariableDeclarator',
- WhileStatement: 'WhileStatement',
- WithStatement: 'WithStatement',
- YieldExpression: 'YieldExpression'
- };
- function Node()
- {
- this.IsNeedIndexData=false; //是否需要大盘数据
- this.IsNeedLatestData=false; //是否需要最新的个股行情数据
- this.IsNeedSymbolData=false; //是否需要下载股票数据
- this.IsNeedMarginData = new Set();
- this.IsNeedNewsAnalysisData = new Set(); //新闻统计数据
- this.IsNeedBlockIncreaseData = new Set(); //是否需要市场涨跌股票数据统计
- this.IsNeedSymbolExData = new Set(); //下载股票行情的其他数据
- this.FunctionData=[]; //{ID:, Args:, FunctionName: } FINVALUE(ID),FINONE(ID,Y,MMDD), FINANCE(ID)
- this.Dynainfo=[]; //{ID:, Args:, FunctionName: } DYNAINFO()
- this.IsAPIData = [] //加载API数据
- this.ExecuteIndex=[]; //执行调用指标
- this.OtherSymbolData=[]; //其他股票数据 key=股票代码(小写)
- this.PeriodSymbolData=[]; //跨周期数据 { Period:, VarName: }
- this.ErrorHandler=ErrorHandler;
- this.GetDataJobList=function() //下载数据任务列表
- {
- let jobs=[];
- if (this.IsNeedSymbolData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA});
- if (this.IsNeedIndexData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA});
- //最新的个股行情数据
- for(var i=0;i<this.Dynainfo.length;++i)
- {
- var item=this.Dynainfo[i];
- jobs.push(item);
- }
- //涨跌停家数统计
- for (var blockSymbol of this.IsNeedBlockIncreaseData)
- {
- jobs.push({ ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA, Symbol: blockSymbol });
- }
- //加载融资融券
- for (var jobID of this.IsNeedMarginData)
- {
- jobs.push({ID:jobID});
- }
- //加载新闻统计
- for (var jobID of this.IsNeedNewsAnalysisData)
- {
- jobs.push({ID:jobID});
- }
- for (var i in this.IsAPIData)
- {
- var item = this.IsAPIData[i];
- jobs.push(item);
- }
- for(var i in this.ExecuteIndex)
- {
- var item=this.ExecuteIndex[i];
- jobs.push(item);
- }
- //行情其他数据
- for (var jobID of this.IsNeedSymbolExData)
- {
- jobs.push({ ID:jobID });
- }
- for(var i in this.FunctionData)
- {
- var item=this.FunctionData[i];
- jobs.push(item);
- }
- for(var i in this.OtherSymbolData)
- {
- var item=this.OtherSymbolData[i];
- jobs.push(item);
- }
- return jobs;
- }
- this.VerifySymbolVariable = function (varName, token)
- {
- let setIndexName = new Set(['INDEXA', 'INDEXC', 'INDEXH', 'INDEXL', "INDEXO", "INDEXV", 'INDEXDEC', 'INDEXADV']);
- if (setIndexName.has(varName))
- {
- this.IsNeedIndexData=true;
- return;
- }
- let setSymbolDataName=new Set(['CLOSE','C','VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT']);
- if (setSymbolDataName.has(varName))
- {
- this.IsNeedSymbolData=true;
- return;
- }
- if (varName === 'VOLR')
- {
- if (!this.IsNeedSymbolExData.has(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA))
- this.IsNeedSymbolExData.add(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA);
- return;
- }
- //CAPITAL流通股本(手), EXCHANGE 换手率, TOTALCAPITAL 总股本(手)
- let setVariantName=new Set(
- [
- "CAPITAL","TOTALCAPITAL","EXCHANGE",
- "HYBLOCK","DYBLOCK","GNBLOCK","FGBLOCK","ZSBLOCK","ZHBLOCK","ZDBLOCK","HYZSCODE",
- "GNBLOCKNUM","FGBLOCKNUM","ZSBLOCKNUM","ZHBLOCKNUM","ZDBLOCKNUM",
- "HYSYL","HYSJL","FROMOPEN",
- //资金流向
- "LARGEINTRDVOL","LARGEOUTTRDVOL",
- "TRADENUM","TRADEINNUM","TRADEOUTNUM",
- "LARGETRDINNUM","LARGETRDOUTNUM",
- "CUR_BUYORDER","CUR_SELLORDER",
- "ACTINVOL","ACTOUTVOL",
- "BIDORDERVOL","BIDCANCELVOL","AVGBIDPX",
- "OFFERORDERVOL","OFFERCANCELVOL","AVGOFFERPX",
- ]);
-
- if (setVariantName.has(varName))
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT, VariantName:varName };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.FunctionData.push(item);
- return;
- }
- if (MAP_DYNAINFO_SHORTCUT.has(varName))
- {
- var item=MAP_DYNAINFO_SHORTCUT.get(varName);
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA, Args:[item.ID], FunctionName:varName };
- this.Dynainfo.push(item);
- return;
- }
- if (g_JSComplierResource.IsCustomVariant(varName)) //自定义函数
- {
- var item={ VariantName:varName, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.FunctionData.push(item);
- return;
- }
- }
- this.VerifySymbolFunction = function (callee, args, token)
- {
- //自定义函数 可以覆盖系统内置函数
- if (g_JSComplierResource.IsCustomFunction(callee.Name))
- {
- var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA, Args:args}
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
- this.FunctionData.push(item);
- return;
- }
- //自定义数据函数
- if (g_JSComplierResource.IsCustomDataFunction(callee.Name))
- {
- var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_DATA_FUNCTION, Args:args}
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
- this.FunctionData.push(item);
- return;
- }
- if (callee.Name=='DYNAINFO')
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA, Args:args, FunctionName:callee.Name };
- this.Dynainfo.push(item);
- return;
- }
- //财务函数
- if (callee.Name=='FINANCE')
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:args, FunctionName:callee.Name };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.FunctionData.push(item);
- return;
- }
- if (callee.Name=="FINVALUE")
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE, Args:args, FunctionName:callee.Name };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.FunctionData.push(item);
- return;
- }
- if (callee.Name=="FINONE")
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE, Args:args, FunctionName:callee.Name };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.FunctionData.push(item);
- return;
- }
- //专业财务数据
- for(var i=0;i<JS_ARRAY_PROFESSIONAL_FINANCE.length;++i)
- {
- var financeItem=JS_ARRAY_PROFESSIONAL_FINANCE[i];
- if (financeItem.Name==callee.Name)
- {
- var item={ ID:financeItem.JobID, Args:args, FunctionName:callee.Name };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.FunctionData.push(item);
- return;
- }
- }
- if (callee.Name === 'MARGIN')
- {
- let jobID = JS_EXECUTE_JOB_ID.GetMarginJobID(args[0].Value);
- if (jobID && !this.IsNeedMarginData.has(jobID)) this.IsNeedMarginData.add(jobID);
- return;
- }
- if (callee.Name === 'NEWS')
- {
- let jobID = JS_EXECUTE_JOB_ID.GetNewsAnalysisID(args[0].Value);
- if (jobID && !this.IsNeedNewsAnalysisData.has(jobID)) this.IsNeedNewsAnalysisData.add(jobID);
- return;
- }
- if (callee.Name == 'COST' || callee.Name == 'WINNER' || callee.Name=='PWINNER') //筹码都需要换手率
- {
- //下载流通股
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:[7], FunctionName:"FINANCE", FunctionName2:callee.Name };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.FunctionData.push(item);
- return;
- }
- if (callee.Name=="INBLOCK")
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT, VariantName:"INBLOCK" }; //下载所有板块
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.FunctionData.push(item);
- return;
- }
- if (callee.Name === 'BETA') //beta需要下载上证指数
- {
- this.IsNeedIndexData = true;
- return;
- }
- if (callee.Name == 'UPCOUNT' || callee.Name == 'DOWNCOUNT') //上涨下跌个数
- {
- var blockSymbol = args[0].Value;
- if (!this.IsNeedBlockIncreaseData.has(blockSymbol)) this.IsNeedBlockIncreaseData.add(blockSymbol);
- return;
- }
- if (callee.Name=='STKINDI' || callee.Name=='CALCSTOCKINDEX') //指标调用
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Args:args, FunctionName:callee.Name };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.ExecuteIndex.push(item);
- return;
- }
- if (callee.Type==Syntax.Literal) //指标调用 "MA.MA1"(10,5,5)"
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Args:args, FunctionName:callee.Value, DynamicName:callee.Value };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.ExecuteIndex.push(item);
- return;
- }
- if (callee.Name == "LOADAPIDATA") //加载API数据
- {
- var item = { Name: callee.Name, ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA, Args: args };
- if (token) item.Token = { Index: token.Start, Line: token.LineNumber };
- this.IsAPIData.push(item);
- return;
- }
- let setStockDataName=new Set(['CLOSE',"C",'VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT','AMO','VOLINSTK']);
- if (setStockDataName.has(callee.Name))
- {
- var item= { Name:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA,Args:args };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
- this.OtherSymbolData.push(item);
- return;
- }
- }
- this.VerifySymbolLiteral=function(value,token)
- {
- if (IFrameSplitOperator.IsString(value))
- {
- if (value.indexOf('$')>0)
- {
- var aryValue=value.split('$');
- if (aryValue.length!=2) return;
- var item= { Literal:value, ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
-
- this.OtherSymbolData.push(item);
- }
- }
- }
- this.ExpressionStatement=function(expression)
- {
- return { Type:Syntax.ExpressionStatement, Expression:expression };
- }
- this.Script=function(body)
- {
- return {Type:Syntax.Program, Body:body, SourceType:'通达信脚本' };
- }
- this.SequenceExpression=function(expression)
- {
- return {Type:Syntax.SequenceExpression, Expression:expression };
- }
- this.BinaryExpression=function(operator, left, right)
- {
- let logical = (operator === '||' || operator === '&&' || operator=='AND' || operator=='OR');
- let type = logical ? Syntax.LogicalExpression : Syntax.BinaryExpression;
- return { Type:type, Operator:operator, Left:left, Right:right };
- }
- this.Literal=function(value,raw,token)
- {
- this.VerifySymbolLiteral(value, token);
- return { Type:Syntax.Literal, Value:value, Raw:raw };
- }
- this.Identifier = function (name, token)
- {
- this.VerifySymbolVariable(name, token);
- return { Type:Syntax.Identifier, Name:name};
- }
- this.AssignmentExpression=function (operator, left, right)
- {
- return { Type:Syntax.AssignmentExpression, Operator:operator, Left:left, Right:right };
- }
- //成员变量, 不需要检测
- this.MemberIdentifier=function(name, token)
- {
- return { Type:Syntax.Identifier, Name:name};
- }
- this.UnaryExpression=function(operator, argument)
- {
- return { Type:Syntax.UnaryExpression, Operator:operator, Argument:argument, Prefix:true };
- }
- this.EmptyStatement=function()
- {
- return { Type:Syntax.EmptyStatement };
- }
- this.CallExpression = function (callee, args, token)
- {
- this.VerifySymbolFunction(callee, args, token);
- return { Type:Syntax.CallExpression, Callee:callee, Arguments:args };
- }
- this.StaticMemberExpression = function (object, property,token)
- {
- this.VerifyMemberVariable(object,property, token);
- return { Type: Syntax.MemberExpression, Computed: false, Object: object, Property: property };
- }
- this.VerifyMemberVariable=function(object,property,token)
- {
- var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Member:{Object:object, Property:property} };
- if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
- this.ExecuteIndex.push(item);
- return;
- }
- }
- function JSParser(code)
- {
- this.ErrorHandler=new ErrorHandler();
- this.Scanner=new Scanner(code, this.ErrorHandler);
- this.Node=new Node(); //节点创建
- this.LookAhead={Type:2, Value:'', LineNumber:this.Scanner.LineNumber, LineStart:0, Start:0, End:0 };
- this.HasLineTerminator=false;
- this.Context = {
- IsModule: false,
- await: false,
- allowIn: true,
- allowStrictDirective: true,
- allowYield: true,
- FirstCoverInitializedNameError: null,
- IsAssignmentTarget: false,
- IsBindingElement: false,
- InFunctionBody: false,
- inIteration: false,
- inSwitch: false,
- labelSet: {},
- Strict: false
- };
- this.PeratorPrecedence =
- {
- ')': 0,
- ';': 0,
- ',': 0,
- ']': 0,
- '||': 1,
- 'OR':1,
- '&&': 2,
- 'AND':2,
- '|': 3,
- '^': 4,
- '&': 5,
- '=': 6,
- '==': 6,
- '!=': 6,
- '<>': 6,
- '===': 6,
- '!==': 6,
- '<': 7,
- '>': 7,
- '<=': 7,
- '>=': 7,
- '<<': 8,
- '>>': 8,
- '>>>': 8,
- '+': 9,
- '-': 9,
- '*': 11,
- '/': 11,
- '%': 11
- };
- this.StartMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 };
- this.LastMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 };
- this.Initialize=function()
- {
- this.NextToken();
- this.LastMarker={ Index:this.Scanner.Index, Line:this.Scanner.LineNumber, Column:this.Scanner.Index-this.Scanner.LineStart };
- }
-
- this.CreateNode=function()
- {
- return { Index:this.StartMarker.Index, Line:this.StartMarker.Line, Column:this.StartMarker.Column };
- }
- this.StartNode=function(token, lastLineStart)
- {
- if (lastLineStart==void 0) { lastLineStart=0; }
- let column = token.Start - token.LineStart;
- let line = token.LineNumber;
- if (column < 0)
- {
- column += lastLineStart;
- line--;
- }
-
- return { Index: token.Start, Line: line, Column: column };
- }
- this.Match=function(value)
- {
- return this.LookAhead.Type==7 /*Punctuator*/ && this.LookAhead.Value==value;
- }
- this.Expect=function(value)
- {
- let token=this.NextToken();
- if (token.Type!=7 /*Punctuator*/ || token.Value!=value)
- this.ThrowUnexpectedToken(token);
- }
- //是否是赋值操作符
- this.MatchAssign=function()
- {
- if (this.LookAhead.Type!=7 /*Punctuator*/) return false;
- let op=this.LookAhead.Value;
- return op==':' || op==':=';
- }
- this.GetTokenRaw=function(token)
- {
- return this.Scanner.Source.slice(token.Start, token.End);
- }
- this.NextToken=function()
- {
- let token=this.LookAhead;
- this.LastMarker.Index=this.Scanner.Index;
- this.LastMarker.Line=this.Scanner.LineNumber;
- this.LastMarker.Column=this.Scanner.Index-this.Scanner.LineStart;
- this.CollectComments(); //过滤注释 空格
- if (this.Scanner.Index !== this.StartMarker.Index)
- {
- this.StartMarker.Index = this.Scanner.Index;
- this.StartMarker.Line = this.Scanner.LineNumber;
- this.StartMarker.Column = this.Scanner.Index - this.Scanner.LineStart;
- }
- let next=this.Scanner.Lex();
- this.HasLineTerminator=(token.LineNumber!=next.LineNumber);
- if (next && this.Context.Strict && next.Type==3/*Identifier */)
- {
- //TODO:
- }
- this.LookAhead=next;
- return token;
- }
- this.CollectComments=function()
- {
- this.Scanner.ScanComments();
- }
- this.ParseScript=function()
- {
- let node=this.CreateNode();
- let body=this.ParseDirectivePrologues();
-
- while(this.LookAhead.Type!=2 /*EOF*/)
- {
- body.push(this.ParseStatementListItem())
- }
- return this.Finalize(node,this.Node.Script(body));
- }
- //https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive
- this.ParseDirective=function()
- {
- let token=this.LookAhead;
- let node=this.CreateNode();
- let expr=this.ParseExpression();
- }
- this.ParseDirectivePrologues=function()
- {
- let firstRestricted=null;
- let body=[];
- while(true)
- {
- let token=this.LookAhead;
- if (token.Type!=8 /*StringLiteral*/) break;
- let statement=this.ParseDirective();
- body.push(statement);
- }
- return body;
- }
- // https://tc39.github.io/ecma262/#sec-block
- this.ParseStatementListItem=function()
- {
- let statement;
- this.Context.IsAssignmentTarget=true;
- this.Context.IsBindingElement=true;
- if (this.LookAhead.Type==4 /*Keyword*/)
- {
- }
- else
- {
- statement=this.ParseStatement();
- }
- return statement;
- }
- // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations
- this.ParseStatement=function()
- {
- let statement;
- switch(this.LookAhead.Type)
- {
- case 1 /* BooleanLiteral */:
- case 5 /* NullLiteral */:
- case 6 /* NumericLiteral */:
- case 8 /* StringLiteral */:
- case 10 /* Template */:
- case 9 /* RegularExpression */:
- statement = this.ParseExpressionStatement();
- break;
- case 7 /* Punctuator */:
- let value = this.LookAhead.Value;
- if (value === '(') statement = this.ParseExpressionStatement();
- else if (value === ';') statement = this.ParseEmptyStatement();
- else statement = this.ParseExpressionStatement();
- break;
- case 3 /* Identifier */:
- statement = this.ParseLabelledStatement();
- break;
- case 4 /* Keyword */:
- break;
- default:
- statement="error";
- }
- return statement;
- }
-
- // https://tc39.github.io/ecma262/#sec-empty-statement
- this.ParseEmptyStatement=function()
- {
- let node=this.CreateNode();
- this.Expect(';');
- return this.Finalize(node, this.Node.EmptyStatement());
- }
- //https://tc39.github.io/ecma262/#sec-labelled-statements
- this.ParseLabelledStatement=function()
- {
- let node=this.CreateNode();
- let expr=this.ParseExpression();
- this.ConsumeSemicolon();
- let statement = new this.Node.ExpressionStatement(expr);
- return this.Finalize(node, statement);
- }
- // https://tc39.github.io/ecma262/#sec-comma-operator
- this.ParseExpression=function()
- {
- let startToken=this.LookAhead;
- let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
- if (this.Match(','))
- {
- let expressions=[];
- expressions.push(expr);
- while(this.LookAhead.Type!=2 /*EOF*/)
- {
- if (!this.Match(',')) break;
- this.NextToken();
- expressions.push(this.IsolateCoverGrammar(this.ParseAssignmentExpression));
- }
- expr=this.Finalize(this.StartNode(startToken),this.Node.SequenceExpression(expressions));
- }
- return expr;
- }
- this.ParseAssignmentExpression=function()
- {
- let expr;
- let startToken=this.LookAhead;
- let token=startToken;
- expr=this.ParseConditionalExpression();
- if (this.MatchAssign())
- {
- if (!this.Context.IsAssignmentTarget)
- {
- let marker=expr.Marker;
- this.ThrowUnexpectedError(marker.Index,marker.Line,marker.Column,Messages.InvalidLHSInAssignment);
- }
- if (!this.Match('=') && !this.Match(':'))
- {
- this.Context.IsAssignmentTarget=false;
- this.Context.IsBindingElement=false;
- }
- else
- {
- this.ReinterpretExpressionAsPattern(expr);
- }
- token=this.NextToken();
- let operator=token.Value;
- let right=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
- expr=this.Finalize(this.StartNode(startToken), this.Node.AssignmentExpression(operator, expr, right));
- this.Context.FirstCoverInitializedNameError=null;
- }
- return expr;
- }
- this.ParseConditionalExpression=function()
- {
- let startToken=this.LookAhead;
- let expr=this.InheritCoverGrammar(this.ParseBinaryExpression);
- return expr;
- }
- this.ParseBinaryExpression=function()
- {
- let startToken=this.LookAhead;
- let expr=this.InheritCoverGrammar(this.ParseExponentiationExpression);
- let token=this.LookAhead;
- var prec=this.BinaryPrecedence(token);
- if (prec>0)
- {
- this.NextToken();
- this.Context.IsAssignmentTarget=false;
- this.Context.IsBindingElement=false;
- let markers=[startToken,this.LookAhead];
- let left=expr;
- let right=this.IsolateCoverGrammar(this.ParseExponentiationExpression);
- let stack=[left,token.Value,right];
- let precedences = [prec];
- while(true)
- {
- prec=this.BinaryPrecedence(this.LookAhead);
- if (prec<=0) break;
- while(stack.length>2 && prec<=precedences[precedences.length-1])
- {
- right=stack.pop();
- let operator=stack.pop();
- precedences.pop();
- left=stack.pop();
- markers.pop();
- let node=this.StartNode(markers[markers.length - 1]);
- stack.push(this.Finalize(node, this.Node.BinaryExpression(operator, left, right)));
- }
- //Shift
- stack.push(this.NextToken().Value);
- precedences.push(prec);
- markers.push(this.LookAhead);
- stack.push(this.IsolateCoverGrammar(this.ParseExponentiationExpression));
- }
- let i=stack.length-1;
- expr=stack[i];
- let lastMarker=markers.pop();
- while(i>1)
- {
- let marker=markers.pop();
- let lastLineStart=lastMarker && lastMarker.LineStart;
- let node=this.StartNode(marker, lastLineStart);
- let operator=stack[i-1];
- expr=this.Finalize(node, this.Node.BinaryExpression(operator, stack[i - 2], expr));
- i-=2;
- lastMarker=marker;
- }
- }
- return expr;
- }
- this.ParseExponentiationExpression=function()
- {
- let startToken=this.LookAhead;
- let expr=this.InheritCoverGrammar(this.ParseUnaryExpression);
- return expr;
- }
- this.ParseUnaryExpression=function()
- {
- let expr;
- if (this.Match('+') || this.Match('-'))
- {
- let node=this.StartNode(this.LookAhead);
- let token=this.NextToken();
- expr=this.InheritCoverGrammar(this.ParseUnaryExpression);
- expr=this.Finalize(node, this.Node.UnaryExpression(token.Value, expr));
- this.Context.IsAssignmentTarget=false;
- this.Context.IsBindingElement=false;
- }
- else
- {
- expr=this.ParseUpdateExpression();
- }
- return expr;
- }
- // https://tc39.github.io/ecma262/#sec-update-expressions
- this.ParseUpdateExpression=function()
- {
- let expr;
- let startToken=this.LookAhead;
- expr=this.InheritCoverGrammar(this.ParseLeftHandSideExpressionAllowCall);
- return expr;
- }
- this.ParseLeftHandSideExpressionAllowCall=function()
- {
- let startToken=this.LookAhead;
- let expr;
- expr=this.InheritCoverGrammar(this.ParsePrimaryExpression);
- while(true)
- {
- if (this.Match('.'))
- {
- this.Context.IsBindingElement = false;
- this.Context.IsAssignmentTarget = true;
- this.Expect('.');
- const property = this.ParseMemberIdentifierName();
- expr = this.Finalize(this.StartNode(startToken), this.Node.StaticMemberExpression(expr, property,startToken));
- }
- else if (this.Match('('))
- {
- this.Context.IsBindingElement=false;
- this.Context.IsAssignmentTarget=false;
- var args=this.ParseArguments(); //解析 调用参数
- expr = this.Finalize(this.StartNode(startToken), this.Node.CallExpression(expr, args, startToken));
- }
- else
- {
- break;
- }
- }
- return expr;
- }
- /*
- BooleanLiteral = 1,
- EOF=2,
- Identifier=3,
- Keyword=4,
- NullLiteral=5,
- NumericLiteral=6,
- Punctuator=7,
- StringLiteral=9,
- RegularExpression=9,
- Template=10
- */
- this.IsIdentifierName = function (token)
- {
- return token.Type === 3 //Identifier
- || token.Type === 4 //Keyword
- || token.Type === 1 //BooleanLiteral
- || token.Type === 5;//NullLiteral;
- }
- this.ParseIdentifierName = function ()
- {
- const node = this.CreateNode();
- const token = this.NextToken();
- if (!this.IsIdentifierName(token))
- {
- this.ThrowUnexpectedToken(token);
- }
- return this.Finalize(node, this.Node.Identifier(token.Value, token));
- }
- this.ParseMemberIdentifierName=function()
- {
- const node = this.CreateNode();
- const token = this.NextToken();
- if (!this.IsIdentifierName(token))
- {
- this.ThrowUnexpectedToken(token);
- }
- return this.Finalize(node, this.Node.MemberIdentifier(token.Value, token));
- }
- // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions
- this.ParseArguments=function()
- {
- this.Expect('(');
- var args=[];
- if (!this.Match(')'))
- {
- while(true)
- {
- let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
- args.push(expr);
- if (this.Match(')')) break;
- this.ExpectCommaSeparator();
- if (this.Match(')')) break;
- }
- }
- this.Expect(')');
- return args;
- }
- // Quietly expect a comma when in tolerant mode, otherwise delegates to expect().
- this.ExpectCommaSeparator=function()
- {
- this.Expect(',');
- }
- // https://tc39.github.io/ecma262/#sec-primary-expression
- this.ParsePrimaryExpression=function()
- {
- let node=this.CreateNode();
- let expr;
- var token, raw;
- switch(this.LookAhead.Type)
- {
- case 3:/* Identifier */
- token = this.NextToken();
- expr = this.Finalize(node, this.Node.Identifier(token.Value, token));
- break;
- case 6:/* NumericLiteral */
- case 8:/* StringLiteral */
- this.Context.IsAssignmentTarget=false;
- this.Context.IsBindingElement=false;
- token=this.NextToken();
- raw=this.GetTokenRaw(token);
- expr=this.Finalize(node, this.Node.Literal(token.Value,raw,token));
- break;
- case 7:/* Punctuator */
- switch(this.LookAhead.Value)
- {
- case '(':
- this.Context.IsBindingElement=false;
- expr=this.InheritCoverGrammar(this.ParseGroupExpression);
- break;
- default:
- expr=this.ThrowUnexpectedToken(this.NextToken())
- }
- break;
- default:
- expr = this.ThrowUnexpectedToken(this.NextToken());
- }
- return expr;
- }
- this.ParseGroupExpression=function()
- {
- let expr;
- this.Expect('(');
- if (this.Match(')'))
- {
- this.NextToken();
- }
- else
- {
- let startToken=this.LookAhead;
- let params=[];
- let arrow=false;
- this.Context.IsBindingElement=true;
- expr=this.InheritCoverGrammar(this.ParseAssignmentExpression);
- if (this.Match(','))
- {
- let expressions=[];
- this.Context.IsAssignmentTarget=false;
- expressions.push(expr);
- while(this.LookAhead.Type!=2 /* EOF */)
- {
- if (!this.Match(',')) break;
- this.NextToken();
- if (this.Match(')'))
- {
- }
- }
- }
- if (!arrow)
- {
- this.Expect(')');
- this.Context.IsBindingElement=false;
- }
- }
- return expr;
- }
- // https://tc39.github.io/ecma262/#sec-expression-statement
- this.ParseExpressionStatement=function()
- {
- let node=this.CreateNode();
- let expr=this.ParseExpression();
- this.ConsumeSemicolon();
- return this.Finalize(node,this.Node.ExpressionStatement(expr));
- }
- this.ConsumeSemicolon=function()
- {
- if (this.Match(';'))
- {
- this.NextToken();
- }
- else if (!this.HasLineTerminator)
- {
- //if (this.LookAhead.Type!=2/*EOF*/ && !this.Match('}'))
- this.LastMarker.Index=this.StartMarker.Index;
- this.LastMarker.Line=this.StartMarker.Line;
- this.LastMarker.Column=this.StartMarker.Column;
- }
- }
- this.ReinterpretExpressionAsPattern=function(expr)
- {
- switch(expr.Type)
- {
- case Syntax.Identifier:
- case Syntax.MemberExpression:
- case Syntax.AssignmentExpression:
- break;
- default:
- break;
- }
- }
- this.Finalize=function(marker,node)
- {
- node.Marker={ Line:marker.Line, Column:marker.Column, Index:marker.Index };
- return node;
- }
- this.BinaryPrecedence = function (token)
- {
- let op = token.Value;
- let precedence;
- if (token.Type === 7 /* Punctuator */) precedence = this.PeratorPrecedence[op] || 0;
- else precedence = 0;
-
- return precedence;
- };
- this.IsolateCoverGrammar=function(parseFunction)
- {
- let previousIsBindingElement=this.Context.IsBindingElement;
- let previousIsAssignmentTarget=this.Context.IsAssignmentTarget;
- let previousFirstCoverInitializedNameError=this.Context.FirstCoverInitializedNameError;
- this.Context.IsBindingElement=true;
- this.Context.IsAssignmentTarget=true;
- this.Context.FirstCoverInitializedNameError=null;
- let result=parseFunction.call(this);
- if (this.Context.FirstCoverInitializedNameError!=null)
- {
- //错误 this.throwUnexpectedToken(this.context.firstCoverInitializedNameError);
- }
- this.Context.IsBindingElement=previousIsBindingElement;
- this.Context.IsAssignmentTarget=previousIsAssignmentTarget;
- this.Context.FirstCoverInitializedNameError=previousFirstCoverInitializedNameError;
- return result;
- }
- this.InheritCoverGrammar = function (parseFunction)
- {
- let previousIsBindingElement = this.Context.IsBindingElement;
- let previousIsAssignmentTarget = this.Context.IsAssignmentTarget;
- let previousFirstCoverInitializedNameError = this.Context.FirstCoverInitializedNameError;
- this.Context.IsBindingElement = true;
- this.Context.IsAssignmentTarget = true;
- this.Context.FirstCoverInitializedNameError = null;
- let result = parseFunction.call(this);
- this.Context.IsBindingElement = this.Context.IsBindingElement && previousIsBindingElement;
- this.Context.IsAssignmentTarget = this.Context.IsAssignmentTarget && previousIsAssignmentTarget;
- this.Context.FirstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.Context.FirstCoverInitializedNameError;
- return result;
- };
- this.ThrowUnexpectedToken=function(token,message)
- {
- throw this.UnexpectedTokenError(token,message);
- }
- this.ThrowUnexpectedError=function(index,line,column,message)
- {
- let msg=message || "执行异常";
-
- return this.ErrorHandler.ThrowError(index,line,column,msg);
- }
- this.UnexpectedTokenError=function(token,message)
- {
- let msg=message || Messages.UnexpectedToken;
- let value='ILLEGAL';
- if (token)
- {
- if (!message)
- {
- }
- value=token.Value;
- }
- msg=msg.replace("%0",value);
- if (token && typeof(token.LineNumber)=='number')
- {
- let index=token.Start;
- let line=token.LineNumber;
- let lastMarkerLineStart=this.LastMarker.Index-this.LastMarker.Column;
- let column=token.Start-lastMarkerLineStart+1;
- return this.ErrorHandler.CreateError(index,line,column,msg);
- }
- else
- {
- let index=this.LastMarker.Index;
- let line=this.LastMarker.Line;
- let column=this.LastMarker.Column+1;
- return this.ErrorHandler.CreateError(index,line,column,msg);
- }
- }
- }
- /*
- 算法类
- */
- function JSAlgorithm(errorHandler, symbolData)
- {
- this.ErrorHandler=errorHandler;
- this.SymbolData = symbolData; //股票数据
- //相加
- this.Add=function(data,data2)
- {
- let isNumber=typeof(data)=='number';
- let isNumber2=typeof(data2)=='number';
- //单数值相加
- if (isNumber && isNumber2) return data+data2;
- //都是数组相加
- let result=[];
- if (!isNumber && !isNumber2)
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]+data2[i];
- }
- }
- return result;
- }
- //单数据和数组相加
- let value;
- let aryData;
- if (isNumber)
- {
- value=data;
- aryData=data2;
- }
- else
- {
- value=data2;
- aryData=data;
- }
- for(let i in aryData)
- {
- result[i]=null;
- if (this.IsNumber(aryData[i]) && this.IsNumber(value)) result[i]=value+aryData[i];
- }
- return result;
- }
- //相减
- this.Subtract=function(data,data2)
- {
- let isNumber=typeof(data)=='number';
- let isNumber2=typeof(data2)=='number';
- //单数值相减
- if (isNumber && isNumber2) return data-data2;
- //都是数组相减
- let result=[];
- if (!isNumber && !isNumber2)
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]-data2[i];
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if (this.IsNumber(data) && this.IsNumber(data2[i])) result[i]=data-data2[i];
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if (this.IsNumber(data[i]) && this.IsNumber(data2)) result[i]=data[i]-data2;
- }
- }
- return result;
- }
- //相乘
- this.Multiply=function(data,data2)
- {
- let isNumber=typeof(data)=='number';
- let isNumber2=typeof(data2)=='number';
- //单数值相乘
- if (isNumber && isNumber2) return data*data2;
- //都是数组相乘
- let result=[];
- if (!isNumber && !isNumber2)
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]*data2[i];
- }
- }
- return result;
- }
- //单数据和数组相乘
- let value;
- let aryData;
- if (isNumber)
- {
- value=data;
- aryData=data2;
- }
- else
- {
- value=data2;
- aryData=data;
- }
- for(let i in aryData)
- {
- result[i]=null;
- if (this.IsNumber(aryData[i]) && this.IsNumber(value)) result[i]=value*aryData[i];
- }
- return result;
- }
- //相除
- this.Divide=function(data,data2)
- {
- let isNumber=typeof(data)=='number';
- let isNumber2=typeof(data2)=='number';
- //单数值相除
- if (isNumber && isNumber2)
- {
- if (data2==0) return null; //除0判断
- return data/data2;
- }
- //都是数组相除
- let result=[];
- if (!isNumber && !isNumber2)
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if ( this.IsNumber(data[i]) && this.IsDivideNumber(data2[i]) ) result[i]=data[i]/data2[i];
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if ( this.IsNumber(data) && this.IsDivideNumber(data2[i]) ) result[i]=data/data2[i];
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if ( this.IsNumber(data[i]) && this.IsDivideNumber(data2) ) result[i]=data[i]/data2;
- }
- }
- return result;
- }
- //大于
- this.GT=function(data,data2)
- {
- let isNumber=IFrameSplitOperator.IsNumber(data);
- let isNumber2=IFrameSplitOperator.IsNumber(data2);
- //单数值比较
- if (isNumber && isNumber2) return (data>data2 ? 1 : 0);
- //都是数组比较
- let result=[];
- if (Array.isArray(data) && Array.isArray(data2))
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if (!IFrameSplitOperator.IsVaild(data[i])) continue;
- if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
- result[i]=(data[i]>data2[i] ? 1:0);
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if (!IFrameSplitOperator.IsVaild(data)) continue;
- if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
- result[i]=(data>data2[i] ? 1 : 0);
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if (!IFrameSplitOperator.IsVaild(data[i])) continue;
- if (!IFrameSplitOperator.IsVaild(data2)) continue;
- result[i]=(data[i]>data2 ? 1 : 0);
- }
- }
- return result;
- }
- //大于等于
- this.GTE=function(data,data2)
- {
- let isNumber=IFrameSplitOperator.IsNumber(data);
- let isNumber2=IFrameSplitOperator.IsNumber(data2);
- //单数值比较
- if (isNumber && isNumber2) return (data>=data2 ? 1 : 0);
- //都是数组比较
- let result=[];
- if (Array.isArray(data) && Array.isArray(data2))
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if (!IFrameSplitOperator.IsVaild(data[i])) continue;
- if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
- result[i]=(data[i]>=data2[i] ? 1:0);
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if (!IFrameSplitOperator.IsVaild(data)) continue;
- if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
- result[i]=(data>=data2[i] ? 1 : 0);
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if (!IFrameSplitOperator.IsVaild(data[i])) continue;
- if (!IFrameSplitOperator.IsVaild(data2)) continue;
- result[i]=(data[i]>=data2 ? 1 : 0);
- }
- }
- return result;
- }
- //小于
- this.LT=function(data,data2)
- {
- let isNumber=IFrameSplitOperator.IsNumber(data);
- let isNumber2=IFrameSplitOperator.IsNumber(data2);
- //单数值比较
- if (isNumber && isNumber2) return (data<data2 ? 1 : 0);
- //都是数组比较
- let result=[];
- if (Array.isArray(data) && Array.isArray(data2))
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if (!IFrameSplitOperator.IsVaild(data[i])) continue;
- if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
- result[i]=(data[i]<data2[i] ? 1:0);
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if (!IFrameSplitOperator.IsVaild(data)) continue;
- if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
- if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data<data2[i] ? 1 : 0);
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if (!IFrameSplitOperator.IsVaild(data[i])) continue;
- if (!IFrameSplitOperator.IsVaild(data2)) continue;
- result[i]=(data[i]<data2 ? 1 : 0);
- }
- }
- return result;
- }
- //小于等于
- this.LTE=function(data,data2)
- {
- let isNumber=IFrameSplitOperator.IsNumber(data);
- let isNumber2=IFrameSplitOperator.IsNumber(data2);
- //单数值比较
- if (isNumber && isNumber2) return (data>=data2 ? 1 : 0);
- //都是数组比较
- let result=[];
- if (Array.isArray(data) && Array.isArray(data2))
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if (!IFrameSplitOperator.IsVaild(data[i])) continue;
- if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
- result[i]=(data[i]<=data2[i] ? 1:0);
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if (!IFrameSplitOperator.IsVaild(data)) continue;
- if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
- result[i]=(data<=data2[i] ? 1 : 0);
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if (!IFrameSplitOperator.IsVaild(data[i])) continue;
- if (!IFrameSplitOperator.IsVaild(data2)) continue;
- result[i]=(data[i]<=data2 ? 1 : 0);
- }
- }
- return result;
- }
- //等于
- this.EQ=function(data,data2)
- {
- let isNumber=IFrameSplitOperator.IsNumber(data);
- let isNumber2=IFrameSplitOperator.IsNumber(data2);
- //单数值比较
- if (isNumber && isNumber2) return (data==data2 ? 1 : 0);
- //都是数组比较
- let result=[];
- if (Array.isArray(data) && Array.isArray(data2))
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i]==data2[i] ? 1:0);
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data==data2[i] ? 1 : 0);
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i]==data2 ? 1 : 0);
- }
- }
- return result;
- }
- //不等于
- this.NEQ = function (data, data2)
- {
- let isNumber=IFrameSplitOperator.IsNumber(data);
- let isNumber2=IFrameSplitOperator.IsNumber(data2);
- //单数值比较
- if (isNumber && isNumber2) return (data != data2 ? 1 : 0);
- //都是数组比较
- let result = [];
- if (Array.isArray(data) && Array.isArray(data2))
- {
- let count = Math.max(data.length, data2.length);
- for (let i = 0; i < count; ++i)
- {
- result[i] = null; //初始化
- if (i < data.length && i < data2.length)
- {
- if (!isNaN(data[i]) && !isNaN(data2[i])) result[i] = (data[i] != data2[i] ? 1 : 0);
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for (let i in data2)
- {
- result[i] = null;
- if (!isNaN(data) && !isNaN(data2[i])) result[i] = (data != data2[i] ? 1 : 0);
- }
- }
- else //数组-单数据
- {
- for (let i in data)
- {
- result[i] = null;
- if (!isNaN(data[i]) && !isNaN(data2)) result[i] = (data[i] != data2 ? 1 : 0);
- }
- }
- return result;
- }
- //AND &&
- this.And=function(data,data2)
- {
- let isNumber=typeof(data)=='number';
- let isNumber2=typeof(data2)=='number';
- //单数值 &&
- if (isNumber && isNumber2) return (data && data2 ? 1 : 0);
- //都是数组 &&
- let result=[];
- if (!isNumber && !isNumber2)
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i] && data2[i] ? 1:0);
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data && data2[i] ? 1 : 0);
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i] && data2 ? 1 : 0);
- }
- }
- return result;
- }
- //OR ||
- this.Or=function(data,data2)
- {
- let isNumber=typeof(data)=='number';
- let isNumber2=typeof(data2)=='number';
- //单数值 &&
- if (isNumber && isNumber2) return (data || data2 ? 1 : 0);
- //都是数组 &&
- let result=[];
- if (!isNumber && !isNumber2)
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i] || data2[i] ? 1:0);
- }
- }
- return result;
- }
- if (isNumber) //单数据-数组
- {
- for(let i in data2)
- {
- result[i]=null;
- if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data || data2[i] ? 1 : 0);
- }
- }
- else //数组-单数据
- {
- for(let i in data)
- {
- result[i]=null;
- if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i] || data2 ? 1 : 0);
- }
- }
- return result;
- }
- this.IF=function(data,trueData,falseData)
- {
- let isNumber=this.IsNumber(data);
- let isNumber2=this.IsNumber(trueData);
- let isNumber3=this.IsNumber(falseData);
- var isArray2=Array.isArray(trueData);
- var isArray3=Array.isArray(falseData);
-
- //单数值
- if (isNumber)
- {
- if (isNumber2 && isNumber3) return data?trueData:falseData;
- return data? trueData:falseData;
- }
-
- //都是数组
- let result=[];
- for(let i in data)
- {
- if (data[i])
- {
- if (isNumber2) result[i]=trueData;
- else if (isArray2) result[i]=trueData[i];
- else result[i]=null;
- }
- else
- {
- if (isNumber3) result[i]=falseData;
- else if (isArray3) result[i]=falseData[i];
- else result[i]=null;
- }
- }
- return result;
- }
- /*
- 根据条件求不同的值,同IF判断相反.
- 用法: IFN(X,A,B)若X不为0则返回B,否则返回A
- 例如: IFN(CLOSE>OPEN,HIGH,LOW)表示该周期收阴则返回最高值,否则返回最低值
- */
- this.IFN=function(data,trueData,falseData)
- {
- return this.IF(data,falseData,trueData);
- }
- //指标函数 函数名全部大写
- this.REF=function(data,n)
- {
- let result=[];
- if (typeof(n)=='number')
- {
- if (IFrameSplitOperator.IsNumber(data)) //单数值
- {
- if (n<0) return result;
- var kData=this.SymbolData.Data.Data;
- if (!kData || kData.length<=0) return result;
- var count=kData.length;
- for(var i=n;i<count;++i)
- {
- result[i]=data;
- }
- }
- else
- {
- if (data.length<=0) return result;
- if (n>=data.length) return result;
-
- result=data.slice(0,data.length-n);
-
- for(let i=0;i<n;++i)
- result.unshift(null);
- }
- }
- else //n 为数组的情况
- {
- for(let i=0;i<data.length;++i)
- {
- result[i]=null;
- if (i>=n.length) continue;
- var value=n[i];
- if (value>0 && value<=i) result[i]=data[i-value];
- else if (i) result[i]=result[i-1];
- else result[i]=data[i];
- }
- }
- return result;
- }
- //引用若干周期前的数据(未作平滑处理).
- //用法: REFV(X,A),引用A周期前的X值.A可以是变量.
- //平滑处理:当引用不到数据时进行的操作.
- //例如: REFV(CLOSE,BARSCOUNT(C)-1)表示第二根K线的收盘价.
- this.REFV=function(data,n)
- {
- let result=[];
- if (typeof(n)=='number')
- {
- if (data.length<=0) return result;
- if (n>=data.length) return result;
- result=data.slice(0,data.length-n);
- for(let i=0;i<n;++i) //不作平滑处理
- result.unshift(null);
- }
- else //n 为数组的情况
- {
- for(let i=0;i<data.length;++i)
- {
- result[i]=null;
- if (i>=n.length) continue;
- var value=n[i];
- if (value>=0 && value<=i) result[i]=data[i-value];
- }
- }
- return result;
- }
- //属于未来函数,引用若干周期后的数据(平滑处理).
- //用法: REFX(X,A),引用A周期后的X值.A可以是变量.
- //平滑处理:当引用不到数据时进行的操作.此函数中,平滑时使用上一个周期的引用值.
- //例如: TT:=IF(C>O,1,2);
- // REFX(CLOSE,TT);表示阳线引用下一周期的收盘价,阴线引用日后第二周期的收盘价.
- this.REFX=function(data,n)
- {
- let result=[];
- if (typeof(n)=='number')
- {
- if (data.length<=0) return result;
- if (n>=data.length) return result;
- result=data.slice(n,data.length);
- //平滑处理
- var lastData=data[data.length-1];
- for(let i=0;i<n;++i)
- result.push(lastData);
- }
- else //n 为数组的情况
- {
- var dataCount=data.length;
- for(let i=0;i<data.length;++i)
- {
- result[i]=null;
- if (i>=n.length) continue;
- var value=n[i];
- if (value>=0 && value+i<dataCount) result[i]=data[i+value];
- else if (i) result[i]=result[i-1];
- else result[i]=data[i];
- }
- }
- return result;
- }
- //属于未来函数,引用若干周期后的数据(未作平滑处理).
- //用法:REFXV(X,A),引用A周期后的X值.A可以是变量.
- //平滑处理:当引用不到数据时进行的操作.
- //例如: REFXV(CLOSE,1)表示下一周期的收盘价,在日线上就是明天收盘价
- this.REFXV=function(data,n)
- {
- let result=[];
- if (typeof(n)=='number')
- {
- if (data.length<=0) return result;
- if (n>=data.length) return result;
- result=data.slice(n,data.length);
- //平滑处理
- for(let i=0;i<n;++i)
- result.push(null);
- }
- else //n 为数组的情况
- {
- var dataCount=data.length;
- for(let i=0;i<data.length;++i)
- {
- result[i]=null;
- if (i>=n.length) continue;
- var value=n[i];
- if (value>=0 && value+i<dataCount) result[i]=data[i+value];
- }
- }
- return result;
- }
- //求最大值.
- //用法:MAX(A,B,C,D ..... ) 返回A,B,C,D ..... 中的较大值
- //例如: MAX(CLOSE-OPEN,0)表示若收盘价大于开盘价返回它们的差值,否则返回0
- this.MAX=function(args, node)
- {
- if (args.length==0) this.ThrowUnexpectedNode(node,'MAX() Error: 参数个数不能为0');
- if (args.length==1) return args[0];
- var aryData=[], aryNumber=[];
- for(var i in args)
- {
- var item=args[i];
- if (IFrameSplitOperator.IsNumber(item)) aryNumber.push(item);
- else if (Array.isArray(item)) aryData.push(item);
- }
- var maxNumber=null;
- if (aryNumber.length>0)
- {
- maxNumber=aryNumber[0];
- for(var i=1; i<aryNumber.length; ++i)
- {
- maxNumber=Math.max(maxNumber,aryNumber[i]);
- }
- }
- var maxAryData=null;
- if (aryData.length>0)
- {
- maxAryData=aryData[0].slice(0);
- for(var i=1;i<aryData.length;++i)
- {
- var dataItem=aryData[i];
- for(var j in dataItem)
- {
- var maxItem=maxAryData[j];
- var item=dataItem[j];
- if (!IFrameSplitOperator.IsNumber(maxItem)) continue;
- if (!IFrameSplitOperator.IsNumber(item))
- {
- maxAryData[j]=null;
- continue;
- }
-
- maxAryData[j]=Math.max(maxItem,item);
- }
- }
- }
- if (maxAryData==null && maxNumber!=null) return maxNumber;
- if (maxAryData && maxNumber==null) return maxAryData;
- for(var i in maxAryData)
- {
- if (!IFrameSplitOperator.IsNumber(maxAryData[i])) continue;
- maxAryData[i]=Math.max(maxAryData[i],maxNumber);
- }
-
- return maxAryData;
- }
- //求最小值.
- //用法:MIN(A,B, C, D .....)返回A,B, C ,D ......中的较小值
- //例如:MIN(CLOSE,OPEN)返回开盘价和收盘价中的较小值
- this.MIN=function(args, node)
- {
- if (args.length==0) this.ThrowUnexpectedNode(node,'MIN() Error: 参数个数不能为0');
- if (args.length==1) return args[0];
- var aryData=[], aryNumber=[];
- for(var i in args)
- {
- var item=args[i];
- if (IFrameSplitOperator.IsNumber(item)) aryNumber.push(item);
- else if (Array.isArray(item)) aryData.push(item);
- }
- var minNumber=null;
- if (aryNumber.length>0)
- {
- minNumber=aryNumber[0];
- for(var i=1; i<aryNumber.length; ++i)
- {
- minNumber=Math.min(minNumber,aryNumber[i]);
- }
- }
- var minAryData=null;
- if (aryData.length>0)
- {
- minAryData=aryData[0].slice(0);
- for(var i=1;i<aryData.length;++i)
- {
- var dataItem=aryData[i];
- for(var j in dataItem)
- {
- var minItem=minAryData[j];
- var item=dataItem[j];
- if (!IFrameSplitOperator.IsNumber(minItem)) continue;
- if (!IFrameSplitOperator.IsNumber(item))
- {
- minAryData[j]=null;
- continue;
- }
-
- minAryData[j]=Math.min(minItem,item);
- }
- }
- }
- if (minAryData==null && minNumber!=null) return minNumber;
- if (minAryData && minNumber==null) return minAryData;
- for(var i in minAryData)
- {
- if (!IFrameSplitOperator.IsNumber(minAryData[i])) continue;
- minAryData[i]=Math.min(minAryData[i],minNumber);
- }
-
- return minAryData;
- }
- //取正数
- this.ABS=function(data)
- {
- let result=[];
- for(let i in data)
- {
- result[i]=null;
- if (!isNaN(data[i])) result[i]=Math.abs(data[i]);
- }
- return result;
- }
- this.MA=function(data,dayCount)
- {
- let result=[];
- if (dayCount<=0) return result;
-
- if (!Array.isArray(dayCount))
- {
- dayCount=parseInt(dayCount);
- if (dayCount<=0) dayCount=1;
- if (!data || !data.length) return result;
-
- for(var i=0;i<data.length;++i)
- {
- result[i]=null;
- if (this.IsNumber(data[i])) break;
- }
- var data=data.slice(0); //复制一份数据出来
- for(var days=0;i<data.length;++i,++days)
- {
- if (days<dayCount-1)
- {
- result[i]=null;
- continue;
- }
- let preValue=data[i-(dayCount-1)];
- let sum=0;
- for(let j=dayCount-1;j>=0;--j)
- {
- var value=data[i-j];
- if (!this.IsNumber(value))
- {
- value=preValue; //空数据就取上一个数据
- data[i-j]=value;
- }
- else
- {
- preValue=value;
- }
- sum+=value;
- }
- result[i]=sum/dayCount;
- }
- }
- else
- {
- for(var i=0;i<data.length;++i)
- {
- result[i]=null;
- if (i>=dayCount.length) continue;
- var sumCount=dayCount[i];
- if (!this.IsNumber(sumCount)) continue;
- if (sumCount<=0) continue;
-
- var sum=0;
- var count=0;
- for(var j=i, k=0;j>=0 && k<sumCount;--j,++k)
- {
- sum+=data[j];
- ++count;
- }
- if (count>0) result[i]=sum/count;
- }
- }
- return result;
- }
- //指数平均数指标 EMA(close,10)
- //N 支持周期数组
- this.EMA=function(data,dayCount)
- {
- var result = [];
- if (data.length<=0) return result;
- if (Array.isArray(dayCount))
- {
- for(var i=0;i<dayCount.length;++i)
- {
- var period=dayCount[i];
- if (!this.IsNumber(period)) continue;
- period=parseInt(period); //周期用整数
- if (period<=0) continue;
- if (period>i+1) period=i+1;
- //EMA(N) = 2/(N+1)*C + (N-1)/(N+1)*EMA', EMA'为前一天的ema
- var EMAFactor=[ 2/ (period + 1), (period - 1) / (period + 1)];
- var ema=null;
- var lastEMA=null;
- for(var j=0;j<period;++j)
- {
- var index=i-(period-j-1);
- var value=data[index];
- if (!this.IsNumber(value)) coninue;
- if (lastEMA==null)
- {
- ema=value; //第一个EMA为第一个数据的价格
- lastEMA=ema;
- }
- else
- {
- ema = EMAFactor[0] * value + EMAFactor[1] * lastEMA;
- lastEMA=ema;
- }
- }
- result[i]=ema;
- }
- }
- else
- {
- dayCount=parseInt(dayCount);
- if (dayCount<=0) return result;
-
- var offset=0;
- //取首个有效数据
- for(;offset<data.length;++offset)
- {
- if (data[offset]!=null && !isNaN(data[offset]))
- break;
- }
-
- var p1Index=offset;
- var p2Index=offset+1;
-
- result[p1Index]=data[p1Index];
- for(var i=offset+1;i<data.length;++i,++p1Index,++p2Index)
- {
- result[p2Index]=((2*data[p2Index]+(dayCount-1)*result[p1Index]))/(dayCount+1);
- }
- }
- return result;
- }
- this.XMA = function (data, n)
- {
- var result = [];
- var offset = 0;
- for (; offset < data.length; ++offset)
- {
- if (this.IsNumber(data[offset])) break;
- }
- var p = parseInt((n - 2) / 2);
- var sum = 0;
- var count = 0, start = 0, end = 0;
- for (var i = offset, j=0; i < data.length; ++i)
- {
- start = i - p - 1;
- end = i + (n - p) - 1;
- for (j = start; j < end; ++j)
- {
- if (j >= 0 && j < data.length)
- {
- if (this.IsNumber(data[j]))
- {
- sum += data[j];
- ++count;
- }
- }
- }
- if (count != 0) result[i] = (sum / count);
- else result[i] = null;
- sum = 0;
- count = 0;
- }
- return result;
- }
- /*
- SMA 移动平均
- 返回移动平均。
- 用法: SMA(X,N,M) X的M日移动平均,M为权重,如Y=(X*M+Y'*(N-M))/N
- */
- this.SMA=function(data,n,m)
- {
- var result = [];
- if (Array.isArray(n))
- {
- for( var i=0;i<n.length;++i)
- {
- var period=n[i];
- if (!this.IsNumber(period)) continue;
- period=parseInt(period);
- if (period<=0) continue;
- if (period>i+1) period=i+1;
-
- var lastSMA=null;
- var sma=null;
- for(var j=0;j<period;++j)
- {
- var index=i-(period-j-1);
- var item=data[index];
- if (!this.IsNumber(item)) continue;
- if (lastSMA==null)
- {
- lastSMA=item;
- sma=item;
- }
- else
- {
- sma=(m*item+(period-m)*lastSMA)/period;
- lastSMA=sma;
- }
- }
- result[i]=sma;
- }
- }
- else
- {
- var i=n;
- var lastData=null;
- for(;i<data.length; ++i)
- {
- if (data[i]==null || isNaN(data[i])) continue;
- lastData=data[i];
- result[i]=lastData; //第一天的数据
- break;
- }
-
- for(++i;i<data.length;++i)
- {
- result[i]=(m*data[i]+(n-m)*lastData)/n;
- lastData=result[i];
- }
- }
- return result;
- }
- /*
- 求动态移动平均.
- 用法: DMA(X,A),求X的动态移动平均.
- 算法: 若Y=DMA(X,A)则 Y=A*X+(1-A)*Y',其中Y'表示上一周期Y值,A必须小于1.
- 例如:DMA(CLOSE,VOL/CAPITAL)表示求以换手率作平滑因子的平均价
- */
- this.DMA=function(data,data2)
- {
- var result = [];
- if (data.length<0 || data.length!=data2.length) return result;
- var index=0;
- for(;index<data.length;++index)
- {
- if (data[index]!=null && !isNaN(data[index]) && data2[index]!=null && !isNaN(data2[index]))
- {
- result[index]=data[index];
- break;
- }
- }
- for(index=index+1;index<data.length;++index)
- {
- if (data[index]==null || data2[index]==null)
- result[index]=null;
- else
- {
- if (data[index]<1)
- result[index]=(data2[index]*data[index])+(1-data2[index])*result[index-1];
- else
- result[index]= data[index];
- }
- }
- return result;
- }
- /*
- 返回加权移动平均
- 用法:WMA(X,N):X的N日加权移动平均.
- 算法:Yn=(1*X1+2*X2+...+n*Xn)/(1+2+...+n)
- */
- this.WMA = function (data, dayCount)
- {
- let result = [];
- if (!data || !data.length) return result;
- if (dayCount < 1) dayCount = 1;
- var i = 0;
- for (i = 0; i < data.length && !this.IsNumber(data[i]); ++i)
- {
- result[i] = null;
- }
- var data = data.slice(0);
- for (var days = 0; i < data.length; ++i, ++days)
- {
- if (days < dayCount - 1)
- {
- result[i] = null;
- continue;
- }
- var preValue = data[i - (dayCount - 1)];
- var sum = 0;
- var count = 0;
- for (var j = dayCount - 1; j >= 0; --j)
- {
- var value = data[i - j];
- if (!this.IsNumber(value))
- {
- value = preValue;
- data[i - j] = value;
- }
- else
- preValue = value;
- count += dayCount - j;
- sum += value * (dayCount - j);
- }
- result[i] = sum / count;
- }
- return result;
- }
- /*
- 返回平滑移动平均
- 用法:MEMA(X,N):X的N日平滑移动平均,如Y=(X+Y'*(N-1))/N
- MEMA(X,N)相当于SMA(X,N,1)
- */
- this.MEMA = function (data, dayCount)
- {
- let result = [];
- if (!data || !data.length) return result;
- var i = 0, j = 0;
- for (j = 0; j < data.length && !this.IsNumber(data[j]); ++j)
- {
- result[j] = null;
- }
- i = j;
- if (dayCount < 1 || i + dayCount >= data.length) return result;
- var sum = 0;
- var data = data.slice(0);
- for (; i < j + dayCount; ++i)
- {
- result[i] = null;
- if (!this.IsNumber(data[i]) && i - 1 >= 0)
- data[i] = data[i - 1];
- sum += data[i];
- }
- result[i - 1] = sum / dayCount;
- for (; i < data.length; ++i)
- {
- if (this.IsNumber(result[i - 1]) && this.IsNumber(data[i]))
- result[i] = (data[i] + result[i - 1] * (dayCount - 1)) / dayCount;
- else if (i - 1 > -1 && this.IsNumber(result[i - 1]))
- result[i] = result[i - 1];
- else
- result[i] = null;
- }
- return result;
- }
- /*
- 加权移动平均
- 返回加权移动平均
- 用法:EXPMA(X,M):X的M日加权移动平均
- EXPMA[i]=buffer[i]*para+(1-para)*EXPMA[i-1] para=2/(1+__para)
- */
- this.EXPMA=function(data,dayCount)
- {
- let result=[];
- if (dayCount>=data.length) return result;
-
- let i=dayCount;
- for(;i<data.length;++i) //获取第1个有效数据
- {
- if (data[i]!=null)
- {
- result[i]=data[i];
- break;
- }
- }
-
- for (i=i+1; i < data.length; ++i)
- {
- if (result[i-1]!=null && data[i]!=null)
- result[i]=(2*data[i]+(dayCount-1)*result[i-1])/(dayCount+1);
- else if (result[i-1]!=null)
- result[i]=result[i-1];
- }
-
- return result;
- }
- //加权平滑平均,MEMA[i]=SMA[i]*para+(1-para)*SMA[i-1] para=2/(1+__para)
- this.EXPMEMA=function(data,dayCount)
- {
- var result=[];
- if (dayCount>=data.length) return result;
- var index=0;
- for(;index<data.length;++index)
- {
- if (data[index] && !isNaN(data[index])) break;
- }
- var sum=0;
- for(var i=0; index<data.length && i<dayCount;++i, ++index)
- {
- if (data[index] && !isNaN(data[index]))
- sum+=data[index];
- else
- sum+=data[index-1];
- }
- result[index-1]=sum/dayCount;
- for(;index<data.length;++index)
- {
- if(result[index-1]!=null && data[index]!=null)
- result[index]=(2*data[index]+(dayCount-1)*result[index-1])/(dayCount+1);
- else if(result[index-1]!=null)
- result[index] = result[index-1];
- }
- return result;
- }
- /*
- 向前累加到指定值到现在的周期数.
- 用法:SUMBARS(X,A):将X向前累加直到大于等于A,返回这个区间的周期数
- 例如:SUMBARS(VOL,CAPITAL)求完全换手到现在的周期数
- */
- this.SUMBARS = function (data, data2)
- {
- var result = [];
- if (!data || !data.length || !data2 || !data2.length) return result;
- var start = 0, i = 0, j = 0;
- for (; start < data.length && !this.IsNumber(data[start]); ++start)
- {
- result[start] = null;
- }
- var total = 0;
- for (i = data.length - 1; i >= start; --i)
- {
- for (j = i, total = 0; j >= start && total < data2[i]; --j)
- total += data[j];
- if (j < start) result[i] = null;
- else result[i] = i - j;
- }
- for (i = start + 1; i < data.length; ++i)
- {
- if (result[i] == null)
- result[i] = result[i - 1];
- }
- return result;
- }
- /*
- 求相反数.
- 用法:REVERSE(X)返回-X.
- 例如:REVERSE(CLOSE)返回-CLOSE
- */
- this.REVERSE = function (data)
- {
- if (this.IsNumber(data))
- {
- return 0-data;
- }
-
- var result = [];
- var i = 0;
- for (; i < data.length && !this.IsNumber(data[i]); ++i)
- {
- result[i] = null;
- }
- for (; i < data.length; ++i)
- {
- if (!this.IsNumber(data[i]))
- result[i] = null;
- else
- result[i] = 0 - data[i];
- }
- return result;
- }
- this.COUNT=function(data,n)
- {
- if (Array.isArray(n))
- {
- var start=null;
- var dataCount=data.length;
- for(var i=0;i<dataCount;++i)
- {
- if (this.IsNumber(data[i]))
- {
- start=i;
- break;
- }
- }
- if (start==null) return [];
- var result=[];
- var count=0;
- for(var i=0;i<n.length;++i)
- {
- var period=n[i];
- if (period==0)
- {
- result[i]=0;
- continue;
- }
- if (!IFrameSplitOperator.IsNumber(period) ) period=i+1; //无效周期 第一个有效值开始.
- else if (period<0) period=i+1;
-
- count=0;
- for(var j=i, k=0 ;j>=0 && k<period ;--j,++k) //当前往前period天 统计
- {
- if (data[j]) ++count;
- }
- result[i]=count;
- }
- return result;
- }
- else
- {
- var period=n;
- var dataCount=data.length;
- var period=period<1?dataCount:period;
-
- var i=0,j=0;
- for(;i<dataCount;++i) // 取第1个有效数据
- {
- if (this.IsNumber(data[i])) break;
- }
-
- var result=[];
- var days=0;
- for(;i<dataCount && j<period; ++i,++j)
- {
- days=data[i]?days+1:days;
- result[i]=days;
- }
-
- for(;i<dataCount;++i)
- {
- if (data[i-period] && days) days--;
-
- days=data[i] ? days+1 : days;
- result[i]=days;
- }
-
- return result;
- }
- }
- /*
- HHV 最高值
- 求最高值。
- 用法: HHV(X,N) 求N周期内X最高值,N=0则从第一个有效值开始。
- 例如: HHV(HIGH,30) 表示求30日最高价。
- */
- this.HHV=function(data,n)
- {
- let result = [];
- if (Array.isArray(n))
- {
- var max = null;
- for (var i = 0, j = 0; i < data.length; ++i)
- {
- result[i] = null;
- if (i >= n.length) continue;
- max = null;
- var count = n[i];
- if (count > 0 && count <= i)
- {
- for (j = i - count; j <= i; ++j)
- {
- if (max == null || max < data[j]) max = data[j];
- }
- }
- else
- {
- count = i;
- for (j = 0; j <= i; ++j)
- {
- if (max == null || max < data[j]) max = data[j];
- }
- }
- result[i] = max;
- }
- }
- else
- {
- if (!IFrameSplitOperator.IsNonEmptyArray(data)) return result;
- n=parseInt(n);
- if (n<=0) n=data.length;
- else if (n>data.length) n=data.length;
- var nStart=this.GetFirstVaildIndex(data);
- if (nStart>=data.length) return result;
- var nMax = nStart;
- if (nMax < data.length) result[nMax] = data[nMax];
- for (var i = nMax + 1, j = 2; i < data.length && j < n; ++i, ++j)
- {
- if (data[i] >= data[nMax]) nMax = i;
- result[i] = data[nMax];
- }
- for (; i < data.length; ++i)
- {
- if (i - nMax < n)
- {
- nMax = data[i] < data[nMax] ? nMax : i;
- }
- else
- {
- for (j = nMax = (i - n + 1); j <= i; ++j)
- {
- nMax = data[j] < data[nMax] ? nMax : j;
- }
- }
- result[i] = data[nMax];
- }
- }
- return result;
- }
- /*
- HV(X,N):求X在N个周期内(不包含当前k线)的最高值。
- 注:
- 1、若N为0则从第一个有效值开始算起(不包含当前K线);
- 2、当N为有效值,但当前的k线数不足N根,按照实际的根数计算,第一根k线返回空值;
- 3、N为空值时,返回空值。
- 4、N可以是变量。
- 例1:
- HH:HV(H,10);//求前10根k线的最高点。
- 例2:
- N:=BARSLAST(DATE<>REF(DATE,1))+1;
- ZH:VALUEWHEN(DATE<>REF(DATE,1),HV(H,N));//在分钟周期上,求昨天最高价。
- 例3:
- HV(H,5) 和 REF(HHV(H,5),1) 的结果是一样的,用HV编写更加方便。
- */
- this.HV=function(data,n)
- {
- var result=this.HHV(data,n);
- return this.REF(result,1);
- }
- /*
- LLV 最低值
- 求最低值。
- 用法: LLV(X,N) 求N周期内X最低值,N=0则从第一个有效值开始。
- 例如: LLV(LOW,0) 表示求历史最低价。
- */
- this.LLV=function(data,n)
- {
- var result = [];
- if (Array.isArray(n))
- {
- for (var i = 0; i < data.length; ++i)
- {
- result[i] = null;
- if (i >= n.length) continue;
- var min = null;
- var count = n[i];
- if (count > 0 && count <= i)
- {
- for (var j = i - count; j <= i; ++j)
- {
- if (min == null || min > data[j]) min = data[j];
- }
- }
- else
- {
- count = i;
- for (var j = 0; j <= i; ++j)
- {
- if (min == null || min > data[j]) min = data[j];
- }
- }
- result[i] = min;
- }
- }
- else
- {
- if (!IFrameSplitOperator.IsNonEmptyArray(data)) return result;
- n=parseInt(n);
- if (n<=0) n=data.length;
- else if (n>data.length) n=data.length;
- var nStart=this.GetFirstVaildIndex(data);
- if (nStart>=data.length) return result;
- var nMin=nStart;
- if (nMin<data.length) result[nMin]=data[nMin];
- for(var i=nMin+1,j=2;i<data.length && j<n;++i,++j)
- {
- if (data[i]<=data[nMin]) nMin=i;
- result[i]=data[nMin];
- }
- for(;i<data.length;++i)
- {
- if (i-nMin<n)
- {
- nMin=data[i]>data[nMin]?nMin:i;
- }
- else
- {
- for(j=nMin=(i-n+1);j<=i;++j)
- {
- nMin=data[j]>data[nMin]?nMin:j;
- }
- }
- result[i]=data[nMin];
- }
- }
- return result;
- }
- /*
- LV(X,N) 求X在N个周期内的最小值(不包含当前k线)
- 注:
- 1、若N为0则从第一个有效值开始算起;
- 2、当N为有效值,但当前的k线数不足N根,按照实际的根数计算;
- 3、N为空值时,返回空值。
- 4、N可以是变量。
- 例1:
- LL:LV(L,10);//求前面10根k线的最低点。(不包含当前k线)
- 例2:
- N:=BARSLAST(DATE<>REF(DATE,1))+1;//分钟周期,日内k线根数
- ZL:VALUEWHEN(DATE<>REF(DATE,1),LV(L,N));//在分钟周期上,求昨天最低价。
- 例3:
- LV(L,5) 和 REF(LLV(L,5),1) 的结果是一样的,用LV编写更加方便。
- */
- this.LV=function(data,n)
- {
- var result=this.LLV(data,n);
- return this.REF(result,1);
- }
- this.STD=function(data,n)
- {
- var result=[];
- var nStart=this.GetFirstVaildIndex(data);
- if (!IFrameSplitOperator.IsNumber(n)) return result;
- if(nStart+n>data.length || n<1) return result;
- var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
- for(i+=n-1;i<data.length;++i)
- {
- dTotal = 0;
- if(bFirst)
- {
- bFirst = false;
- for(j=i-n+1;j<=i;++j)
- {
- dAvg += data[j];
- }
-
- dAvg /= n;
- }
- else
- {
- dAvg += (data[i]-data[i-n])/n;
- }
- for(j=i-n+1;j<=i;++j)
- {
- dTotal += (data[j]-dAvg)*(data[j]-dAvg);
- }
-
- result[i] = Math.sqrt(dTotal/(n-1));
- }
- return result;
- }
- //STDDEV(X,N) 返回标准偏差
- //将标准差除以样本大小N的平方根即可得出标准误差。标准误差 = σ/sqrt(n)
- this.STDDEV=function(data,n)
- {
- var result=[];
-
- if (!Array.isArray(data)) return result;
- var nStart=this.GetFirstVaildIndex(data);
- if (!IFrameSplitOperator.IsNumber(n)) return result;
- if(nStart+n>data.length || n<1) return result;
- var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
- for(i+=n-1;i<data.length;++i)
- {
- dTotal = 0;
- if(bFirst)
- {
- bFirst = false;
- for(j=i-n+1;j<=i;++j)
- {
- dAvg += data[j];
- }
-
- dAvg /= n;
- }
- else
- {
- dAvg += (data[i]-data[i-n])/n;
- }
- for(j=i-n+1;j<=i;++j)
- {
- dTotal += (data[j]-dAvg)*(data[j]-dAvg);
- }
-
- result[i] = Math.sqrt(dTotal/(n-1))/Math.sqrt(n);
- }
- return result;
- }
- //平均绝对方差
- this.AVEDEV=function(data,n)
- {
- var result=[];
- var total=0;
- var averageData=[]; //平均值
- for(var i=n-1;i<data.length;++i)
- {
- total=0;
- for(var j=0;j<n;++j)
- {
- total+=data[i-j];
- }
- averageData[i]=total/n;
- }
- for(var i=n-1;i<data.length;++i)
- {
- total=0;
- for(var j=0;j<n;++j)
- {
- total+=Math.abs(data[i-j]-averageData[i]);
- }
- result[i]=total/n;
- }
- return result;
- }
- //上穿
- this.CROSS=function(data,data2)
- {
- var result = [];
- if (Array.isArray(data) && Array.isArray(data2))
- {
- if (data.length != data2.length) return result = [];
- var index = 0;
- for (; index < data.length; ++index)
- {
- if (this.IsNumber(data[index]) && this.IsNumber(data2[index]))
- break;
- }
- for (++index; index < data.length; ++index)
- {
- result[index] = (data[index] > data2[index] && data[index - 1] < data2[index - 1]) ? 1 : 0;
- }
- }
- else if (Array.isArray(data) && typeof (data2) == 'number')
- {
- var index = 0;
- for (; index < data.length; ++index)
- {
- if (this.IsNumber(data[index])) break;
- }
- for (++index; index < data.length; ++index)
- {
- result[index] = (data[index] > data2 && data[index - 1] < data2) ? 1 : 0;
- }
- }
- else if (typeof (data) == 'number' && Array.isArray(data2))
- {
- var index = 0;
- for (; index < data2.length; ++index)
- {
- if (this.IsNumber(data2[index])) break;
- }
- for (++index; index < data2.length; ++index)
- {
- result[index] = (data2[index] < data && data2[index - 1] > data) ? 1 : 0;
- }
- }
- return result;
- }
- /*
- CROSSDOWN(A,B):表示当A从上方向下穿B,成立返回1(Yes),否则返回0(No)
- 注:1、CROSSDOWN(A,B)等同于CROSS(B,A),CROSSDOWN(A,B)编写更利于理解
- 例1:
- MA5:=MA(C,5);
- MA10:=MA(C,10);
- CROSSDOWN(MA5,MA10)//MA5下穿MA10
- */
- this.CROSSDOWN=function(data,data2)
- {
- return this.CROSS(data2,data);
- }
- //累乘
- this.MULAR=function(data,n)
- {
- var result=[];
- if(data.length<n) return result;
- var index=n;
- for(;index<data.length;++index)
- {
- if (data[index]!=null && !isNaN(data[index]))
- {
- result[index]=data[index];
- break;
- }
- }
- for(++index;index<data.length;++index)
- {
- result[index]=result[index-1]*data[index];
- }
- return result;
- }
- this.SUM=function(data,n)
- {
- var result=[];
- if (!Array.isArray(n))
- {
- if (n==0)
- {
- var start=-1;
- for(var i=0; i<data.length; ++i) //取第1个有效数
- {
- if (IFrameSplitOperator.IsNumber(data[i]))
- {
- start=i;
- break;
- }
- }
- if (start<0) return result;
- result[start]=data[start];
-
- for (var i=start+1; i<data.length; ++i)
- {
- result[i] = result[i-1]+data[i];
- }
- }
- else
- {
- result[0]=data[0];
- for(var i=1;i<n && i<data.length;++i) //前面小于N周期的累加
- {
- result[i] = result[i-1]+data[i];
- }
- for(var i=n-1,j=0;i<data.length;++i,++j)
- {
- for(var k=0;k<n;++k)
- {
- if (k==0) result[i]=data[k+j];
- else result[i]+=data[k+j];
- }
- }
- }
- }
- else
- {
- for(var i=0;i<data.length;++i)
- {
- result[i]=null;
- var totalCount=n[i];
- if (!(totalCount>0)) continue;
- for(var j=i, k=0 ;j>=0 && k<totalCount ;--j,++k)
- {
- if (k==0) result[i]=data[j];
- else result[i]+=data[j];
- }
- }
- }
-
- return result;
- }
- /*
- BARSCOUNT 有效数据周期数
- 求总的周期数。
- 用法: BARSCOUNT(X) 第一个有效数据到当前的天数。
- 例如: BARSCOUNT(CLOSE) 对于日线数据取得上市以来总交易日数,对于分笔成交取得当日成交笔数,对于1分钟线取得当日交易分钟数。
- */
- this.BARSCOUNT=function(data)
- {
- let result=[];
- let days=null;
- for(let i in data)
- {
- result[i]=0;
- if (days==null)
- {
- if (!this.IsNumber(data[i])) contnue;
- days=0;
- }
-
- result[i]=days;
- ++days;
- }
- return result;
- }
- //DEVSQ 数据偏差平方和
- //DEVSQ(X,N) 返回数据偏差平方和。
- this.DEVSQ=function(data,n)
- {
- if (this.IsNumber(data) && this.IsNumber(n))
- return 0;
- var result=[];
- if (Array.isArray(data))
- {
- var num = null;
- if (Array.isArray(n)) //取最后一个有效数
- {
- for(var i=n.length-1;i>=0;--i)
- {
- if (this.IsNumber(n[i]))
- {
- num = parseInt(n[i]);
- break;
- }
- }
- }
- else
- {
- num = parseInt(n);
- }
- if (!this.IsNumber(num)) return result;
-
- var datanum = data.length;
- var i = 0, j = 0, k = 0;
- var E = 0, DEV = 0;
- for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
- {
- result[i] = null;
- }
- if (num < 1 || i+num>datanum) return result;
- for(E=0; i < datanum && j < num; ++i,++j)
- E += data[i]/num;
- if (j == num)
- {
- DEV = 0;
- for(i--; k < num; k++)
- DEV += (data[i-k]-E) * (data[i-k]-E);
- result[i] = DEV;
- i++;
- }
- for(; i < datanum; ++i)
- {
- E += (data[i] - data[i-num]) / num;
- for(DEV=0, k = 0; k < num; ++k)
- DEV += (data[i-k]-E) * (data[i-k]-E);
- result[i] = DEV;
- }
- }
-
- return result;
- }
- //NOT 取反
- //求逻辑非。
- //用法: NOT(X) 返回非X,即当X=0时返回1,否则返回0。
- //例如: NOT(ISUP) 表示平盘或收阴。
- this.NOT=function(data)
- {
- let isNumber=typeof(data)=='number';
- if (isNumber) return data? 0:1;
- let result=[];
- for(let i in data)
- {
- result[i]=null;
- if (this.IsNumber(data[i])) result[i]=data[i]?0:1;
- }
- return result;
- }
- //FORCAST 线性回归预测值
- //FORCAST(X,N) 返回线性回归预测值。
- this.FORCAST=function(data,n)
- {
- var result=[];
- if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
- var num = n;
- var datanum = data.length;
- if (num < 1 || num >= datanum)
- return result;
- var Ex = 0, Ey = 0, Sxy = 0, Sxx = 0, Const, Slope;
- var i, j,x;
- for(j = 0; j < datanum && !this.IsNumber(data[j]); ++j)
- {
- result[j] = null;
- }
- for(i = j+num-1; i < datanum; ++i)
- {
- Ex = Ey = Sxy = Sxx = 0;
- for (j = 0, x = num; j < num && j <= i; ++j,--x)
- {
- Ex +=x;
- Ey += data[i - j];
- }
- Ex /= num;
- Ey /= num;
- for (j = 0, x = num; j < num && j <= i; ++j, --x)
- {
- Sxy += (x-Ex)*(data[i-j]-Ey);
- Sxx += (x-Ex)*(x-Ex);
- }
- Slope = Sxy / Sxx;
- Const = Ey - Ex*Slope;
- result[i] = Slope * num + Const;
- }
- return result;
- }
- //SLOPE 线性回归斜率
- //SLOPE(X,N) 返回线性回归斜率。
- this.SLOPE=function(data,n)
- {
- let result=[];
- if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
- if (n<1 || !data.length) return result;
- if (n>=data.length) return result;
- let start=0;
- for(let i=0;i<data.length;++i,++start)
- {
- result[i]=null;
- if (this.IsNumber(data[i])) break;
- }
- let x,y,xy,xx;
- for(let i=start+n-1;i<data.length;++i)
- {
- result[i]=null;
- x=y=xy=xx=0;
- for(var j=0;j<n && j<=i; ++j)
- {
- x+=(i-j); //数据索引相加
- y+=data[i-j]; //数据相加
- }
- x=x/n; y=y/n;
- for(j=0;j<n && j<=i; ++j)
- {
- xy+=(i-j-x)*(data[i-j]-y);
- xx+=(i-j-x)*(i-j-x);
- }
- if (xx) result[i]= xy/xx;
- else if (i) result[i]=result[i-1];
- }
- return result;
- }
- //STDP 总体标准差
- //STDP(X,N) 返回总体标准差。
- this.STDP=function(data,n)
- {
- var result=[];
- var nStart=this.GetFirstVaildIndex(data);
- if (!IFrameSplitOperator.IsNumber(n)) return result;
- if(nStart+n>data.length || n<1) return result;
- var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
- for(i+=n-1;i<data.length;++i)
- {
- dTotal = 0;
- if(bFirst)
- {
- bFirst = false;
- for(j=i-n+1;j<=i;++j)
- {
- dAvg += data[j];
- }
-
- dAvg /= n;
- }
- else
- {
- dAvg += (data[i]-data[i-n])/n;
- }
- for(j=i-n+1;j<=i;++j)
- {
- dTotal += (data[j]-dAvg)*(data[j]-dAvg);
- }
- result[i] = Math.sqrt(dTotal/n);
- }
- return result;
- }
- //VAR 估算样本方差
- //VAR(X,N) 返回估算样本方差。
- this.VAR=function(data,n)
- {
- if (this.IsNumber(data) && this.IsNumber(n)) return 0;
- var result=[];
- if (Array.isArray(data) && this.IsNumber(n))
- {
- var num = parseInt(n);
- var datanum = data.length;
- if (num <= 0 || num >= datanum) return result;
- var i, j;
- for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
- {
- result[i] = null;
- }
- var SigmaPowerX, SigmaX;
- for (j = 0, i = i+num-1; i < datanum; ++i)
- {
- SigmaPowerX = SigmaX = 0;
- for(j=0; j < num && j <= i; ++j)
- {
- SigmaPowerX += data[i-j] * data[i-j];
- SigmaX += data[i-j];
- }
- result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1);
- }
- }
- else if (Array.isArray(data) && Array.isArray(n))
- {
- var start=this.GetFirstVaildIndex(data);
- for(var i=start; i<data.length; ++i)
- {
- var SigmaPowerX = SigmaX = 0;
- if (!this.IsNumber(n[i])) continue;
- var num=parseInt(n[i]);
- if (num <= 0 || i-(num-1)<0) continue;
- for (var j = 0; j<num; ++j)
- {
- SigmaPowerX += data[i-j] * data[i-j];
- SigmaX += data[i-j];
- }
- result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1);
- }
- }
- return result;
- }
- //VARP 总体样本方差
- //VARP(X,N) 返回总体样本方差 。
- this.VARP=function(data,n)
- {
- var result=[];
- if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
- var num = n;
- var datanum = data.length;
- if (num < 1 || num >= datanum)
- return result;
- var i = 0, j = 0;
- for (i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
- {
- result[i] = null;
- }
- var SigmaPowerX = 0, SigmaX = 0;
- for (; i < datanum && j < num; ++i, ++j)
- {
- SigmaPowerX += data[i] * data[i];
- SigmaX += data[i];
- }
- if (j == num)
- result[i-1] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num);
- for(; i < datanum; ++i)
- {
- SigmaPowerX += data[i]*data[i] - data[i-num]*data[i-num];
- SigmaX += data[i] - data[i-num];
- result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num);
- }
- return result;
- }
- //RANGE(A,B,C)表示A>B AND A<C;
- this.RANGE=function(data,range,range2)
- {
- let isNumber=typeof(data)=='number';
- let isNumber2=typeof(range)=='number';
- let isNumber3=typeof(range2)=='number';
- if (isNumber && isNumber2 && isNumber3)
- {
- if (data>Math.min(range,range2) && data<Math.max(range,range2)) return 1;
- else return 0;
- }
- let result=[];
- let value, rangeValue,rangValue2;
- for(let i=0; i<data.length; ++i)
- {
- result[i]=null;
- value=data[i];
- if (!this.IsNumber(value)) continue;
- if (!isNumber2)
- {
- if (i>=range.length) continue;
- rangeValue=range[i];
- }
- else
- {
- rangeValue=range;
- }
- if (!this.IsNumber(rangeValue)) continue;
- if (!isNumber3)
- {
- if (i>=range2.length) continue;
- rangeValue2=range2[i];
- }
- else
- {
- rangeValue2=range2;
- }
- if (!this.IsNumber(rangeValue2)) continue;
- result[i]= (value>Math.min(rangeValue,rangeValue2) && value<Math.max(rangeValue,rangeValue2)) ? 1:0;
- }
- return result;
- }
- this.EXIST=function(data,n)
- {
- n=parseInt(n);
- if (typeof(data)=='number') return 0;
- var latestID; //最新满足条件的数据索引
- var result=[];
- var value;
- for(let i=0;i<data.length;++i)
- {
- result[i]=null;
- value=data[i];
- if (this.IsNumber(value) && value>0) latestID==i;
- if (i-latestID<n) result[i]=1;
- else result[i]=0;
- }
- return result;
- }
- //用法:BETWEEN(A,B,C)表示A处于B和C之间时返回1,否则返回0
- //例如:BETWEEN(CLOSE,MA(CLOSE,20),MA(CLOSE,10))表示收盘价介于10日均线和20日均线之间
- this.BETWEEN=function(condition, data, data2)
- {
- var result=[];
- var isNumber=typeof(condition)=='number';
- var isNumber2=typeof(data)=='number';
- var isNumber3=typeof(data2)=='number';
- if (isNumber && isNumber2 && isNumber3) //单数值
- {
- return (condition>=data && condition<=data2) ? 1 : 0;
- }
- for(var i in condition)
- {
- result[i]=0;
- var item=condition[i];
- var left=null, right=null;
- if (isNumber2) left=data;
- else if (i<data.length-1) left=data[i];
-
- if (isNumber3) right=data2;
- else if (i<data2.length-1) right=data2[i];
- if (left==null || right==null) continue;
- if (left>right)
- {
- if (item>=right && item<=left)
- result[i]=1;
- }
- else
- {
- if (item<=right && item>=left)
- result[i]=1;
- }
- }
- return result;
- }
- /*
- 过滤连续出现的信号.
- 用法:TFILTER(买入条件,卖出条件,N);过滤掉买入(卖出)信号发出后,下一个反向信号发出前的所有买入(卖出)信号.
- N=1表示仅对买入信号过滤;
- N=2表示仅对卖出信号过滤;
- N=0表示对买入和卖出信号都过滤,返回1,2表示买入或卖出条件成立;
- 同一K线上只能有一个信号;
- 例如:
- ENTERLONG:TFILTER(买入,卖出,1);
- EXITLONG:TFILTER(买入,卖出,2);
- TFILTER(D,K,1) 等价于 D AND COUNT(D, BARSLAST(K)) == 1
- TFILTER(D,K,2) 等价于 K AND COUNT(K, BARSLAST(D)) == 1
- TFILTER(D,K,0) 需要做个判断,如果满足 D AND COUNT(D, BARSLAST(K)) == 1 则返回1,如果满足 K AND COUNT(K, BARSLAST(D)) == 1 则返回2
- */
- this.TFILTER=function(data,data2,n)
- {
- if (!this.IsNumber(n)) return [];
- if (n==1)
- {
- return this.And(data,this.EQ(this.COUNT(data,this.BARSLAST(data2)),1));
- }
- else if (n==2)
- {
- return this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
- }
- else if (n==0)
- {
- var result=this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
- var value=this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
-
- for(var i=0; i<result.length; ++i)
- {
- var item=value[i];
- if (item>0) result[i]=2;
- }
- return result;
- }
-
- return [];
- }
- /*
- 过滤连续出现的信号.
- 用法:FILTER(X,N):X满足条件后,将其后N周期内的数据置为0,N为常量.
- 例如:
- FILTER(CLOSE>OPEN,5)查找阳线,5天内再次出现的阳线不被记录在内
- */
- this.FILTER = function (data, n)
- {
- var result = [];
- for (let i = 0, j = 0; i < data.length; ++i)
- {
- if (data[i])
- {
- result[i] = 1;
- for (j = 0; j < n && j + i + 1 < data.length; ++j)
- {
- result[j + i + 1] = 0;
- }
- i += n;
- }
- else
- {
- result[i] = 0;
- }
- }
- return result;
- }
- //反向过滤连续出现的信号.
- //用法:FILTERX(X,N):X满足条件后,将其前N周期内的数据置为0,N为常量.
- //例如:FILTERX(CLOSE>OPEN,5)查找阳线,前5天内出现过的阳线不被记录在内
- this.FILTERX=function(data, n, node)
- {
- var result=[];
- if (IFrameSplitOperator.IsNumber(n))
- {
- for(var i=data.length-1, j=0; i>=0; --i)
- {
- if (data[i])
- {
- result[i]=1;
- for(j=0;j<n && i-j-1>=0;++j)
- {
- result[i-j-1]=0;
- }
- i-=n;
- }
- else
- {
- result[i]=0;
- }
- }
- }
- else if (Array.isArray(n))
- {
- for(var i=data.length-1, j=0; i>=0; --i)
- {
- if (data[i])
- {
- result[i]=1;
- if (!IFrameSplitOperator.IsNumber(n[i])) continue;
- var period=parseInt(n[i]);
- if (period<=0) continue;
-
- for(j=0;j<period && i-j-1>=0;++j)
- {
- result[i-j-1]=0;
- }
- i-=period;
- }
- else
- {
- result[i]=0;
- }
- }
- }
- return result;
- }
- this.BARSLAST=function(data)
- {
- var result=[];
- if (!data) return result;
- let day=null;
- for(let i=0;i<data.length;++i)
- {
- result[i]=null;
- if (data[i]>0) day=0;
- else if (day!=null) ++day;
- if (day!=null) result[i]=day;
- }
- return result;
- }
- /*
- N周期内第一个条件成立到当前的周期数.
- 用法:
- BARSSINCEN(X,N):N周期内第一次X不为0到现在的天数,N为常量
- 例如:
- BARSSINCEN(HIGH>10,10)表示10个周期内股价超过10元时到当前的周期数
- */
- this.BARSSINCEN = function (data, n)
- {
- var result=[];
- if (this.IsNumber(n) && Array.isArray(data))
- {
- var nPeriod=n;
- if (nPeriod<1) nPeriod=data.length;
- var i=this.GetFirstVaildIndex(data);
- if (i>=data.length) return result;
- var j=0;
- if (i <= nPeriod - 1) j = nPeriod - 1;
- else j = i;
- result[j] = j - i;
- for (; j < data.length; ++j)
- {
- if (this.IsNumber(result[j - 1]))
- {
- if (result[j - 1] + 1 < nPeriod)
- {
- result[j] = result[j - 1] + 1;
- }
- else
- {
- for (var k = j - nPeriod+1; k <= j; ++k)
- {
- if (!(Math.abs(data[k]) < 0.000001))
- {
- result[j] = j - k;
- break;
- }
- }
- }
- }
- else
- {
- if (!(Math.abs(data[j]) < 0.000001))
- result[j] = 0;
- }
- }
- }
- return result;
- }
- /*
- 第一个条件成立到当前的周期数.
- 用法:
- BARSSINCE(X):第一次X不为0到现在的天数
- 例如:
- BARSSINCE(HIGH>10)表示股价超过10元时到当前的周期数
- */
- this.BARSSINCE = function (data)
- {
- var result = [];
- var day = null;
- for (let i = 0; i < data.length; ++i)
- {
- result[i] = null;
- if (day == null)
- {
- if (data[i]) day = 0;
- }
- else
- {
- ++day;
- }
- if (day) result[i] = day;
- }
- return result;
- }
- /*三角函数调用 func 三角函数
- 反正切值. 用法: ATAN(X)返回X的反正切值
- 余弦值. 用法: COS(X)返回X的余弦值
- 正弦值. 用法: SIN(X)返回X的正弦值
- 正切值. 用法: TAN(X)返回X的正切值
- 求自然对数. 用法: LN(X)以e为底的对数 例如: LN(CLOSE)求收盘价的对数
- 求10为底的对数. 用法: LOG(X)取得X的对数 例如: LOG(100)等于2
- 指数. 用法: EXP(X)为e的X次幂 例如: EXP(CLOSE)返回e的CLOSE次幂
- 开平方. 用法: SQRT(X)为X的平方根 例如: SQRT(CLOSE)收盘价的平方根
- */
- this.Trigonometric = function (data, func)
- {
- if (!Array.isArray(data))
- {
- if (this.IsNumber(data)) return func(data);
- return null;
- }
- else
- {
- var result = [];
- for (let i in data)
- {
- var item = data[i];
- if (this.IsNumber(item)) result[i] = func(item);
- else result[i] = null;
- }
- return result;
- }
- }
- //反正弦值. 用法: ASIN(X)返回X的反正弦值
- this.ASIN = function (data)
- {
- if (!Array.isArray(data))
- {
- if (this.IsNumber(data)) return Math.acos(data);
- return null;
- }
- else
- {
- var result = [];
- for (let i in data)
- {
- var item = data[i];
- result[i] = null;
- if (this.IsNumber(item))
- {
- if (item >= -1 && item <= 1)
- {
- result[i] = Math.asin(item);
- }
- else if (i - 1 >= 0)
- {
- var preItem = result[i - 1];
- if (this.IsNumber(preItem)) result[i] = preItem;
- }
- }
- }
- return result;
- }
- }
- //反余弦值. 用法: ACOS(X)返回X的反余弦值
- this.ACOS = function (data)
- {
- if (!Array.isArray(data))
- {
- if (this.IsNumber(data)) return Math.acos(data);
- return null;
- }
- else
- {
- var result = [];
- for (let i in data)
- {
- var item = data[i];
- result[i] = null;
- if (this.IsNumber(item))
- {
- if (item >= -1 && item <= 1)
- {
- result[i] = Math.acos(item);
- }
- else if (i - 1 >= 0) //超出范围使用上一个数值
- {
- var preItem = result[i - 1];
- if (this.IsNumber(preItem)) result[i] = preItem;
- }
- }
- }
- return result;
- }
- }
- /*
- LAST(X,A,B):持续存在.
- 用法:
- LAST(CLOSE>OPEN,10,5)
- 表示从前10日到前5日内一直阳线
- 若A为0,表示从第一天开始,B为0,表示到最后日止
- */
- this.LAST = function (data, n, n2)
- {
- var result = [];
- if (n2 <= 0) n2 = data.length - 1;
- if (n2 > n) return result;
- var day = 0;
- for (let i = 0, j = 0; i < data.length; ++i) {
- result[i] = 0;
- day = 0;
- var start = i - n;
- var end = i - n2;
- if (start < 0 || end < 0) continue;
- for (j = start; j < data.length && j <= end; ++j, ++day) {
- if (!data[j]) break;
- }
- if (day == end - start + 1) //[start,end]
- result[i] = 1;
- }
- return result;
- }
- /*
- 属于未来函数,之字转向.
- 用法: ZIG(K,N),当价格变化量超过N%时转向,K表示0:开盘价,1:最高价,2:最低价,3:收盘价,其余:数组信息
- 例如: ZIG(3,5)表示收盘价的5%的ZIG转向
- */
- this.ZIG=function(data,n)
- {
- var hisData=this.SymbolData.Data;
- var result=[];
- if (typeof(data)=='number')
- {
- switch(data)
- {
- case 0:
- data=hisData.GetOpen();
- break;
- case 1:
- data=hisData.GetHigh();
- break;
- case 2:
- data=hisData.GetLow();
- break;
- case 3:
- data=hisData.GetClose();
- break;
- default:
- return result;
- }
- }
- return this.ZIG_Calculate(data,n);
- }
- this.ZIG_Calculate=function(data,dRate)
- {
- var dest=[];
- var nDataCount=data.length;
- var m=this.GetFirstVaildIndex(data);
- var i = 0, lLastPos = 0, lState = 0, j = 0;
- var dif = 0;
- for (i = m + 1, lLastPos = lState = m; i<nDataCount - 1 && lState == m; ++i)
- {
- lState = Math.abs(data[i] - data[m]) * 100 >= dRate*data[m] ? (data[i]>data[m] ? i : -i) : m;
- }
- for (; i<nDataCount - 1; ++i)
- {
- if (data[i] >= data[i - 1] && data[i] >= data[i + 1])
- {
- if (lState<0)
- {
- if ((data[i] - data[-lState]) * 100<dRate*data[-lState]) continue;
- else
- {
- dif = (data[lLastPos] - data[j = -lState]) / (-lState - lLastPos);
- dest[j--]=data[-lState];
- for (; j >= lLastPos; j--)
- dest[j]=data[-lState] + (-lState - j)*dif;
- lLastPos = -lState;
- lState = i;
- }
- }
- else if (data[i]>data[lState]) lState = i;
- }
- else if (data[i] <= data[i - 1] && data[i] <= data[i + 1])
- {
- if (lState>0)
- {
- if ((data[lState] - data[i]) * 100<dRate*data[lState]) continue;
- else
- {
- dif = (data[lState] - data[j = lLastPos]) / (lState - lLastPos);
- dest[j++]=data[lLastPos];
- for (; j <= lState; ++j)
- dest[j]=data[lLastPos] + (j - lLastPos)*dif;
- lLastPos = lState;
- lState = -i;
- }
- }
- else if (data[i]<data[-lState]) lState = -i;
- }
- }
- if (Math.abs(lState) >= nDataCount - 2)
- {
- if (lState>0 && data[nDataCount - 1] >= data[lState]) lState = nDataCount - 1;
- if (lState<0 && data[nDataCount - 1] <= data[-lState]) lState = 1 - nDataCount;
- }
- if (lState>0)
- {
- dif = (data[lState] - data[j = lLastPos]) / (lState - lLastPos );
- dest[j++]=data[lLastPos];
- for (; j <= lState; ++j)
- dest[j]=data[lLastPos] + (j - lLastPos)*dif;
- }
- else
- {
- dif = (data[lLastPos] - data[j = -lState]) / (-lState - lLastPos);
- dest[j--]=data[-lState];
- for (; j >= lLastPos; j--)
- dest[j]=(data[-lState] + (-lState - j)*dif);
- }
- if ((lState = Math.abs(lState))<nDataCount - 1)
- {
- if (data[nDataCount - 1] >= data[lState])
- {
- dif = (data[nDataCount - 1] - data[j = lState]) / (nDataCount - lState);
- dest[j++]=(data[lState]);
- for (; j<nDataCount; ++j)
- dest[j]=(data[lState] + (j - lState)*dif);
- }
- else
- {
- dif = (data[lState] - data[j = nDataCount - 1]) / (nDataCount - lState);
- dest[j--]=(data[nDataCount - 1]);
- for (; j >= lState; j--)
- dest[j]=(data[nDataCount - 1] + (nDataCount - j)*dif);
- }
- }
- return dest;
- }
- this.GetFirstVaildIndex=function(data)
- {
- for (var i = 0; i <data.length; ++i)
- {
- if (this.IsNumber(data[i]))
- return i;
- }
- return data.length;
- }
- this.JSDraw = null;
- this.CalculateZIGLine = function (firstData, secondData, thridData, data, result)
- {
- if (this.JSDraw == null) this.JSDraw = new JSDraw(this.ErrorHandler);
- var isUp = secondData.Up;
- var findData = firstData;
- if (isUp)
- {
- for (var i = firstData.ID + 1; i < thridData.ID; ++i) //查找最高点
- {
- var subItem = data[i];
- if (!this.IsNumber(subItem)) continue;
- if (findData.Value < subItem) findData = { ID: i, Value: subItem };
- }
- }
- else
- {
- for (var i = firstData.ID + 1; i < thridData.ID; ++i) //查找最低点
- {
- var subItem = data[i];
- if (!this.IsNumber(subItem)) continue;
- if (findData.Value > subItem) findData = { ID: i, Value: subItem };
- }
- }
- secondData.Value = findData.Value;
- secondData.ID = findData.ID;
- var lineCache = { Start: { ID: firstData.ID, Value: firstData.Value }, End: { ID: secondData.ID, Value: secondData.Value } };
- var lineData = this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值
- for (var i in lineData)
- {
- var lineItem = lineData[i];
- result[lineItem.ID] = lineItem.Value;
- }
- if (thridData.ID == data.length - 1) //最后一组数据
- {
- //最后2个点的数据连成线
- lineCache = { Start: { ID: secondData.ID, Value: secondData.Value }, End: { ID: thridData.ID, Value: thridData.Value } };
- lineData = this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值
- for (var i in lineData)
- {
- var lineItem = lineData[i];
- result[lineItem.ID] = lineItem.Value;
- }
- }
- else
- {
- firstData.ID = secondData.ID;
- firstData.Value = secondData.Value;
- secondData.ID = thridData.ID;
- secondData.Value = thridData.Value;
- secondData.Up = firstData.Value < secondData.Value;
- }
- }
- /*
- 属于未来函数,前M个ZIG转向波谷到当前距离.
- 用法:
- TROUGHBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波谷到当前的周期数,M必须大于等于1
- 例如:
- TROUGHBARS(2,5,2)表示%5最低价ZIG转向的前2个波谷到当前的周期数
- */
- this.TROUGHBARS=function(data,n,n2)
- {
- var zigData=this.ZIG(data,n); //计算ZIG
- var dest=[];
- var lEnd =n2;
- if (lEnd<1) return dest;
- var nDataCount = zigData.length;
- var trough = [];
- for(var i=0;i<lEnd;++i) trough[i]=0;
- var lFlag = 0;
- var i = this.GetFirstVaildIndex(zigData) + 1;
- for (lEnd--; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
- for (; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
- for (trough[0] = --i; i<nDataCount - 1; ++i)
- {
- if (zigData[i]<zigData[i + 1])
- {
- if (lFlag)
- {
- if (lEnd)
- {
- var tempTrough=trough.slice(0);
- for(var j=0;j<lEnd;++j)
- {
- trough[j+1]=tempTrough[j];
- }
- }
- trough[lFlag = 0] = i;
- }
- }
- else lFlag = 1;
- if (trough[lEnd]) dest[i]=(i - trough[lEnd]);
- }
- if (trough[lEnd]) dest[i]=(i - trough[lEnd]);
- return dest;
- }
- this.TROUGH=function(data,n,n2)
- {
- var zigData=this.ZIG(data,n); //计算ZIG
- var dest=[];
- var End=n2;
- if(End<1) return dest;
- var nDataCount = zigData.length;
- var trough=[];
- for(var i=0;i<End;++i) trough[i]=0;
- var i=1,Flag=0;
- var i = this.GetFirstVaildIndex(zigData) + 1;
- for(End--; i<nDataCount && zigData[i]>zigData[i-1]; ++i);
- for(; i<nDataCount && zigData[i]<zigData[i-1]; ++i);
- for(trough[0]=--i;i<nDataCount-1;++i)
- {
- if(zigData[i]<zigData[i+1])
- {
- if(Flag)
- {
- if(End)
- {
- var tempTrough=trough.slice(0);
- for(var j=0;j<End;++j)
- {
- trough[j+1]=tempTrough[j];
- }
- }
- trough[Flag=0]=i;
- }
- }
- else Flag=1;
- if(trough[End]) dest[i]=zigData[trough[End]];
- }
- if(trough[End]) dest[i]=zigData[trough[End]];
- return dest;
- }
- /*
- 属于未来函数,前M个ZIG转向波峰到当前距离.
- 用法:
- PEAKBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波峰到当前的周期数,M必须大于等于1
- 例如:
- PEAKBARS(0,5,1)表示%5开盘价ZIG转向的上一个波峰到当前的周期数
- */
- this.PEAKBARS=function(data,n,n2)
- {
- var zigData=this.ZIG(data,n); //计算ZIG
- var dest=[];
- var nDataCount = zigData.length;
- var lEnd = n2;
- if (lEnd < 1) return dest;
- var peak = [];
- for(var i=0;i<lEnd;++i) peak[i]=0;
- var lFlag = 0;
-
- var i = this.GetFirstVaildIndex(zigData) + 1;
- for (lEnd--; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
- for (; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
- for (peak[0] = --i; i<nDataCount - 1; ++i)
- {
- if (zigData[i]>zigData[i + 1])
- {
- if (lFlag)
- {
- if (lEnd)
- {
- var tempPeak=peak.slice(0);
- for(var j=0;j<lEnd;++j)
- {
- peak[j+1]=tempPeak[j];
- }
- }
- peak[lFlag = 0] = i;
- }
- }
- else lFlag = 1;
- if (peak[lEnd]) dest[i]=(i - peak[lEnd]);
- }
- if (peak[lEnd])dest[i]=(i - peak[lEnd]);
- return dest;
- }
- this.PEAK=function(data,n,n2)
- {
- var zigData=this.ZIG(data,n); //计算ZIG
- var dest=[];
- var nDataCount = zigData.length;
- var lEnd = n2;
- if (lEnd < 1) return dest;
- var lFlag = 0;
- var peak = [];
- for(var i=0;i<lEnd;++i) peak[i]=0;
-
- var i = this.GetFirstVaildIndex(zigData) + 1;
- for (lEnd--; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
- for (; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
- for (peak[0] = --i; i<nDataCount - 1; ++i)
- {
- if (zigData[i]>zigData[i + 1])
- {
- if (lFlag)
- {
- if (lEnd)
- {
- var tempPeak=peak.slice(0);
- for(var j=0;j<lEnd;++j)
- {
- peak[j+1]=tempPeak[j];
- }
- }
- peak[lFlag = 0] = i;
- }
- }
- else lFlag = 1;
- if (peak[lEnd]) dest[i]=(zigData[peak[lEnd]]);
- }
- if (peak[lEnd]) dest[i]=(zigData[peak[lEnd]]);
-
- return dest;
- }
- /*
- 一直存在.
- 例如:
- EVERY(CLOSE>OPEN,N)
- 表示N日内一直阳线(N应大于0,小于总周期数,N支持变量)
- */
- this.EVERY = function (data, n)
- {
- var result=[];
- if (n<1) return result;
- if (IFrameSplitOperator.IsNumber(n))
- {
- n=parseInt(n);
- var i=0;
- for(;i<data.length;++i)
- {
- result[i]=null;
- if (this.IsNumber(data[i])) break;
- }
- var flag=0;
- for(;i<data.length;++i)
- {
- if (data[i]) flag+=1;
- else flag=0;
-
- if (flag==n)
- {
- result[i]=1;
- --flag;
- }
- else
- {
- result[i]=0;
- }
- }
- }
- else if (Array.isArray(n))
- {
- for(var i=0;i<n.length;++i)
- {
- var value=n[i];
- result[i]=null;
- if (!IFrameSplitOperator.IsPlusNumber(value)) continue;
- value=parseInt(value);
- var flag=0;
- for(var j=i, k=0; j>=0 && k<value; --j, ++k)
- {
- if (data[j]) ++flag;
- }
- result[i]=(flag==value?1:0);
- }
- }
- return result;
- }
- /*
- 成本分布情况.
- 用法:
- COST(10),表示10%获利盘的价格是多少,即有10%的持仓量在该价格以下,其余90%在该价格以上,为套牢盘
- 该函数仅对日线分析周期有效
- */
- this.COST = function (data, node)
- {
- var result=[];
- var rate=data/100;
- if(rate<0.000001 || rate>1) return result;
-
- var kData=this.SymbolData.Data.Data;
- if (!kData || kData.length<=0) return result;
- var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本
- var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low;
- for(var i=0;i<kData.length;++i)
- {
- var item=kData[i];
- dMinPrice = Math.min(dMinPrice,item.Low);
- dMaxPrice = Math.max(dMaxPrice,item.High);
- }
- if (dMinPrice > 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0)
- this.ThrowUnexpectedNode(node,'COST() 历史K线最大最小值错误, 超出(0,5000)范围');
- var lMaxPrice = parseInt(dMaxPrice * 100 + 1);
- var lMinPrice = parseInt(dMinPrice * 100 - 1);
- var lLow = 0, lHigh = 0, lClose = 0;
- //去掉小数
- dMaxPrice = lMaxPrice / 100.0;
- dMinPrice = lMinPrice / 100.0;
- var lSpeed = lMaxPrice - lMinPrice + 1;
- if (lSpeed < 1) return result;
-
- var aryVolPrice=[],aryPerVol=[];
- for(var i=0;i<lSpeed;++i)
- {
- aryVolPrice[i]=0;
- aryPerVol[i]=0;
- }
- var dHSL = 0, dTotalVol = 0, dVol = 0, dCost=0;
- for(var i=0;i<kData.length;++i)
- {
- if (i >= aryCapital.length) continue;
- if (aryCapital[i]>1)
- {
- var kItem=kData[i]
- dHSL = kItem.Vol/aryCapital[i];
- for( var j=0;j<lSpeed;j++)
- aryVolPrice[j]*=(1-dHSL);
- lLow=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Low *100)))-lMinPrice;
- lHigh=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.High*100)))-lMinPrice;
- lClose=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Close*100)))-lMinPrice;
- for(var j=0;j<lSpeed;++j) aryPerVol[j]=0;
- var lHalf =parseInt((lLow + lHigh + 2 * lClose) / 4);
- if (lHalf == lHigh || lHalf == lLow)
- {
- aryPerVol[lHalf] += kItem.Vol;
- }
- else
- {
- var dVH = kItem.Vol / (lHalf - lLow);
- for (var k = lLow; k<lHalf; ++k)
- {
- aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow));
- }
- for (k; k <= lHigh; ++k)
- {
- aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh));
- }
- }
- var dTotalVol = 0;
- for (var j = lLow; j <= lHigh; j++)
- {
- aryVolPrice[j] += aryPerVol[j];
- }
- for (var j = 0; j < lSpeed; j++)
- {
- dTotalVol += aryVolPrice[j];
- }
- for(j=0,dCost=dVol=0;j<lSpeed;++j)
- {
- dVol+=aryVolPrice[j];
- if(dVol>=dTotalVol*rate)
- {
- dCost=(dMaxPrice-dMinPrice)*j/lSpeed+dMinPrice;
- break;
- }
- }
- }
- result[i]=dCost;
- }
- return result;
- }
- /*
- 获利盘比例.
- 用法:
- WINNER(CLOSE),表示以当前收市价卖出的获利盘比例,例如返回0.1表示10%获利盘;WINNER(10.5)表示10.5元价格的获利盘比例
- 该函数仅对日线分析周期有效
- !!!!计算比较耗时间
- */
- this.WINNER = function (data,node)
- {
- var result=[];
- var kData=this.SymbolData.Data.Data;
- if (!kData || kData.length<=0) return result;
- var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本
- var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low;
- for(var i=0;i<kData.length;++i)
- {
- var item=kData[i];
- dMinPrice = Math.min(dMinPrice,item.Low);
- dMaxPrice = Math.max(dMaxPrice,item.High);
- }
- if (dMinPrice > 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0)
- this.ThrowUnexpectedNode(node,'WINNER() 历史K线最大最小值错误, 超出(0,5000)范围');
- var lMaxPrice = parseInt(dMaxPrice * 100 + 1);
- var lMinPrice = parseInt(dMinPrice * 100 - 1);
- var lLow = 0, lHigh = 0, lClose = 0;
- //去掉小数
- dMaxPrice = lMaxPrice / 100.0;
- dMinPrice = lMinPrice / 100.0;
- var lSpeed = lMaxPrice - lMinPrice + 1;
- if (lSpeed < 1) return result;
-
- var aryVolPrice=[],aryPerVol=[];
- for(var i=0;i<lSpeed;++i)
- {
- aryVolPrice[i]=0;
- aryPerVol[i]=0;
- }
- var dHSL = 0, dTotalVol = 0, dVol = 0;
- for(var i=0;i<kData.length;++i)
- {
- if (i >= aryCapital.length) continue;
- if (!(aryCapital[i]>1)) continue;
- var kItem=kData[i]
- dHSL = kItem.Vol/aryCapital[i];
- for( var j=0;j<lSpeed;j++)
- aryVolPrice[j]*=(1-dHSL);
- lLow=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Low *100)))-lMinPrice;
- lHigh=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.High*100)))-lMinPrice;
- lClose=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Close*100)))-lMinPrice;
- for(var j=0;j<lSpeed;++j) aryPerVol[j]=0;
- var lHalf =parseInt((lLow + lHigh + 2 * lClose) / 4);
- if (lHalf == lHigh || lHalf == lLow)
- {
- aryPerVol[lHalf] += kItem.Vol;
- }
- else
- {
- var dVH = kItem.Vol / (lHalf - lLow);
- for (var k = lLow; k<lHalf; ++k)
- {
- aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow));
- }
- for (k; k <= lHigh; ++k)
- {
- aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh));
- }
- }
- var dTotalVol = 0;
- for (var j = lLow; j <= lHigh; j++)
- {
- aryVolPrice[j] += aryPerVol[j];
- }
- for (var j = 0; j < lSpeed; j++)
- {
- dTotalVol += aryVolPrice[j];
- }
- if (Array.isArray(data))
- lHigh = parseInt(Math.min((data[i] * 100) - lMinPrice, lSpeed - 1));
- else
- lHigh = parseInt(Math.min((data * 100) - lMinPrice, lSpeed - 1));
- for (var j = 0, dVol = 0; j <= lHigh; j++)
- {
- dVol += aryVolPrice[j];
- }
- if (dTotalVol > 0) result[i]=dVol / dTotalVol;
- else if (i - 1 >= 0) result[i] = result[i - 1];
- }
-
- return result;
- }
- //计算截至到某一天的历史所有筹码
- this.CalculateChip = function (index, exchangeData, hisData, dRate)
- {
- var result = { Min: null, Max: null, Data: [] };
- var seed = 1;//筹码历史衰减换手系数
- var max = null, min = null;
- for (let i = index; i >= 0; --i)
- {
- let item = {}; //Vol:量 High:最高 Low:最低
- var kData = hisData[i];
- if (i == index) item.Vol = kData.Vol * exchangeData[i];
- else item.Vol = kData.Vol * seed;
- item.Date = kData.Date;
- item.High = kData.High;
- item.Low = kData.Low;
- if (max == null) max = item.High;
- else if (max < item.High) max = item.High;
- if (min == null) min = item.Low;
- else if (min < item.Low) min = item.Low;
- result.Data[i] = item;
- seed *= (1 - (exchangeData[i] / 100) * dRate); //换手率累乘
- }
- result.Max = max;
- result.Min = min;
- return result;
- }
- /*
- 返回是否连涨周期数.
- 用法:
- UPNDAY(CLOSE,M)
- 表示连涨M个周期,M为常量
- */
- this.UPNDAY = function (data, n)
- {
- var result = [];
- if (n < 1) return result;
- if (data == null || n > data.length) return result;
- var days = 0;
- for (let i = 0; i < data.length; ++i)
- {
- result[i] = 0;
- if (i - 1 < 0) continue;
- if (!this.IsNumber(data[i]) || !this.IsNumber(data[i - 1])) //无效数都不算连涨
- {
- days = 0;
- continue;
- }
- if (data[i] > data[i - 1])++days;
- else days = 0;
- if (days == n)
- {
- result[i] = 1;
- --days;
- }
- }
- return result;
- }
- /*
- 返回是否连跌周期.
- 用法:
- DOWNNDAY(CLOSE,M)
- 表示连跌M个周期,M为常量
- */
- this.DOWNNDAY = function (data, n)
- {
- var result = [];
- if (n < 1) return result;
- if (data == null || n > data.length) return result;
- var days = 0;
- for (let i = 0; i < data.length; ++i)
- {
- result[i] = 0;
- if (i - 1 < 0) continue;
- if (!this.IsNumber(data[i]) || !this.IsNumber(data[i - 1])) //无效数都不算连涨
- {
- days = 0;
- continue;
- }
- if (data[i] < data[i - 1])++days;
- else days = 0;
- if (days == n)
- {
- result[i] = 1;
- --days;
- }
- }
- return result;
- }
- /*
- 返回是否持续存在X>Y
- 用法:
- NDAY(CLOSE,OPEN,3)
- 表示连续3日收阳线
- */
- this.NDAY = function (data, data2, n)
- {
- var result = [];
- if (n < 1) return result;
- if (!Array.isArray(data) && !Array.isArray(data2)) return result;
- if (data == null || data2 == null) return result;
- if (Array.isArray(data) && Array.isArray(data2))
- {
- if (n >= data.length || n >= data2.length) return result;
- var count = Math.max(data.length, data2.length);
- var days = 0;
- for (let i = 0; i < count; ++i)
- {
- result[i] = 0;
- if (i >= data.length || i >= data2.length) continue;
- if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]))
- {
- days = 0;
- continue;
- }
- if (data[i] > data2[i])++days;
- else days = 0;
- if (days == n)
- {
- result[i] = 1;
- --days;
- }
- }
- }
- else if (Array.isArray(data) && !Array.isArray(data2))
- {
- if (n >= data.length || !this.IsNumber(data2)) return;
- var days = 0;
- for (let i in data)
- {
- result[i] = 0;
- if (!this.IsNumber(data[i]))
- {
- days = 0;
- continue;
- }
- if (data[i] > data2)++days;
- else days = 0;
- if (days == n)
- {
- result[i] = 1;
- --days;
- }
- }
- }
- else if (!Array.isArray(data) && Array.isArray(data2))
- {
- if (n >= data2.length || !this.IsNumber(data)) return;
- var days = 0;
- for (let i in data2)
- {
- result[i] = 0;
- if (!this.IsNumber(data2[i]))
- {
- days = 0;
- continue;
- }
- if (data > data2[i])++days;
- else days = 0;
- if (days == n)
- {
- result[i] = 1;
- --days;
- }
- }
- }
- return result;
- }
- /*
- 两条线维持一定周期后交叉.
- 用法:LONGCROSS(A,B,N)表示A在N周期内都小于B,本周期从下方向上穿过B时返回1,否则返回0
- */
- this.LONGCROSS = function (data, data2, n)
- {
- var result = [];
- var count = Math.max(data.length, data2.length);
- for (let i = 0; i < count; ++i)
- {
- result[i] = 0;
- if (i - 1 < 0) continue;
- if (i >= data.length || i >= data2.length) continue;
- if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]) || !this.IsNumber(data[i - 1]) || !this.IsNumber(data2[i - 1])) continue;
- if (data[i] > data2[i] && data[i - 1] < data2[i - 1]) result[i] = 1;
- }
- for (let i = 0, j = 0; i < count; ++i)
- {
- if (!result[i]) continue;
- for (j = 1; j <= n && i - j >= 0; ++j)
- {
- if (data[i - j] >= data2[i - j])
- {
- result[i] = 0;
- break;
- }
- }
- }
- return result;
- }
- this.ISVALID=function(data)
- {
- if (Array.isArray(data))
- {
- var result=[];
- for(var i=0;i<data.length;++i)
- {
- var item=data[i];
- if (item) result[i]=1;
- else result[i]=0;
- }
- return result;
- }
- else
- {
- if (data) return 1;
- else return 0;
- }
- }
- /*
- EXISTR(X,A,B):是否存在(前几日到前几日间).
- 例如: EXISTR(CLOSE>OPEN,10,5)
- 表示从前10日内到前5日内存在着阳线
- 若A为0,表示从第一天开始,B为0,表示到最后日止
- */
- this.EXISTR = function (data, n, n2)
- {
- var result = [];
- if (!Array.isArray(data)) return result;
- n = parseInt(n);
- n2 = parseInt(n2);
- if (n <= 0) n = data.length;
- if (n2 <= 0) n2 = 1;
- if (n2 > n) return result;
- var result = [];
- var value;
- for (let i = 0, j = 0; i < data.length; ++i)
- {
- result[i] = null;
- if (i - n < 0 || i - n2 < 0) continue;
- result[i] = 0;
- for (j = n; j >= n2; --j)
- {
- var value = data[i - j];
- if (this.IsNumber(value) && value)
- {
- result[i] = 1;
- break;
- }
- }
- }
- return result;
- }
- /*
- RELATE(X,Y,N) 返回X和Y的N周期的相关系数
- RELATE(X,Y,N)=(∑[(Xi-Avg(X))(Yi-Avg(y))])/N ÷ √((∑(Xi-Avg(X))^2)/N * (∑(Yi-Avg(Y))^2)/N)
- 其中 avg(x)表示x的N周期均值: avg(X) = (∑Xi)/N
- √(...)表示开平方
- */
- this.RELATE = function (data, data2, n)
- {
- var result = [];
- if (n < 1) n = 1;
- if (!Array.isArray(data) || !Array.isArray(data2)) return result;
- var dataAverage = this.CalculateAverage(data, n);
- var data2Average = this.CalculateAverage(data2, n);
- var count = Math.max(data.length, data2.length);
- for (let i = 0, j = 0; i < count; ++i)
- {
- result[i] = null;
- if (i >= data.length || i >= data2.length || i >= dataAverage.length || i >= data2Average.length) continue;
- var average = dataAverage[i];
- var average2 = data2Average[i];
- var total = 0, total2 = 0, total3 = 0;
- for (j = i - n + 1; j <= i; ++j)
- {
- total += (data[j] - average) * (data2[j] - average2); //∑[(Xi-Avg(X))(Yi-Avg(y))])
- total2 += Math.pow(data[j] - average, 2); //∑(Xi-Avg(X))^2
- total3 += Math.pow(data2[j] - average2, 2); //∑(Yi-Avg(Y))^2)
- }
- result[i] = (total / n) / (Math.sqrt(total2 / n) * Math.sqrt(total3 / n));
- }
- return result;
- }
- //计算数组n周期内的均值
- this.CalculateAverage = function (data, n)
- {
- var result = [];
- if (n < 1) return result;
- var total = 0;
- for (var i = 0; i < data.length; ++i) //去掉开始的无效数
- {
- if (this.IsNumber(data[i])) break;
- }
- for (; i < data.length && i < n; ++i) //计算第1个周期的数据
- {
- result[i] = null;
- var value = data[i];
- if (!this.IsNumber(value)) continue;
- total += value;
- }
- result[i - 1] = total / n;
- for (; i < data.length; ++i) //计算后面的周期数据
- {
- var value = data[i];
- var preValue = data[i - n]; //上一个周期的第1个数据
- if (!this.IsNumber(value)) value = 0;
- if (!this.IsNumber(preValue)) preValue = 0;
- total = total - preValue + value; //当前周期的数据 等于上一个周期数据 去掉上一个周期的第1个数据 加上这个周期的最后1个数据
- result[i] = total / n;
- }
- return result;
- }
- /*
- COVAR(X,Y,N) 返回X和Y的N周期的协方差
- */
- this.COVAR = function (data, data2, n)
- {
- if (this.IsNumber(data) || this.IsNumber(data2)) return 0;
- var result = [];
- if (n < 1) n = 1;
- if (!Array.isArray(data) || !Array.isArray(data2)) return result;
- var dataAverage = this.CalculateAverage(data, n);
- var data2Average = this.CalculateAverage(data2, n);
- var count = Math.max(data.length, data2.length);
- var count = Math.max(data.length, data2.length);
- for (let i = 0, j = 0; i < count; ++i)
- {
- result[i] = null;
- if (i >= data.length || i >= data2.length || i >= dataAverage.length || i >= data2Average.length) continue;
- var average = dataAverage[i];
- var average2 = data2Average[i];
- var total = 0;
- for (j = i - n + 1; j <= i; ++j)
- {
- total += (data[j] - average) * (data2[j] - average2);
- }
- result[i] = (total / n);
- }
- return result;
- }
- /*
- 求上一高点到当前的周期数.
- 用法:
- HHVBARS(X,N):求N周期内X最高值到当前周期数,N=0表示从第一个有效值开始统计
- 例如:
- HHVBARS(HIGH,0)求得历史新高到到当前的周期数
- */
- this.HHVBARS = function (data, n)
- {
- var result = [];
- if (!Array.isArray(data)) return result;
- if (Array.isArray(n))
- {
- for(var i=0;i<n.length;++i)
- {
- result[i]=null;
- var period=n[i];
- if (!this.IsNumber(period)) continue;
- var start=i-period;
- if (start<0) start=0;
- var nMax=null;
- var j=start;
- for(; j<data.length;++j)
- {
- if (this.IsNumber(data[j]))
- {
- nMax=j;
- break;
- }
- }
- for(var k=0; j<data.length && k<period;++k, ++j)
- {
- if (data[j]>=data[nMax]) nMax=j;
- }
- if (nMax!=null)
- result[i]=(i-nMax);
- }
- }
- else
- {
- if (n < 1) n = data.length;
- var nMax = null; //最大值索引
- for (var i = 0; i < data.length; ++i)
- {
- result[i] = null;
- if (this.IsNumber(data[i])) {
- nMax = i;
- break;
- }
- }
- var j = 0;
- for (i = nMax + 1; i < data.length && j < n; ++i, ++j) //求第1个最大值
- {
- if (data[i] >= data[nMax]) nMax = i;
- if (n == data.length) result[i] = (i - nMax);
- }
- for (; i < data.length; ++i)
- {
- if (i - nMax < n)
- {
- if (data[i] >= data[nMax]) nMax = i;
- }
- else
- {
- nMax = i - n + 1;
- for (j = nMax; j <= i; ++j) //计算区间最大值
- {
- if (data[j] >= data[nMax]) nMax = j;
- }
- }
- result[i] = i - nMax;
- }
- }
- return result;
- }
- /*
- 求上一低点到当前的周期数.
- 用法: LLVBARS(X,N):求N周期内X最低值到当前周期数,N=0表示从第一个有效值开始统计
- 例如: LLVBARS(HIGH,20)求得20日最低点到当前的周期数
- */
- this.LLVBARS = function (data, n)
- {
- var result = [];
- if (!Array.isArray(data)) return result;
- if (Array.isArray(n))
- {
- for(var i=0;i<n.length;++i)
- {
- result[i]=null;
- var period=n[i];
- if (!this.IsNumber(period)) continue;
- var start=i-period;
- if (start<0) start=0;
- var nMin=null;
- var j=start;
- for(; j<data.length;++j)
- {
- if (this.IsNumber(data[j]))
- {
- nMin=j;
- break;
- }
- }
- for(var k=0; j<data.length && k<period;++k, ++j)
- {
- if (data[j]<=data[nMin]) nMin=j;
- }
- if (nMin!=null)
- result[i]=(i-nMin);
- }
- }
- else
- {
- if (n < 1) n = data.length;
- var nMin = null; //最小值索引
- for (var i = 0; i < data.length; ++i)
- {
- result[i] = null;
- if (this.IsNumber(data[i]))
- {
- nMin = i;
- break;
- }
- }
- var j = 0;
- for (i = nMin + 1; i < data.length && j < n; ++i, ++j) //求第1个最大值
- {
- if (data[i] <= data[nMin]) nMin = i;
- if (n == data.length) result[i] = (i - nMin);
- }
- for (; i < data.length; ++i)
- {
- if (i - nMin < n)
- {
- if (data[i] <= data[nMin]) nMin = i;
- }
- else
- {
- nMin = i - n + 1;
- for (j = nMin; j <= i; ++j) //计算区间最小值
- {
- if (data[j] <= data[nMin]) nMin = j;
- }
- }
- result[i] = i - nMin;
- }
- }
- return result;
- }
- /*
- β(Beta)系数
- BETA(N) 返回当前证券N周期收益与对应大盘指数收益相比的贝塔系数
- 需要下载上证指数历史数据
- 涨幅(X)=(现价-上一个交易日收盘价)/上一个交易日收盘价
- 公式=股票和指数协方差/股票方差
- */
- this.BETA = function (n)
- {
- var result = [];
- var stockData = this.SymbolData.Data;
- var indexData = this.SymbolData.IndexData;
- if (n <= 0) n = 1;
- var stockProfit = []; //股票涨幅
- var indexProfit = []; //指数涨幅
- for (let i = 0; i < stockData.Data.length; ++i)
- {
- stockProfit[i] = 0;
- indexProfit[i] = 0;
- var stockItem = stockData.Data[i];
- var indexItem = indexData.Data[i];
- if (stockItem.Close > 0 && stockItem.YClose > 0) stockProfit[i] = (stockItem.Close - stockItem.YClose) / stockItem.YClose;
- if (indexItem.Close > 0 && indexItem.YClose > 0) indexProfit[i] = (indexItem.Close - indexItem.YClose) / indexItem.YClose;
- }
- //计算均值数组
- var averageStockProfit = this.CalculateAverage(stockProfit, n);
- var averageIndexProfit = this.CalculateAverage(indexProfit, n);
- for (var i = 0, j = 0; i < stockData.Data.length; ++i)
- {
- result[i] = null;
- if (i >= stockProfit.length || i >= indexProfit.length || i >= averageStockProfit.length || i >= averageIndexProfit.length) continue;
- var averageStock = averageStockProfit[i];
- var averageIndex = averageIndexProfit[i];
- var covariance = 0; //协方差
- var variance = 0; //方差
- for (j = i - n + 1; j <= i; ++j)
- {
- var value = (indexProfit[j] - averageIndex);
- var value2 = (stockProfit[j] - averageStock);
- covariance += value * value2;
- variance += value * value;
- }
- if (this.IsDivideNumber(variance) && this.IsNumber(covariance))
- result[i] = covariance / variance; //(covariance/n)/(variance/n)=covariance/variance;
- }
- return result;
- }
- /*
- 用法:BETA2(X,Y,N)为X与Y的N周期相关放大系数,表示Y变化1%,则X将变化N%
- 例如:BETA2(CLOSE,INDEXC,10)表示收盘价与大盘指数之间的10周期相关放大率
- */
- this.BETA2 = function (x, y, n)
- {
- var result = [];
- if (n <= 0) n = 1;
- var xProfit = [null]; //x数据的涨幅
- var yProfit = [null]; //y数据的涨幅
- var count = Math.max(x.length, y.length);
- var lastItem = { X: x[0], Y: y[0] };
- for (var i = 1; i < count; ++i)
- {
- xProfit[i] = 0;
- yProfit[i] = 0;
- var xItem = x[i];
- var yItem = y[i];
- if (lastItem.X > 0) xProfit[i] = (xItem - lastItem.X) / lastItem.X;
- if (lastItem.Y > 0) yProfit[i] = (yItem - lastItem.Y) / lastItem.Y;
- lastItem = { X: xItem, Y: yItem };
- }
- //计算均值数组
- var averageXProfit = this.CalculateAverage(xProfit, n);
- var averageYProfit = this.CalculateAverage(yProfit, n);
- for (var i = 0, j = 0; i < count; ++i)
- {
- result[i] = null;
- if (i >= xProfit.length || i >= yProfit.length || i >= averageXProfit.length || i >= averageYProfit.length) continue;
- var averageX = averageXProfit[i];
- var averageY = averageYProfit[i];
- var covariance = 0; //协方差
- var variance = 0; //方差
- for (j = i - n + 1; j <= i; ++j)
- {
- var value = (xProfit[j] - averageX);
- var value2 = (yProfit[j] - averageY);
- covariance += value * value2;
- variance += value * value;
- }
- if (this.IsDivideNumber(variance) && this.IsNumber(covariance))
- result[i] = covariance / variance; //(covariance/n)/(variance/n)=covariance/variance;
- }
- return result;
- }
- /*
- 抛物转向.
- 用法:
- SAR(N,S,M),N为计算周期,S为步长,M为极值
- 例如:
- SAR(10,2,20)表示计算10日抛物转向,步长为2%,极限值为20%
- */
- this.SAR = function (n, step, exValue)
- {
- var result = [];
- var stockData = this.SymbolData.Data;
- if (n >= stockData.Data.length) return result;
- var high = null, low = null;
- for (var i = 0; i < n; ++i)
- {
- var item = stockData.Data[i];
- if (high == null) high = item.High;
- else if (high < item.High) high = item = high;
- if (low == null) low = item.Low;
- else if (low > item.Low) low = item.Low;
- }
- const SAR_LONG = 0, SAR_SHORT = 1;
- var position = SAR_LONG;
- result[n - 1] = low;
- var nextSar = low, sip = stockData.Data[0].High, af = exValue / 100;
- for (var i = n; i < stockData.Data.length; ++i)
- {
- var ysip = sip;
- var item = stockData.Data[i];
- var yitem = stockData.Data[i - 1];
- if (position == SAR_LONG)
- {
- if (item.Low < result[i - 1])
- {
- position = SAR_SHORT;
- sip = item.Low;
- af = step / 100;
- nextSar = Math.max(item.High, yitem.High);
- nextSar = Math.max(nextSar, ysip + af * (sip - ysip));
- }
- else
- {
- position = SAR_LONG;
- if (item.High > ysip)
- {
- sip = item.High;
- af = Math.min(af + step / 100, exValue / 100);
- }
- nextSar = Math.min(item.Low, yitem.Low);
- nextSar = Math.min(nextSar, result[i - 1] + af * (sip - result[i - 1]));
- }
- }
- else if (position == SAR_SHORT)
- {
- if (item.High > result[i - 1])
- {
- position = SAR_LONG;
- sip = item.High;
- af = step / 100;
- nextSar = Math.min(item.Low, yitem.Low);
- nextSar = Math.min(nextSar, result[i - 1] + af * (sip - ysip));
- }
- else
- {
- position = SAR_SHORT;
- if (item.Low < ysip)
- {
- sip = item.Low;
- af = Math.min(af + step / 100, exValue / 100);
- }
- nextSar = Math.max(item.High, yitem.High);
- nextSar = Math.max(nextSar, result[i - 1] + af * (sip - result[i - 1]));
- }
- }
- result[i] = nextSar;
- }
- return result;
- }
- /*
- 抛物转向点.
- 用法:
- SARTURN(N,S,M),N为计算周期,S为步长,M为极值,若发生向上转向则返回1,若发生向下转向则返回-1,否则为0
- 其用法与SAR函数相同
- */
- this.SARTURN = function (n, step, exValue)
- {
- var result = [];
- var sar = this.SAR(n, step, exValue);
- var stockData = this.SymbolData.Data;
- var index = 0;
- for (index = 0; index < sar.length; ++index)
- {
- if (this.IsNumber(sar[index])) break;
- }
- var flag = 0;
- if (index < stockData.Data.length) flag = stockData.Data[index].Close > sar[index];
- for (var i = index + 1; i < stockData.Data.length; ++i)
- {
- var item = stockData.Data[i];
- if (item.Close < sar[i] && flag) result[i] = -1;
- else result[i] = (item.Close > sar[i] && !flag) ? 1 : 0;
- flag = item.Close > sar[i];
- }
- return result;
- }
- /*
- 属于未来函数,将当前位置到若干周期前的数据设为1.
- 用法:
- BACKSET(X,N),若X非0,则将当前位置到N周期前的数值设为1.
- 例如:
- BACKSET(CLOSE>OPEN,2)若收阳则将该周期及前一周期数值设为1,否则为0
- */
- this.BACKSET = function (condition, n)
- {
- var result = [];
- if (!condition) return result;
- var dataCount = condition.length;
- if (!this.IsNumber(dataCount) || dataCount <= 0) return result;
- if (Array.isArray(n))
- {
- for(var i=0;i<dataCount;++i) //初始化0
- {
- result[i]=0;
- }
- for(var i=0;i<dataCount;++i)
- {
- var value=condition[i];
- var period=n[i];
- if (this.IsNumber(value) && value && this.IsNumber(period))
- {
- for(var j=i,k=0; j>=0 && k<period; --j,++k)
- {
- result[j]=1;
- }
- }
- }
- }
- else
- {
- for (var i = 0; i < dataCount; ++i) //初始化0
- {
- result[i] = 0;
- }
- for (var pos = 0; pos < dataCount; ++pos)
- {
- if (this.IsNumber(condition[pos])) break;
- }
- if (pos == dataCount) return result;
- var num = Math.min(dataCount - pos, Math.max(n, 1));
- for (var i = dataCount - 1, j = 0; i >= 0; --i)
- {
- var value = condition[i];
- if (this.IsNumber(value) && value)
- {
- for (j = i; j > i - num; --j)
- {
- result[j] = 1;
- }
- }
- }
- if (condition[i])
- {
- for (j = i; j >= pos; --j) result[j] = 1;
- }
- }
- return result;
- }
- //STRCAT(A,B):将两个字符串A,B(非序列化)相加成一个字符串C.
- //用法: STRCAT('多头','开仓')将两个字符串'多头','开仓'相加成一个字符串'多头开仓'
- this.STRCAT = function (str1, str2)
- {
- var result="";
- if (IFrameSplitOperator.IsString(str1)) result+=str1;
- if (IFrameSplitOperator.IsString(str2)) result+=str2;
- return result;
- }
- //STRCAT6(A,B,C,D,E,F):将六个字符串A,B,C,D,E,F(非序列化)相加成一个字符串.
- //用法: STRCAT6('多头','开仓','或者','空头','平仓','')将六个字符串相加成一个字符串
- this.STRCAT6=function(str1, str2,str3, str4,str5, str6)
- {
- var result="";
- if (IFrameSplitOperator.IsString(str1)) result+=str1;
- if (IFrameSplitOperator.IsString(str2)) result+=str2;
- if (IFrameSplitOperator.IsString(str3)) result+=str3;
- if (IFrameSplitOperator.IsString(str4)) result+=str4;
- if (IFrameSplitOperator.IsString(str5)) result+=str5;
- if (IFrameSplitOperator.IsString(str6)) result+=str6;
- return result;
- }
- //VARCAT(A,B):将两个字符串A,B相加成一个字符串C.
- //用法: DRAWTEXT(CLOSE>OPEN,LOW,VARCAT('多头',VAR2STR(C,2))) 将两个字符串相加成一个字符串并按条件显示出来
- this.VARCAT=function(data,data2)
- {
- var result=[];
- if (Array.isArray(data) && Array.isArray(data2))
- {
- var nCount=Math.max(data.length, data2.length);
- var strValue="";
- for(var i=0;i<nCount;++i)
- {
- result[i]=null;
- strValue="";
- if (i<data.length)
- {
- var item=data[i];
- if (this.IsString(item))
- strValue+=item;
- }
- if (i<data2.length)
- {
- var item=data2[i];
- if (this.IsString(item))
- strValue+=item;
- }
- if (strValue!="")
- result[i]=strValue;
- }
- }
- else if (this.IsString(data) && Array.isArray(data2))
- {
- for(var i=0;i<data2.length;++i)
- {
- result[i]=null;
- var item=data2[i];
- if (this.IsString(item))
- {
- result[i]=data+item;
- }
- }
- }
- else if (Array.isArray(data) && this.IsString(data2))
- {
- for(var i=0;i<data.length;++i)
- {
- result[i]=null;
- var item=data[i];
- if (this.IsString(item))
- {
- result[i]=item+data2;
- }
- }
- }
- else if (this.IsString(data) && this.IsString(data2))
- {
- result=data+data2;
- }
- return result;
- }
- //VARCAT6(A,B,C,D,E,F):将六个字符串A,B,C,D,E,F相加成一个字符串.
- //每个数据都进行序列运算,若用于多股选股,建议换用STRCAT6
- //用法: VARCAT6('多头',VAR2STR(C,2),' ',VAR2STR(O,2),' ',VAR2STR(MA(C,5),2))将六个字符串相加成一个字符串
- this.VARCAT6=function(data,data2,data3,data4,data5)
- {
- var aryData=[];
- if (Array.isArray(data) || IFrameSplitOperator.IsString(data)) aryData.push(data);
- if (Array.isArray(data2) || IFrameSplitOperator.IsString(data2)) aryData.push(data2);
- if (Array.isArray(data3) || IFrameSplitOperator.IsString(data3)) aryData.push(data3);
- if (Array.isArray(data4) || IFrameSplitOperator.IsString(data4)) aryData.push(data4);
- if (Array.isArray(data5) || IFrameSplitOperator.IsString(data5)) aryData.push(data5);
- if (!IFrameSplitOperator.IsNonEmptyArray(aryData)) return [];
- if (aryData.length==1) return data;
- var tempData=this.VARCAT(aryData[0], aryData[1]);
- var result=tempData;
- for(var i=2;i<aryData.length;++i)
- {
- result=this.VARCAT(tempData,aryData[i]);
- tempData=result;
- }
- return result;
- }
- //FINDSTR(A,B):在字符串A中查找字符串B,如果找到返回1,否则返回0.
- //用法: FINDSTR('多头开仓','开仓')在字符串'多头开仓'中查找字符串'开仓',返回1
- this.FINDSTR=function(data, data2)
- {
- var result=[];
- var str, str2;
- if (IFrameSplitOperator.IsNumber(data)) str=data.toString();
- else str=data;
- if (IFrameSplitOperator.IsNumber(data2)) str2=data2.toString();
- else str2=data2;
- if (IFrameSplitOperator.IsString(str) && IFrameSplitOperator.IsString(str2))
- {
- if (str.indexOf(str2)>=0) return 1;
- else return 0;
- }
- else if (Array.isArray(data) && IFrameSplitOperator.IsString(str2))
- {
- for(var i=0;i<data.length;++i)
- {
- var item=data[i];
- if (IFrameSplitOperator.IsString(item))
- {
- result[i]=item.indexOf(str2)>=0?1:0;
- }
- else if (IFrameSplitOperator.IsNumber(item))
- {
- str=item.toString();
- result[i]=str.indexOf(str2)>=0?1:0;
- }
- else
- {
- result[i]=0;
- }
- }
- }
- return result;
- }
- this.STRLEN=function(data)
- {
- if (IFrameSplitOperator.IsString(data)) return data.length;
- if (Array.isArray(data))
- {
- var result=[];
- for(var i=0;i<data.length;++i)
- {
- var item=data[i];
- if (IFrameSplitOperator.IsString(item)) result[i]=item.length;
- else result[i]=null;
- }
- return result;
- }
- return null;
- }
- this.STRCMP=function(data, data2)
- {
- if (IFrameSplitOperator.IsString(data) && IFrameSplitOperator.IsString(data2))
- {
- return data==data2? 1:0;
- }
- return null;
- }
- //STRSPACE(A):字符串附带一空格
- this.STRSPACE=function(data)
- {
- var result=[];
- if (Array.isArray(data))
- {
- for(var i=0;i<data.length;++i)
- {
- result[i]=null;
- var item=data[i];
- if (TouchList.IsString(item))
- result[i]=item+' ';
- }
- }
- else
- {
- if (this.IsString(data))
- result=data+" ";
- }
- return result;
- }
- //CON2STR(A,N):取A最后的值(非序列值)转为字符串,小数位数N.
- //用法: CON2STR(FINANCE(20),3)表示取营业收入,以3位小数转为字符串
- this.CON2STR = function (data, n)
- {
- var result = "";
- var dec=0;
- if (IFrameSplitOperator.IsNumber(n)) dec=n;
- if (Array.isArray(data))
- {
- for (var i = data.length - 1; i >= 0; --i)
- {
- var item = data[i];
- if (this.IsNumber(item))
- {
- result = item.toFixed(dec);
- return result;
- }
- }
- }
- else
- {
- if (this.IsNumber(data))
- result = data.toFixed(dec);
- }
- return result;
- }
- //VAR2STR(A,N):取A的每一个值转为字符串,小数位数N.
- //用法: VAR2STR(C,3)表示取收盘价,以3位小数转为字符串
- this.VAR2STR=function(data,n)
- {
- var result=[];
- var dec=0;
- if (IFrameSplitOperator.IsNumber(n)) dec=n;
- if (Array.isArray(data))
- {
- for(var i=0;i<data.length;++i)
- {
- result[i]=null;
- var item=data[i];
- if (this.IsNumber(item))
- result[i]=item.toFixed(dec);
- }
- }
- else
- {
- if (this.IsNumber(data))
- result=data.toFixed(dec);
- }
- return result;
- }
- this.ZTPRICE = function (data, rate)
- {
- if (!this.IsNumber(rate)) return null;
- if (Array.isArray(data))
- {
- var result = [];
- for (var i in data)
- {
- var item = data[i];
- if (this.IsNumber(item)) result[i] = (1 + rate) * item;
- else result[i] = null;
- }
- return result;
- }
- else if (this.IsNumber(data))
- {
- var result = (1 + rate) * data;
- return result;
- }
- }
- this.DTPRICE = function (data, rate)
- {
- if (!this.IsNumber(rate)) return null;
- if (Array.isArray(data))
- {
- var result = [];
- for (var i in data)
- {
- var item = data[i];
- if (this.IsNumber(item)) result[i] = (1 - rate) * item;
- else result[i] = null;
- }
- return result;
- }
- else if (this.IsNumber(data))
- {
- var result = (1 - rate) * data;
- return result;
- }
- }
- /*
- FRACPART(A) 取得小数部分
- 含义:FRACPART(A)返回数值的小数部分
- 阐释:例如FRACPART(12.3)求得0.3,FRACPART(-3.5)求得-0.5
- */
- this.FRACPART = function (data)
- {
- if (Array.isArray(data))
- {
- var result = [];
- var integer = 0;
- for (var i in data)
- {
- var item = data[i];
- if (this.IsNumber(item))
- {
- integer = parseInt(item);
- result[i] = item - integer;
- }
- else result[i] = null;
- }
- return result;
- }
- else if (this.IsNumber(data))
- {
- integer = parseInt(data);
- var result = data - integer;
- return result;
- }
- }
- /*
- 取符号.
- 用法:
- SIGN(X),返回X的符号.当X>0,X=0,X<0分别返回1,0,-1
- */
- this.SIGN=function(data)
- {
- if (Array.isArray(data))
- {
- var result=[];
- for(var i=0;i<data.length;++i)
- {
- var item=data[i];
- result[i]=null;
- if (!IFrameSplitOperator.IsNumber(item)) continue;
- if (item>0) result[i]=1;
- else if (item==0) result[i]=0;
- else result[i]=-1;
- }
- return result;
- }
- else
- {
- if (data>0) return 1;
- else if (data==0) return 0;
- else return -1;
- }
- }
- /*
- 统计连续满足条件的周期数.
- 用法: BARSLASTCOUNT(X),统计连续满足X条件的周期数.
- 例如: BARSLASTCOUNT(CLOSE>OPEN)表示统计连续收阳的周期数
- */
- this.BARSLASTCOUNT=function(data)
- {
- var result=null;
- if (Array.isArray(data))
- {
- result=[];
- if (data.length>0)
- {
- var count=0;
- for(var i=data.length-1;i>=0;--i)
- {
- count=0;
- for(var j=i;j>=0;--j)
- {
- if (data[j]) ++count;
- else break;
- }
- result[i]=count;
- }
- }
- }
- else
- {
- if (data) result=1;
- else result=0;
- }
- return result;
- }
- //取整.
- //用法: INTPART(A)返回沿A绝对值减小方向最接近的整数
- //例如:INTPART(12.3)求得12,INTPART(-3.5)求得-3
- this.INTPART=function(data)
- {
- var result=null;
- if (Array.isArray(data))
- {
- result=[];
- for(var i in data)
- {
- var item=data[i];
- if (this.IsNumber(item)) result[i]=parseInt(item);
- else result[i]=null;
- }
- }
- else if (this.IsNumber(data))
- {
- result=parseInt(data);
- }
- return result;
- }
- //用法:CONST(A),取A最后的值为常量.
- //例如:CONST(INDEXC),表示取大盘现价
- this.CONST=function(data)
- {
- if (Array.isArray(data))
- {
- var count=data.length;
- if (count>0) return data[count-1];
- return null;
- }
- else
- {
- return data;
- }
- }
- //当前值是近多少周期内的最大值.
- //用法: TOPRANGE(X):X是近多少周期内X的最大值
- //例如: TOPRANGE(HIGH)表示当前最高价是近多少周期内最高价的最大值
- this.TOPRANGE=function(data)
- {
- if (this.IsNumber(data)) return 0;
-
- var result=[];
- if (Array.isArray(data))
- {
- var count=data.length;
- for(var i=count-1; i>=0;--i)
- {
- result[i]=0;
- var item=data[i];
- if (!this.IsNumber(item)) continue;
- var value=0;
- for(var j=i-1;j>=0;--j)
- {
- if (data[j]>item)
- {
- break;
- }
- ++value;
- }
- result[i]=value;
- }
- }
- return result;
- }
- //当前值是近多少周期内的最小值.
- //用法:LOWRANGE(X):X是近多少周期内X的最小值
- //例如:LOWRANGE(LOW)表示当前最低价是近多少周期内最低价的最小值
- this.LOWRANGE=function(data)
- {
- if (this.IsNumber(data)) return 0;
- var result=[];
- if (Array.isArray(data))
- {
- var count=data.length;
- for(var i=count-1; i>=0;--i)
- {
- result[i]=0;
- var item=data[i];
- if (!this.IsNumber(item)) continue;
- var value=0;
- for(var j=i-1;j>=0;--j)
- {
- if (data[j]<item)
- {
- break;
- }
- ++value;
- }
- result[i]=value;
- }
- }
- return result;
- }
- //N周期前的M周期内的第T个最小值.
- //用法:FINDLOW(VAR,N,M,T):VAR在N日前的M天内第T个最低价
- this.FINDLOW=function(data,n,m,t)
- {
- if (this.IsNumber(data)) return data;
-
- var result=[];
- if (Array.isArray(data))
- {
- var count=data.length;
- for(var i=count-1;i>=0;--i)
- {
- result[i]=null;
- var aryValue=[];
- for(var j=n;j<m;++j)
- {
- var index=i-j;
- if (index<0) break;
- var item=data[index];
- if (this.IsNumber(item)) aryValue.push(item);
- }
- if (aryValue.length>0)
- {
- aryValue.sort(function(a,b) { return a-b;});
- var index=t-1;
- if (index<0) index=0;
- else if (index>=aryValue.length) index=aryValue.length-1;
- result[i]=aryValue[index];
- }
- }
- }
- return result;
- }
- //N周期前的M周期内的第T个最大值.
- //用法:FINDHIGH(VAR,N,M,T):VAR在N日前的M天内第T个最高价
- this.FINDHIGH=function(data,n,m,t)
- {
- if (this.IsNumber(data)) return data;
-
- var result=[];
- if (Array.isArray(data))
- {
- var count=data.length;
- for(var i=count-1;i>=0;--i)
- {
- result[i]=null;
- var aryValue=[];
- for(var j=n;j<m;++j)
- {
- var index=i-j;
- if (index<0) break;
- var item=data[index];
- if (this.IsNumber(item)) aryValue.push(item);
- }
- if (aryValue.length>0)
- {
- aryValue.sort(function(a,b) { return b-a;});
- var index=t-1;
- if (index<0) index=0;
- else if (index>=aryValue.length) index=aryValue.length-1;
- result[i]=aryValue[index];
- }
- }
- }
- return result;
- }
- //N周期前的M周期内的第T个最大值到当前周期的周期数.
- //用法:FINDHIGHBARS(VAR,N,M,T):VAR在N日前的M天内第T个最高价到当前周期的周期数
- this.FINDHIGHBARS=function(data, n, m, t)
- {
- if (this.IsNumber(data)) return (m-n-t);
-
- var result=[];
- if (Array.isArray(data))
- {
- var count=data.length;
- for(var i=count-1;i>=0;--i)
- {
- result[i]=null;
- var aryValue=[];
- for(var j=n;j<m;++j)
- {
- var index=i-j;
- if (index<0) break;
- var item=data[index];
- if (this.IsNumber(item)) aryValue.push({ Value:item, Period:j });
- }
- if (aryValue.length>0)
- {
- aryValue.sort(function(a,b) { return b.Value-a.Value;});
- var index=t-1;
- if (index<0) index=0;
- else if (index>=aryValue.length) index=aryValue.length-1;
- result[i]=aryValue[index].Period;
- }
- }
- }
- return result;
- }
- //N周期前的M周期内的第T个最小值到当前周期的周期数.
- //用法:FINDLOWBARS(VAR,N,M,T):VAR在N日前的M天内第T个最低价到当前周期的周期数.
- this.FINDLOWBARS=function(data, n, m, t)
- {
- if (this.IsNumber(data)) return (m-n-t);
-
- var result=[];
- if (Array.isArray(data))
- {
- var count=data.length;
- for(var i=count-1;i>=0;--i)
- {
- result[i]=null;
- var aryValue=[];
- for(var j=n;j<m;++j)
- {
- var index=i-j;
- if (index<0) break;
- var item=data[index];
- if (this.IsNumber(item)) aryValue.push({ Value:item, Period:j });
- }
- if (aryValue.length>0)
- {
- aryValue.sort(function(a,b) { return a.Value-b.Value;});
- var index=t-1;
- if (index<0) index=0;
- else if (index>=aryValue.length) index=aryValue.length-1;
- result[i]=aryValue[index].Period;
- }
- }
- }
- return result;
- }
- //求高值名次.
- //用法:HOD(X,N):求当前X数据是N周期内的第几个高值,N=0则从第一个有效值开始.
- //例如:HOD(HIGH,20)返回是20日的第几个高价
- this.HOD=function(data, n)
- {
- var result=[];
- if (IFrameSplitOperator.IsNumber(data)) return 1;
- if (Array.isArray(data))
- {
- var count=data.length;
- for(var i=count-1;i>=0;--i)
- {
- var value=data[i];
- if (!IFrameSplitOperator.IsNumber(value)) continue;
- if (Array.isArray(n)) var subCount=parseInt(n[i]);
- else var subCount=parseInt(n);
- if (n<=0) subCount=i;
- var index=1;
- for(var j=i-1, k=1; j>=0 && k<subCount; --j, ++k)
- {
- var item=data[j];
- if (IFrameSplitOperator.IsNumber(item) && item>value) ++index;
- }
- result[i]=index;
- }
- }
- return result;
- }
- //求低值名次.
- //用法:LOD(X,N):求当前X数据是N周期内的第几个低值,N=0则从第一个有效值开始.
- //例如:LOD(LOW,20)返回是20日的第几个低价
- this.LOD=function(data, n)
- {
- var result=[];
- if (IFrameSplitOperator.IsNumber(data)) return 1;
- if (Array.isArray(data))
- {
- var count=data.length;
- for(var i=count-1;i>=0;--i)
- {
- var value=data[i];
- if (!IFrameSplitOperator.IsNumber(value)) continue;
- if (Array.isArray(n)) var subCount=parseInt(n[i]);
- else var subCount=parseInt(n);
- if (n<=0) subCount=i;
- var index=1;
- for(var j=i-1, k=1; j>=0 && k<subCount; --j, ++k)
- {
- var item=data[j];
- if (IFrameSplitOperator.IsNumber(item) && item<value) ++index;
- }
- result[i]=index;
- }
- }
- return result;
- }
- //属于未来函数,下一次条件成立到当前的周期数.
- //用法:BARSNEXT(X):下一次X不为0到现在的天数
- //例如:BARSNEXT(CLOSE/REF(CLOSE,1)>=1.1)表示下一个涨停板到当前的周期数
- this.BARSNEXT=function(data)
- {
- if (!Array.isArray(data)) return 0;
- var result=[];
- for(var i=0;i<data.length;++i)
- {
- result[i]=0;
- for(var j=i, k=0;j<data.length;++j, ++k)
- {
- var item=data[j];
- if (item>0)
- {
- result[i]=k;
- break;
- }
- }
- }
- return result;
- }
- //取随机数.
- //用法:RAND(N),返回一个范围在1-N的随机整数
- this.RAND=function(n)
- {
- if (Array.isArray(n))
- {
- var result=[];
- for(var i in n)
- {
- result[i]=null;
- var item=n[i];
- var value=parseInt(item);
- if (value<=0) continue;
- result[i]=Math.ceil(Math.random()*value);
- }
- return result;
- }
- else
- {
- var value=parseInt(n);
- if (value<=0) return null;
- var stockData= this.SymbolData.Data;
- var count=stockData.Data.length;
- var result=[];
- for(var i=0;i<count;++i)
- {
- result[i]=Math.ceil(Math.random()*value);
- }
-
- return result;
- }
- }
- //求自适应均线值.
- //用法:AMA(X,A),A为自适应系数,必须小于1.
- //算法:Y=Y'+A*(X-Y').初值为X
- this.AMA=function(data,n)
- {
- var result=[];
- var period;
- if (Array.isArray(n))
- {
- //取最新的一个数据做为自适应系数
- for(var i=data.length-1;i>=0;--i)
- {
- if (this.IsNumber(n[i]))
- {
- period=n[i];
- break;
- }
- }
- }
- else
- {
- period=n;
- }
-
- if (this.IsNumber(period))
- {
- if (period>1) return result;
- var index=0;
- var value=0;
- for(index;index<data.length;++index)
- {
- result[index]=null;
- if (this.IsNumber(data[index]))
- {
- value=data[index];
- result[index]=value;
- break;
- }
- }
- for(var i=index+1;i<data.length;++i)
- {
- var item=data[i];
- result[i]=result[i-1]+period*(item-result[i-1]);
- }
- }
-
- return result;
- }
- //返回移动平均
- //用法:TMA(X,A,B),A和B必须小于1,算法 Y=(A*Y'+B*X),其中Y'表示上一周期Y值.初值为X
- this.TMA=function(data, a, b)
- {
- var result=[];
- if (this.IsNumber(a) && a<=1 && this.IsNumber(b) && b<1)
- {
- var bFirstFind=false;
- var proValue; //上一个值
- for(var i in data)
- {
- result[i]=null;
- if (bFirstFind==false)
- {
- var item=data[i];
- if (this.IsNumber(item))
- {
- result[i]=item;
- proValue=result[i];
- bFirstFind=true;
- }
- }
- else
- {
- var item=data[i];
- if (!this.IsNumber(item)) continue;
- result[i]=a*result[i-1]+b*item;
- proValue=result[i];
- }
- }
- }
- return result;
- }
- this.ROUND=function(data)
- {
- if (this.IsNumber(data))
- {
- return Math.round(data);
- }
-
- var result=[];
- if (Array.isArray(data))
- {
- for(var i in data)
- {
- var item=data[i];
- if (this.IsNumber(item))
- result[i]=Math.round(item);
- else
- result[i]=null;
- }
- }
- return result;
- }
- this.ROUND2=function(data,n)
- {
- var ROUND2_SEED=
- [
- 1,10,100,1000,
- 10000,
- 100000,
- 1000000,
- 10000000,
- 100000000,
- 1000000000,
- 10000000000,
- 100000000000,
- 1000000000000
- ];
- var decimal=0;
- if (this.IsNumber(n)) decimal=parseInt(n);
- if (n<0) decimal=0;
- else if (n>=ROUND2_SEED.length) decimal=ROUND2_SEED.length-1;
- if (this.IsNumber(data))
- {
- return Math.round(data*ROUND2_SEED[decimal])/ROUND2_SEED[decimal];
- }
- var result=[];
- if (Array.isArray(data))
- {
- for(var i in data)
- {
- var item=data[i];
- if (this.IsNumber(item))
- {
- result[i]=Math.round(item*ROUND2_SEED[decimal])/ROUND2_SEED[decimal];
- }
- else
- {
- result[i]=null;
- }
- }
- }
- return result;
- }
- /* 文华
- TRMA(X,N): 求X在N个周期的三角移动平均值。
- 算法:三角移动平均线公式,是采用算数移动平均,并且对第一个移动平均线再一次应用算数移动平均。
- TRMA(X,N) 算法如下
- ma_half= MA(X,N/2)
- trma=MA(ma_half,N/2)
- 注:
- 1、N包含当前k线。
- 2、当N为有效值,但当前的k线数不足N根,函数返回空值。
- 3、N为0或空值的情况下,函数返回空值。
- 例1:
- TRMA5:TRMA(CLOSE,5);//计算5个周期内收盘价的三角移动平均。(N不能被2整除)
- //TRMA(CLOSE,5)=MA(MA(CLOSE,(5+1)/2)),(5+1)/2);
- 例2:
- TRMA10:TRMA(CLOSE,10);// 计算10个周期内收盘价的三角移动平均。(N能被2整除)
- TRMA(CLOSE,10)=MA(MA(CLOSE,10/2),(10/2)+1));
- */
- this.TRMA=function(data,n)
- {
- if (!this.IsNumber(n) || n<=0) return [];
- n=parseInt(n);
- var nFalf=0,nFalf2=0;
- if (n%2==0)
- {
- nFalf=parseInt(n/2);
- nFalf2=nFalf+1;
- }
- else
- {
- nFalf=parseInt((n+1)/2);
- nFalf2=nFalf;
- }
- var maFalf=this.MA(data,nFalf);
- var result=this.MA(maFalf,nFalf2);
- return result;
- }
- //VALUEWHEN(COND,X)
- //当COND条件成立时,取X的当前值,否则取VALUEWHEN的上个值.
- this.VALUEWHEN=function(cond,data)
- {
- if (Array.isArray(cond))
- {
- var result=[];
- if (Array.isArray(data))
- {
- var preValue=null;
- for(var i in cond)
- {
- if (i>=data.length)
- {
- result[i]=preValue;
- continue;
- }
- var item=data[i];
- if (cond[i])
- {
- result[i]=item;
- preValue=item;
- }
- else
- {
- result[i]=preValue;
- }
- }
- }
- else
- {
- var preValue=null;
- for(var i in cond)
- {
- if (cond[i])
- {
- result[i]=data;
- preValue=data;
- }
- else
- {
- result[i]=preValue;
- }
- }
- }
- return result;
- }
- else
- {
- return cond? 1:0;
- }
- }
- /*
- HARMEAN(X,N) 求X在N个周期内的调和平均值。
- 算法举例:HARMEAN(X,5)=1/[(1/X1+1/X2+1/X3+1/X4+1/X5)/5]
- 注:
- 1、N包含当前k线。
- 2、调和平均值与倒数的简单平均值互为倒数。
- 3、当N为有效值,但当前的k线数不足N根,函数返回空值。
- 4、N为0或空值的情况下,函数返回空值。
- 5、X为0或空值的情况下,函数返回空值。
- 6、N可以为变量。
- 例:HM5:=HARMEAN(C,5);//求5周期收盘价的调和平均值。
- */
- this.HARMEAN=function(data, n)
- {
- var result=[];
- if (Array.isArray(data))
- {
- if (Array.isArray(n))
- {
- for(var i=0;i<data.length;++i)
- {
- if (i>=n.length)
- {
- result[i]=null;
- continue;
- }
- var count=parseInt(n[i]);
- if (count<=0 || count>i)
- {
- result[i]=null;
- continue;
- }
- var sum=0;
- for(var j=0;j<count;++j)
- {
- var item=data[i-j];
- if (!this.IsNumber(item) || item==0)
- {
- sum=null;
- break;
- }
- sum+=1/item;
- }
- if (sum==null)
- {
- result[i]=null;
- }
- else
- {
- result[i]=1/(sum/count);
- }
- }
- }
- else if (this.IsNumber(n))
- {
- n=parseInt(n);
- if (n<=0) return result;
- for(var i=0;i<data.length;++i)
- {
- if (n>i)
- {
- result[i]=null;
- continue;
- }
- var sum=0;
- for(var j=0;j<n;++j)
- {
- var item=data[i-j];
- if (!this.IsNumber(item) || item==0)
- {
- sum=null;
- break;
- }
- sum+=1/item;
- }
- if (sum==null)
- {
- result[i]=null;
- }
- else
- {
- result[i]=1/(sum/n);
- }
- }
- }
- }
- return result;
- }
- //指定日期到1990.12.19的天数.
- //用法: DATETODAY(date)
- //DATETODAY(date).返回date到1990.12.19的天数.有效日期为(901219-1341231)
- //例如: DATETODAY(901219)返回0.
- this.DATETODAY=function(data)
- {
- var result=[];
- var startDate=new Date('1990-12-19')
- var startValue=19901219;
- var ONE_DAY=1000 * 60 * 60 * 24
- if (Array.isArray(data))
- {
- for(var i in data)
- {
- result[i]=null;
- var item=data[i];
- if (!this.IsNumber(item)) continue;
- var value=item+19000000;
- if (value<startValue) continue;
- var year=parseInt(value/10000);
- var month=parseInt((value%10000)/100);
- var day=parseInt(value%100);
- var dateItem=new Date(`${year}-${month}-${day}`);
- result[i]=Math.round((dateItem-startDate)/ONE_DAY);
- }
- }
- else if (this.IsNumber(data))
- {
- var value=data+19000000;
- if (value>=startValue)
- {
- var year=parseInt(value/10000);
- var month=parseInt((value%10000)/100);
- var day=parseInt(value%100);
- var dateItem=new Date(`${year}-${month}-${day}`);
- return Math.round((dateItem-dateItem)/ONE_DAY);
- }
- }
- return result;
- }
- //求1990.12.19后第若干天的日期.
- //用法:DAYTODATE(N)
- //DAYTODATE(N).返回1990.12.19后第N天的日期.有效天数为(0-20000)
- //例如:DAYTODATE(0)返回901219.
- this.DAYTODATE=function(data)
- {
- var startDate=new Date('1990-12-19')
- var result=[];
- if (Array.isArray(data))
- {
- for(var i in data)
- {
- result[i]=null;
- var item=data[i];
- if (!this.IsNumber(item)) continue;
- startDate.setDate(startDate.getDate()+item);
- var value=startDate.getFullYear()*10000+(startDate.getMonth()+1)*100+startDate.getDate();
- value-=19000000;
- result[i]=value;
- startDate.setDate(startDate.getDate()-item);
- }
- }
- else if (this.IsNumber(data))
- {
- startDate.setDate(startDate.getDate()+data);
- var value=startDate.getFullYear()*10000+(startDate.getMonth()+1)*100+startDate.getDate();
- value-=19000000;
- return value;
- }
- return result;
- }
- /*
- 求指定时刻距0时有多长时间.
- 用法:
- TIMETOSEC(time)
- TIMETOSEC(time).返回time时刻距0时有多长时间,单位为秒.有效时间为(0-235959)
- 例如:
- TIMETOSEC(93000)返回34200.
- */
- this.TIMETOSEC=function(time)
- {
- var hour=parseInt(time/10000);
- var minute=parseInt((time%10000)/100);
- var sec=time%100;
- var value=hour*60*60+minute*60+sec;
- return value;
- }
- /*
- 求0时后若干秒是什么时间.
- 用法:
- SECTOTIME(N)
- SECTOTIME(N).返回0时后N秒是什么时间.有效秒数为(0-86399)
- 例如:
- SECTOTIME(34200)返回93000.
- */
- this.SECTOTIME=function(data)
- {
- var daySec = 24 * 60 * 60;
- var hourSec= 60 * 60;
- var minuteSec=60;
- var dd = Math.floor(data / daySec);
- var hh = Math.floor((data % daySec) / hourSec);
- var mm = Math.floor((data % hourSec) / minuteSec);
- var ss=data%minuteSec;
- var value=hh*10000+mm*100+ss;
- return value;
- }
- this.MOD=function(data, data2)
- {
- var result=[];
- let isNumber=typeof(data)=='number';
- let isNumber2=typeof(data2)=='number';
- //单数值
- if (isNumber && isNumber2)
- {
- return JSAlgorithm.MOD(data,data2);
- }
- else if (!isNumber && !isNumber2) //都是数组相加
- {
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- result[i]=null; //初始化
- if (i<data.length && i<data2.length)
- {
- if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=JSAlgorithm.MOD(data[i],data2[i]);
- }
- }
- return result;
- }
- else if (isNumber && !isNumber2) //单数字 数组
- {
- for(var i in data2)
- {
- result[i]=null;
- if (this.IsNumber(data) && this.IsNumber(data2[i])) result[i]=JSAlgorithm.MOD(data,data2[i]);
- }
- return result;
- }
- else if (!isNumber && isNumber2) //数组 单数字
- {
- for(var i in data)
- {
- result[i]=null;
- if (this.IsNumber(data[i]) && this.IsNumber(data2)) result[i]=JSAlgorithm.MOD(data[i],data2);
- }
- return result;
- }
- return result;
- }
- this.POW=function(data, n)
- {
- var result=[];
- if (Array.isArray(data) && Array.isArray(n))
- {
- for(var i=0;i<data.length;++i)
- {
- var value=data[i];
- var value2=n[i];
- if (this.IsNumber(value) && this.IsNumber(value2)) result[i]=Math.pow(value,value2);
- else result[i]=null;
- }
- }
- else if (this.IsNumber(data) && Array.isArray(n))
- {
- for(var i=0;i<n.length;++i)
- {
- var item=n[i];
- if (this.IsNumber(item)) result[i]=Math.pow(data,item);
- else result[i]=null;
- }
- }
- else if (this.IsNumber(data) && this.IsNumber(n))
- {
- return Math.pow(data,n);
- }
- else if (Array.isArray(data) && this.IsNumber(n))
- {
- for(var i=0; i<data.length;++i)
- {
- var item=data[i];
- if (this.IsNumber(item)) result[i]=Math.pow(item,n);
- else result[i]=null;
- }
- }
-
- return result;
- }
- this.CEILING=function(data)
- {
- let isNumber=typeof(data)=='number';
- if (isNumber) return parseInt(data);
- var result=[];
- for(var i in data)
- {
- var item=data[i];
- if (this.IsNumber(item)) result[i]=parseInt(item);
- else result[i]=null;
- }
- return result;
- }
- this.FLOOR=function(data)
- {
- let isNumber=typeof(data)=='number';
- if (isNumber) return parseInt((data-1));
- var result=[];
- for(var i in data)
- {
- var item=data[i];
- if (this.IsNumber(item)) result[i]=parseInt((item-1));
- else result[i]=null;
- }
- return result;
- }
- this.PWINNER=function(n, data, node)
- {
- var result=[];
- return result;
- }
- //用法:ANY(CLOSE>OPEN,10),表示前10日内存在着阳线
- this.ANY=function(data, n)
- {
- if (n<=0) n=1;
- var result=[];
- if (Array.isArray(data))
- {
- if (n>=data.length) return 0;
- for(var i=n, j=0;i<data.length;++i)
- {
- var value=0;
- for(j=0;j<n;++j)
- {
- var item=data[i-j];
- if (item>0)
- {
- value=1;
- break;
- }
- }
- result[i]=value;
- }
- return result;
- }
- else if (IFrameSplitOperator.IsNumber(data))
- {
- if (data<=0) return 0;
- if (n>=this.SymbolData.Data.Data.length) return 0;
- for(var i=n; i<this.SymbolData.Data.Data.length; ++i)
- {
- result[i]=1;
- }
- return result;
- }
- else
- {
- return 0;
- }
- }
- //用法:ALL(CLOSE>OPEN,10),表示前10日内一直阳线
- this.ALL=function(data, n)
- {
- if (n<=0) n=1;
- var result=[];
- if (Array.isArray(data))
- {
- if (n>=data.length) return 0;
- for(var i=n, j=0;i<data.length;++i)
- {
- var value=1;
- for(j=0;j<n;++j)
- {
- var item=data[i-j];
- if (!(item>0))
- {
- value=0;
- break;
- }
- }
- result[i]=value;
- }
- return result;
- }
- else if (IFrameSplitOperator.IsNumber(data))
- {
- if (data<=0) return 0;
- if (n>=this.SymbolData.Data.Data.length) return 0;
- for(var i=n; i<this.SymbolData.Data.Data.length; ++i)
- {
- result[i]=1;
- }
- return result;
- }
- else
- {
- return 0;
- }
- }
- /*
- TESTSKIP(A):满足A则直接返回.
- 用法:
- TESTSKIP(A)
- 表示如果满足条件A则该公式直接返回,不再计算接下来的表达式 注意:A为非序列数据,只取最后一个数据
- */
- this.TESTSKIP=function(data, node)
- {
- if (Array.isArray(data))
- {
- if (data.length<=0) return false;
- var item=data[data.length-1];
- if (!item) return false;
- return true;
- }
- else if (IFrameSplitOperator.IsNumber(data))
- {
- if (data<=0) return false;
- return true;
- }
- else
- {
- if (!data) return false;
- return true;
- }
- }
- /*根据条件执行不同的语句,可中止(根据序列的最后一个数值来判断).
- 用法:
- IFC(X,A,B)若X不为0则执行A,否则执行B.IFC与IF函数的区别:根据X的值来选择性执行A、B表达式.
- 例如:
- IFC(CLOSE>OPEN,HIGH,TESTSKIP(1));L;表示当日收阳则返回最高值,并执行下一句"L;",否则退出公式计算
- */
- this.IFC=function(data)
- {
- if (Array.isArray(data))
- {
- var item=data[data.length-1];
- if (IFrameSplitOperator.IsNumber(item)) return item>0;
- return false;
- }
- else if (IFrameSplitOperator.IsNumber(data))
- {
- return data>0;
- }
- else
- {
- return false;
- }
- }
- /*
- 有效数据右对齐.
- 用法:
- ALIGNRIGHT(X)有效数据向右移动,左边空出来的周期填充无效值
- 例如:TC:=IF(CURRBARSCOUNT=2 || CURRBARSCOUNT=5,DRAWNULL,C);XC:ALIGNRIGHT(TC);删除了两天的收盘价,并将剩余数据右移
- */
- this.ALIGNRIGHT=function(data)
- {
- if (Array.isArray(data))
- {
- var result=[];
- var index=data.length-1;
- for(var i=data.length-1;i>=0;--i)
- {
- var item=data[i];
- if (IFrameSplitOperator.IsNumber(item) || IFrameSplitOperator.IsString(item))
- {
- result[index]=item;
- --index;
- }
- }
- for(var i=index;i>=0;--i)
- {
- result[i]=null;
- }
- return result;
- }
- else
- {
- return data;
- }
- }
- //格式化字符串 "{0}-{1}", C, O;
- this.STRFORMAT=function(strFormat,args,node)
- {
- var aryParam=strFormat.match(/{\d+}/g);
- if (!IFrameSplitOperator.IsNonEmptyArray(aryParam)) return null;
- var mapParam=new Map(); //key=index, value={Text}
- var maxIndex=-1;
- for(var i=0;i<aryParam.length;++i)
- {
- var item=aryParam[i];
- if (item.length<3) continue;
- var value=item.slice(1, item.length-1);
- var index=parseInt(value);
- var paramItem={ Src:item, Index:index, Text:null};
- if (maxIndex<index) maxIndex=index;
- mapParam.set(index, paramItem);
- }
- var isArray=false; //是否输出数组字符串
- var maxCount=0;
- for(var i=1;i<args.length;++i)
- {
- var item=args[i];
- if (Array.isArray(item))
- {
- isArray=true;
- if (maxCount<item.length) maxCount=item.length;
- }
- }
- if (isArray)
- {
- var result=[];
- for(var i=0;i<maxCount;++i)
- {
- var strItem=strFormat;
-
- for(var item of mapParam)
- {
- var paramInfo=item[1];
- var paramItem=args[paramInfo.Index+1];
- var text="null";
- if (paramItem)
- {
- if (Array.isArray(paramItem))
- {
- var value=paramItem[i];
- if (value) text=`${value}`;
- }
- else
- {
- text=`${paramItem}`;
- }
- }
- strItem=strItem.replace(paramInfo.Src, text);
- }
- result[i]=strItem;
- }
- return result;
- }
- else
- {
- var result=strFormat;
- for(var item of mapParam)
- {
- var paramInfo=item[1];
- var paramItem=args[paramInfo.Index+1];
- var text="null";
- if (paramItem)
- {
- text=`${paramItem}`;
- }
- result=result.replace(paramInfo.Src, text);
- }
- return result;
- }
- }
-
- //函数调用
- this.CallFunction=function(name,args,node)
- {
- switch(name)
- {
- case 'MAX':
- case "MAX6":
- return this.MAX(args,node);
- case 'MIN':
- case "MIN6":
- return this.MIN(args,node);
- case 'REF':
- return this.REF(args[0], args[1]);
- case "REFV":
- return this.REFV(args[0], args[1]);
- case 'REFX':
- return this.REFX(args[0], args[1]);
- case "REFXV":
- return this.REFXV(args[0], args[1]);
- case "REFX1": //文华函数
- return this.REFX(args[0], args[1]);
- case 'ABS':
- return this.ABS(args[0]);
- case 'MA':
- return this.MA(args[0], args[1]);
- case "EMA":
- return this.EMA(args[0], args[1]);
- case "SMA":
- return this.SMA(args[0], args[1],args[2]);
- case "DMA":
- return this.DMA(args[0], args[1]);
- case "XMA":
- return this.XMA(args[0], args[1]);
- case 'EXPMA':
- return this.EXPMA(args[0], args[1]);
- case 'EXPMEMA':
- return this.EXPMEMA(args[0], args[1]);
- case 'COUNT':
- return this.COUNT(args[0], args[1]);
- case 'LLV':
- return this.LLV(args[0], args[1]);
- case "LV":
- return this.LV(args[0], args[1]);
- case 'LLVBARS':
- return this.LLVBARS(args[0], args[1]);
- case 'HHV':
- return this.HHV(args[0], args[1]);
- case "HV":
- return this.HV(args[0], args[1]);
- case 'HHVBARS':
- return this.HHVBARS(args[0], args[1]);
- case 'MULAR':
- return this.MULAR(args[0], args[1]);
- case 'CROSS':
- return this.CROSS(args[0], args[1]);
- case "CROSSDOWN":
- return this.CROSSDOWN(args[0], args[1]);
- case 'LONGCROSS':
- return this.LONGCROSS(args[0], args[1], args[2]);
- case 'AVEDEV':
- return this.AVEDEV(args[0], args[1]);
- case 'STD':
- return this.STD(args[0], args[1]);
- case "STDDEV":
- return this.STDDEV(args[0], args[1]);
- case 'IF':
- case 'IFF':
- case "IFELSE":
- return this.IF(args[0], args[1], args[2]);
- case 'IFN':
- return this.IFN(args[0], args[1], args[2]);
- case 'NOT':
- return this.NOT(args[0]);
- case 'SUM':
- return this.SUM(args[0], args[1]);
- case 'RANGE':
- return this.RANGE(args[0],args[1],args[2]);
- case 'EXIST':
- return this.EXIST(args[0],args[1]);
- case 'EXISTR':
- return this.EXISTR(args[0], args[1], args[2]);
- case "ISVALID":
- return this.ISVALID(args[0]);
- case 'FILTER':
- return this.FILTER(args[0], args[1]);
- case 'TFILTER':
- return this.TFILTER(args[0],args[1],args[2]);
- case 'SLOPE':
- return this.SLOPE(args[0],args[1]);
- case 'BARSLAST':
- return this.BARSLAST(args[0]);
- case 'BARSCOUNT':
- return this.BARSCOUNT(args[0]);
- case 'BARSSINCEN':
- return this.BARSSINCEN(args[0], args[1]);
- case 'BARSSINCE':
- return this.BARSSINCE(args[0]);
- case 'LAST':
- return this.LAST(args[0], args[1], args[2]);
- case 'EVERY':
- return this.EVERY(args[0], args[1]);
- case 'ZIG':
- return this.ZIG(args[0], args[1]);
- case 'TROUGHBARS':
- return this.TROUGHBARS(args[0], args[1], args[2]);
- case "TROUGH":
- return this.TROUGH(args[0],args[1],args[2]);
- case 'PEAKBARS':
- return this.PEAKBARS(args[0], args[1], args[2]);
- case 'PEAK':
- return this.PEAK(args[0],args[1],args[2]);
- case 'COST':
- return this.COST(args[0], node);
- case 'WINNER':
- return this.WINNER(args[0], node);
- case "PWINNER":
- return this.PWINNER(args[0],args[1],node);
- case 'UPNDAY':
- return this.UPNDAY(args[0], args[1]);
- case 'DOWNNDAY':
- return this.DOWNNDAY(args[0], args[1]);
- case 'NDAY':
- return this.NDAY(args[0], args[1], args[2]);
- case 'DEVSQ':
- return this.DEVSQ(args[0], args[1]);
- case 'FORCAST':
- return this.FORCAST(args[0], args[1]);
- case 'STDP':
- return this.STDP(args[0], args[1]);
- case 'VAR':
- return this.VAR(args[0], args[1]);
- case 'VARP':
- return this.VARP(args[0], args[1]);
- case 'RELATE':
- return this.RELATE(args[0], args[1], args[2]);
- case 'COVAR':
- return this.COVAR(args[0], args[1], args[2]);
- case 'BETA':
- return this.BETA(args[0]);
- case 'BETA2':
- return this.BETA2(args[0], args[1], args[2]);
- case 'WMA':
- return this.WMA(args[0], args[1]);
- case 'MEMA':
- return this.MEMA(args[0], args[1]);
- case 'SUMBARS':
- return this.SUMBARS(args[0], args[1]);
- case 'REVERSE':
- return this.REVERSE(args[0]);
- case 'SAR':
- return this.SAR(args[0], args[1], args[2]);
- case 'SARTURN':
- return this.SARTURN(args[0], args[1], args[2]);
- case 'BACKSET':
- return this.BACKSET(args[0], args[1]);
- case 'STRCAT':
- return this.STRCAT(args[0], args[1]);
- case "STRCAT6":
- return this.STRCAT6(args[0], args[1],args[2], args[3],args[4], args[5]);
- case "VARCAT":
- return this.VARCAT(args[0], args[1]);
- case "VARCAT6":
- return this.VARCAT6(args[0], args[1],args[2], args[3],args[4], args[5]);
- case "VAR2STR":
- return this.VAR2STR(args[0], args[1]);
- case 'CON2STR':
- return this.CON2STR(args[0], args[1]);
- case "STRSPACE":
- return this.STRSPACE(args[0]);
- case 'FINDSTR':
- return this.FINDSTR(args[0], args[1]);
- case "STRCMP":
- return this.STRCMP(args[0], args[1]);
- case "STRLEN":
- return this.STRLEN(args[0]);
- case "STRFORMAT":
- return this.STRFORMAT(args[0], args, node);
- case 'DTPRICE':
- return this.DTPRICE(args[0], args[1]);
- case 'ZTPRICE':
- return this.ZTPRICE(args[0], args[1]);
- case 'FRACPART':
- return this.FRACPART(args[0]);
- case "SIGN":
- return this.SIGN(args[0]);
- case 'BARSLASTCOUNT':
- return this.BARSLASTCOUNT(args[0]);
- case 'INTPART':
- return this.INTPART(args[0]);
- case "CONST":
- return this.CONST(args[0]);
- case "TOPRANGE":
- return this.TOPRANGE(args[0]);
- case "LOWRANGE":
- return this.LOWRANGE(args[0]);
- case "FINDLOW":
- return this.FINDLOW(args[0],args[1],args[2],args[3]);
- case "FINDLOWBARS":
- return this.FINDLOWBARS(args[0],args[1],args[2],args[3]);
- case "FINDHIGH":
- return this.FINDHIGH(args[0],args[1],args[2],args[3]);
- case "FINDHIGHBARS":
- return this.FINDHIGHBARS(args[0],args[1],args[2],args[3]);
- case "BARSNEXT":
- return this.BARSNEXT(args[0]);
- case "HOD":
- return this.HOD(args[0], args[1]);
- case "LOD":
- return this.LOD(args[0], args[1]);
- case "AMA":
- return this.AMA(args[0], args[1]);
- case "TMA":
- return this.TMA(args[0],args[1],args[2]);
- case "ROUND":
- return this.ROUND(args[0]);
- case "ROUND2":
- return this.ROUND2(args[0],args[1]);
- case "TRMA":
- return this.TRMA(args[0],args[1]);
- case "VALUEWHEN":
- return this.VALUEWHEN(args[0],args[1]);
- case "HARMEAN":
- return this.HARMEAN(args[0],args[1]);
- case "DATETODAY":
- return this.DATETODAY(args[0]);
- case "DAYTODATE":
- return this.DAYTODATE(args[0]);
- case "TIMETOSEC":
- return this.TIMETOSEC(args[0]);
- case "SECTOTIME":
- return this.SECTOTIME(args[0]);
- case 'MOD':
- return this.MOD(args[0],args[1]);
- case 'POW':
- return this.POW(args[0],args[1]);
- case 'CEILING':
- return this.CEILING(args[0]);
- case 'FLOOR':
- return this.FLOOR(args[0]);
- case "BETWEEN":
- return this.BETWEEN(args[0], args[1],args[2]);
- case "ANY":
- return this.ANY(args[0],args[1]);
- case "ALL":
- return this.ALL(args[0],args[1]);
- case "ALIGNRIGHT":
- return this.ALIGNRIGHT(args[0]);
- //三角函数
- case 'ATAN':
- return this.Trigonometric(args[0], Math.atan);
- case 'ACOS':
- return this.ACOS(args[0]);
- case 'ASIN':
- return this.ASIN(args[0]);
- case 'COS':
- return this.Trigonometric(args[0], Math.cos);
- case 'SIN':
- return this.Trigonometric(args[0], Math.sin);
- case 'TAN':
- return this.Trigonometric(args[0], Math.tan);
- case 'LN':
- return this.Trigonometric(args[0], Math.log);
- case 'LOG':
- return this.Trigonometric(args[0], Math.log10);
- case 'EXP':
- return this.Trigonometric(args[0], Math.exp);
- case 'SQRT':
- return this.Trigonometric(args[0], Math.sqrt);
- default:
- this.ThrowUnexpectedNode(node,'函数'+name+'不存在');
- }
- }
- //调用自定义函数 返回数据格式{Out:输出数据, Draw:绘图数据(可选)}
- this.CallCustomFunction=function(name, args, symbolData, node)
- {
- var functionInfo=g_JSComplierResource.CustomFunction.Data.get(name);
- var dwonloadData=symbolData.GetStockCacheData({ CustomName:name, Node:node });
- if (!functionInfo.Invoke)
- return { Out: dwonloadData }
- JSConsole.Complier.Log('[JSAlgorithm::CallCustomFunction] call custom function functionInfo=',functionInfo);
- var self=this;
- var obj=
- {
- Name:name,
- Args:args,
- Symbol:symbolData.Symbol, Period:symbolData.Period, Right:symbolData.Right,
- KData:symbolData.Data, //K线数据
- DownloadData:dwonloadData,
- ThrowError:function(error)
- {
- self.ThrowUnexpectedNode(node, error);
- }
- };
- return functionInfo.Invoke(obj);
- }
- this.ThrowUnexpectedNode=function(node,message)
- {
- let marker=node.Marker;
- let msg=message || "执行异常";
-
- return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
-
- }
- }
- //是否有是有效的数字
- JSAlgorithm.prototype.IsNumber=function(value)
- {
- if (value==null) return false;
- if (isNaN(value)) return false;
- return true;
- }
- //是否是整形
- JSAlgorithm.prototype.IsInteger=function(x)
- {
- return (typeof x === 'number') && (x % 1 === 0);
- }
- //是否有是有效的除数
- JSAlgorithm.prototype.IsDivideNumber=function(value)
- {
- if (value==null) return false;
- if (isNaN(value)) return false;
- if (value==0) return false;
- return true;
- }
- //取模
- JSAlgorithm.MOD=function(number,divisor)
- {
- if( (number < 0 && divisor < 0) || (number >=0 && divisor >= 0)) //同号
- {
- if(parseInt(number) == number && parseInt(divisor) == divisor) //全为整数
- {
- return number%divisor;
- }
- else //被除数-(整商×除数)之后在第一位小数位进行四舍五入
- {
- var value = parseFloat((number - (Math.floor(number/divisor) * divisor)).toFixed(1));
- return value;
- }
- }
- else //异号
- {
- var absNumber = Math.abs(number); //绝对值
- var absDivisor = Math.abs(divisor); //绝对值
- var value = Math.abs(Math.abs(divisor) * (Math.floor(absNumber/absDivisor) + 1) - Math.abs(number));
- if(divisor < 0) value = -value
- return value;
- }
- }
- //是否是字符串
- JSAlgorithm.prototype.IsString=function(value)
- {
- if (value && typeof(value)=='string') return true;
- return false;
- }
- /*
- 绘图函数
- */
- function JSDraw(errorHandler, symbolData)
- {
- this.ErrorHandler=errorHandler;
- this.SymbolData = symbolData;
- this.DRAWTEXT=function(condition,price,text)
- {
- let drawData=[];
- let result={DrawData:drawData, DrawType:'DRAWTEXT',Text:text};
- if (Array.isArray(condition))
- {
- var IsNumber=this.IsNumber(price);
- var isFixedPosition=false;
- if (price==="TOP"|| price==="BOTTOM")
- {
- result.FixedPosition=price;
- isFixedPosition=true;
- }
- for(var i=0; i<condition.length; ++i)
- {
- drawData[i]=null;
- if (condition[i]!==1) continue;
- if (IsNumber || isFixedPosition)
- {
- drawData[i]=price;
- }
- else
- {
- if (this.IsNumber(price[i])) drawData[i]=price[i];
- }
- }
- }
- else if (this.IsNumber(condition) && condition===1)
- {
- var IsNumber=this.IsNumber(price);
- var isFixedPosition=false;
- if (price==="TOP"|| price==="BOTTOM")
- {
- result.FixedPosition=price;
- isFixedPosition=true;
- }
- for(var i=0;i<this.SymbolData.Data.Data.length;++i)
- {
- if (IsNumber || isFixedPosition)
- {
- drawData[i]=price;
- }
- else
- {
- if (this.IsNumber(price[i])) drawData[i]=price[i];
- }
- }
- }
- return result;
- }
- //1.固定位置显示文字;2.在指标排序中显示字符串栏目.
- //用法:DRAWTEXT_FIX(COND,X,Y,TYPE,TEXT),COND中一般需要加ISLASTBAR,当COND条件满足时,在当前指标窗口内(X,Y)位置书写文字TEXT,X,Y为书写点在窗口中相对于左上角的百分比,TYPE:0为左对齐,1为右对齐,2=居中.
- //例如:DRAWTEXT_FIX(ISLASTBAR AND CLOSE/OPEN>1.08,0.5,0.5,0,'大阳线')表示最后一个交易日实体阳线大于8%时在窗口中间位置显示'大阳线'字样.若文字中含有&,则进行折行.最多只能显示250个字符
- this.DRAWTEXT_FIX=function(condition,x,y,type,text)
- {
- var drawData={ Value:[], Text:[] };
- var result={DrawData:drawData, DrawType:'DRAWTEXT_FIX', Text:null, Position:{ X:x, Y:y, Type:type } };
- if (Array.isArray(condition))
- {
- for(var i=0; i<condition.length; ++i)
- {
- drawData.Text[i]=null;
- drawData.Value[i]=0;
- if (condition[i]!==1) continue;
-
- drawData.Value[i]=1;
- drawData.Text[i]=text;
- }
- }
- else
- {
- if(condition===1)
- {
- for(var i=0;i<this.SymbolData.Data.Data.length;++i)
- {
- drawData.Text[i]=text;
- drawData.Value[i]=1;
- }
- }
- }
-
- return result;
- }
- /*
- 固定位置显示数字.
- 用法: DRAWNUMBER_FIX(COND,X,Y,TYPE,NUMBER,decimal=2),当COND条件满足时,在当前指标窗口内(X,Y)位置书写数字NUMBER,X,Y为书写点在窗口中相对于左上角的百分比,TYPE:0为左对齐,1为右对齐 2=居中
- 例如: DRAWNUMBER_FIX(CURRBARSCOUNT=1 AND CLOSE/OPEN>1.08,0.5,0.5,0,C)表示最后一个交易日实体阳线大于8%时在窗口中间位置显示收盘价.
- */
- this.DRAWNUMBER_FIX=function(condition,x,y,align,data, decimal=2)
- {
- var drawData={ Value:[], Text:[], };
- var result={ DrawData:drawData, DrawType:'DRAWNUMBER_FIX', Position:{ X:x, Y:y, Type:align } };
- var isNumber=IFrameSplitOperator.IsNumber(data);
- if (Array.isArray(condition))
- {
- for(var i=0; i<condition.length; ++i)
- {
- drawData.Text[i]=null;
- drawData.Value[i]=null;
- if (condition[i]!==1) continue;
- if (isNumber)
- {
- drawData.Text[i]=data.toFixed(decimal);
- drawData.Value[i]=data;
- }
- else
- {
- if (i>=data.length || !IFrameSplitOperator.IsNumber(data[i])) continue;
- var item=data[i];
- drawData.Text[i]=item.toFixed(decimal);
- drawData.Value[i]=item;
- }
- }
- }
- else
- {
- if(condition!==1)
- {
-
- }
- else
- {
- for(var i=0;i<this.SymbolData.Data.Data.length;++i)
- {
- if (isNumber)
- {
- drawData.Text[i]=data.toFixed(decimal);
- drawData.Value[i]=data;
- }
- else
- {
- if (i>=data.length || !IFrameSplitOperator.IsNumber(data[i])) continue;
- var item=data[i];
- drawData.Text[i]=item.toFixed(decimal);
- drawData.Value[i]=item;
- }
- }
- }
- }
- return result;
- }
- //direction 文字Y轴位置 0=middle 1=价格的顶部 2=价格的底部
- //offset 文字Y轴偏移
- this.SUPERDRAWTEXT = function (condition, price, text, direction, offset)
- {
- let drawData = [];
- let result = { DrawData: drawData, DrawType: 'SUPERDRAWTEXT', Text: text, YOffset: offset, Direction: direction, TextAlign: 'center' };
- if (condition.length <= 0) return result;
- var IsNumber = typeof (price) == "number";
- for (var i in condition)
- {
- drawData[i] = null;
- if (isNaN(condition[i]) || !condition[i]) continue;
- if (IsNumber)
- {
- drawData[i] = price;
- }
- else
- {
- if (this.IsNumber(price[i])) drawData[i] = price[i];
- }
- }
- return result;
- }
- this.STICKLINE=function(condition,data,data2,width,type)
- {
- let drawData=[];
- let result={DrawData:drawData, DrawType:'STICKLINE',Width:width, Type:type};
- var IsNumber=typeof(data)=="number";
- var IsNumber2=typeof(data2)=="number";
- if (Array.isArray(condition)) //数组
- {
- if(condition.length<=0) return result;
- for(var i in condition)
- {
- drawData[i]=null;
- if (isNaN(condition[i]) || !condition[i]) continue;
- if (IsNumber && IsNumber2)
- {
- drawData[i]={Value:data,Value2:data2};
- }
- else if (IsNumber && !IsNumber2)
- {
- if (isNaN(data2[i])) continue;
- drawData[i]={Value:data,Value2:data2[i]};
- }
- else if (!IsNumber && IsNumber2)
- {
- if (isNaN(data[i])) continue;
- drawData[i]={Value:data[i],Value2:data2};
- }
- else
- {
- if (isNaN(data[i]) || isNaN(data2[i])) continue;
- drawData[i]={Value:data[i],Value2:data2[i]};
- }
- }
- }
- else
- {
- if(!condition) return result;
- for(var i=0;i<this.SymbolData.Data.Data.length;++i) //以K线长度为数据长度
- {
- drawData[i]=null;
- if (IsNumber && IsNumber2)
- {
- drawData[i]={Value:data,Value2:data2};
- }
- else if (IsNumber && !IsNumber2)
- {
- if (!this.IsNumber(data2[i])) continue;
- drawData[i]={Value:data,Value2:data2[i]};
- }
- else if (!IsNumber && IsNumber2)
- {
- if (!this.IsNumber(data[i])) continue;
- drawData[i]={Value:data[i],Value2:data2};
- }
- else
- {
- if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i])) continue;
- drawData[i]={Value:data[i],Value2:data2[i]};
- }
- }
- }
-
-
- return result;
- }
- /*
- DRAWLINE 绘制直线段
- 在图形上绘制直线段。
- 用法: DRAWLINE(COND1,PRICE1,COND2,PRICE2,EXPAND)
- 当COND1条件满足时,在PRICE1位置画直线起点,当COND2条件满足时,在PRICE2位置画直线终点,EXPAND为延长类型。
- 例如: DRAWLINE(HIGH>=HHV(HIGH,20),HIGH,LOW<=LLV(LOW,20),LOW,1) 表示在创20天新高与创20天新低之间画直线并且向右延长。
- */
- this.DRAWLINE=function(condition,data,condition2,data2,expand)
- {
- let drawData=[];
- let result={DrawData:drawData, DrawType:'DRAWLINE', Expand:expand};
- if(condition.length<=0) return result;
- let count=Math.max(condition.length,condition2.length);
- let bFirstPoint=false;
- let bSecondPont=false;
- let lineCache={Start:{ },End:{ }, List:new Array()};
- function CopyLineData(aryDest, arySrc)
- {
- if (!IFrameSplitOperator.IsNonEmptyArray(arySrc)) return;
- for(var j=0; j<arySrc.length; ++j)
- {
- var item=arySrc[j];
- aryDest[item.ID]=item.Value;
- }
- }
- for(let i=0;i<count;++i)
- {
- drawData[i]=null;
- if (i<condition.length && i<condition2.length)
- {
- if (bFirstPoint==false && bSecondPont==false)
- {
- if (condition[i]==null || !condition[i]) continue;
- bFirstPoint=true;
- lineCache.Start={ID:i, Value:data[i]}; //第1个点
- }
- else if (bFirstPoint==true && bSecondPont==false)
- {
- var bCondition2=(condition2[i]!=null && condition2[i]); //条件2
- if (!bCondition2)
- {
- if (condition[i] ) //条件1满足
- lineCache.Start={ID:i, Value:data[i]}; //移动第1个点
- continue;
- }
- if (bCondition2)
- {
- bSecondPont=true;
- lineCache.End={ID:i, Value:data2[i]}; //第2个点
-
- if (condition[i])
- {
- var lineData=this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
- CopyLineData(drawData,lineData);
- bFirstPoint=true;
- bSecondPont=false;
- lineCache.Start={ID:i, Value:data[i]}; //第1个点
- }
- }
- }
- else if (bFirstPoint==true && bSecondPont==true)
- {
- var bCondition2=(condition2[i]!=null && condition2[i]); //条件2
- if (bCondition2) //条件2满足
- {
- lineCache.End={ID:i, Value:data2[i]}; //移动第2个点
- }
- else if (condition[i]) //条件1满足
- {
- var lineData=this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
- CopyLineData(drawData,lineData);
- if (expand==1) this.CalculateDrawDataExtendLine(drawData, lineCache.Start.ID-2);//右延长线
- bFirstPoint=bSecondPont=false;
- lineCache={Start:{ },End:{ }};
- bFirstPoint=true;
- bSecondPont=false;
- lineCache.Start={ID:i, Value:data[i]}; //第1个点
- }
- }
- }
- //最后一组线
- if (bFirstPoint==true && bSecondPont==true)
- {
- var lineData=this.CalculateDrawLine(lineCache);
- CopyLineData(drawData,lineData);
- }
- }
- if (expand==1) this.CalculateDrawDataExtendLine(drawData);//右延长线
- return result;
- }
- this.CalculateDrawDataExtendLine=function(drawData, maxCount)
- {
- if (maxCount<0) return;
- var x2=null;
- var count=drawData.length;
- if (this.IsNumber(maxCount) && maxCount<count) count=maxCount;
- for(var i=count-1;i>=0;--i)
- {
- if (this.IsNumber(drawData[i]))
- {
- x2=i;
- break;
- }
- }
- //y3=(y1-y2)*(x3-x1)/(x2-x1)
- if (x2!=null && x2-1>=0)
- {
- var x1=x2-1;
- for(var i=x2+1;i<count;++i)
- {
- var y1=drawData[x1];
- var y2=drawData[x2];
- var y3=(y1-y2)*(i-x1)/(x2-x1);
- if (y1-y3<0) break;
- drawData[i]=y1-y3;
- }
- }
- }
- /*
- 画出带状线.
- 用法: DRAWBAND(VAL1,COLOR1,VAL2,COLOR2),当VAL1>VAL2时,在VAL1和VAL2之间填充COLOR1;当VAL1<VAL2时,填充COLOR2,这里的颜色均使用RGB函数计算得到.
- 例如: DRAWBAND(OPEN,RGB(0,224,224),CLOSE,RGB(255,96,96));
- */
- this.DRAWBAND=function(data,color,data2,color2)
- {
- let drawData=[];
- let result = { DrawData: drawData, DrawType: 'DRAWBAND', Color: [color.toLowerCase(), color2.toLowerCase()]};
- let count=Math.max(data.length, data2.length);
- for(let i=0;i<count;++i)
- {
- let item={Value:null, Value2:null};
- if (i<data.length) item.Value=data[i];
- if (i<data2.length) item.Value2=data2[i];
- drawData.push(item);
- }
- return result;
- }
- this.DRAWKLINE = function (high, open, low, close)
- {
- let drawData = [];
- let result = { DrawData: drawData, DrawType: 'DRAWKLINE' };
- let count = Math.max(high.length, open.length, low.length, close.length);
- for (let i = 0; i < count; ++i)
- {
- let item = { Open: null, High: null, Low: null, Close: null };
- if (i < high.length && i < open.length && i < low.length && i < close.length)
- {
- item.Open = open[i];
- item.High = high[i];
- item.Low = low[i];
- item.Close = close[i];
- }
- drawData[i] = item;
- }
- return result;
- }
- //满足条件画一根K线
- this.DRAWKLINE_IF = function (condition, high, open, low, close)
- {
- let drawData = [];
- let result = { DrawData: drawData, DrawType: 'DRAWKLINE_IF' };
- let count = Math.max(condition.length, high.length, open.length, low.length, close.length);
- for (let i = 0; i < count; ++i) {
- let item = { Open: null, High: null, Low: null, Close: null };
- if (i < high.length && i < open.length && i < low.length && i < close.length && i < condition.length)
- {
- if (condition[i])
- {
- item.Open = open[i];
- item.High = high[i];
- item.Low = low[i];
- item.Close = close[i];
- }
- }
- drawData[i] = item;
- }
- return result;
- }
- /*
- DRAWCOLORKLINE 绘制K线
- 用法:
- DRAWCOLORKLINE(Cond,Color,Empty);
- 满足Cond条件时,按照Color颜色绘制K线,根据Empty标志判断是空心还是实心。COLOR代表颜色,Empty非0为空心。
- 注:
- 不支持将该函数定义为变量,即不支持下面的写法:
- A:DRAWCOLORKLINE(Cond,Color,Empty);
- 例:
- DRAWCOLORKLINE(C>O,COLORBLUE,0);//收盘价大于开盘价,用蓝色绘制实心K线
- */
- this.DRAWCOLORKLINE=function(condition, color, empty)
- {
- let drawData=[];
- let result={ DrawData:drawData, DrawType:'DRAWCOLORKLINE', IsEmptyBar:!(empty==0), Color:color };
- if (Array.isArray(condition)) //数组
- {
- for(var i=0; i<condition.length && i<this.SymbolData.Data.Data.length; ++i)
- {
- drawData[i]=null;
- var condItem=condition[i];
- if (!condItem) continue;
- var kItem=this.SymbolData.Data.Data[i];
- if (!kItem) continue;
- drawData[i]={Open:kItem.Open,High:kItem.High, Low:kItem.Low, Close:kItem.Close};
- }
- }
- else
- {
- if (condition)
- {
- for(var i=0;i<this.SymbolData.Data.Data.length;++i) //以K线长度为数据长度
- {
- drawData[i]=null;
- var kItem=this.SymbolData.Data.Data[i];
- if (!kItem) continue;
- drawData[i]={Open:kItem.Open,High:kItem.High, Low:kItem.Low, Close:kItem.Close };
- }
- }
- }
- return result;
- }
- /*
- PLOYLINE 折线段
- 在图形上绘制折线段。
- 用法: PLOYLINE(COND,PRICE),当COND条件满足时,以PRICE位置为顶点画折线连接。
- 例如: PLOYLINE(HIGH>=HHV(HIGH,20),HIGH)表示在创20天新高点之间画折线。
- */
- this.POLYLINE = function (condition, data)
- {
- let drawData = [];
- let result = { DrawData: drawData, DrawType: 'POLYLINE' };
- let isNumber = typeof (data) == 'number';
- let bFirstPoint = false;
- let bSecondPont = false;
- if (isNumber)
- {
- for (let i in condition)
- {
- drawData[i] = null;
- if (bFirstPoint == false)
- {
- if (!condition[i]) continue;
- drawData[i] = data;
- bFirstPoint = true;
- }
- else {
- drawData[i] = data;
- }
- }
- }
- else
- {
- let lineCache = { Start: {}, End: {}, List: new Array() };
- for (let i in condition)
- {
- drawData[i] = null;
- if (bFirstPoint == false && bSecondPont == false)
- {
- if (condition[i] == null || !condition[i]) continue;
- if (i >= data.length || !this.IsNumber(data[i])) continue;
- bFirstPoint = true;
- lineCache.Start = { ID: parseInt(i), Value: data[i] }; //第1个点
- }
- else if (bFirstPoint == true && bSecondPont == false)
- {
- if (condition[i] == null || !condition[i]) continue;
- if (i >= data.length || !this.IsNumber(data[i])) continue;
- lineCache.End = { ID: parseInt(i), Value: data[i] }; //第2个点
- //根据起始点和结束点 计算中间各个点的数据
- let lineData = this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
- for (let j in lineData)
- {
- let item = lineData[j];
- drawData[item.ID] = item.Value;
- }
- let start = { ID: lineCache.End.ID, Value: lineCache.End.Value };
- lineCache = { Start: start, End: {} };
- }
- }
- }
- return result
- }
- /*
- 画出数字.
- 用法:
- DRAWNUMBER(COND,PRICE,NUMBER),当COND条件满足时,在PRICE位置书写数字NUMBER.
- 例如:
- DRAWNUMBER(CLOSE/OPEN>1.08,LOW,C)表示当日实体阳线大于8%时在最低价位置显示收盘价.
- */
- this.DRAWNUMBER = function (condition, data, data2,decimal)
- {
- let drawData={ Value:[], Text:[] };
- let result={ DrawData:drawData, DrawType:'DRAWNUMBER' };
- var dec=2; //小数位数
- if (IFrameSplitOperator.IsNumber(decimal)) dec=decimal;
- var priceData={ DataType:0, SingleValue:null, ArrayValue:null }; //SingleValue=单值 ArrayValue=数组
- if (Array.isArray(data))
- {
- priceData.ArrayValue=data;
- priceData.DataType=2;
- }
- else
- {
- if (data==="TOP"|| data==="BOTTOM") result.FixedPosition=data;
- priceData.SingleValue=data;
- priceData.DataType=1;
- }
- var numberData={ DataType:0, SingleValue:null,ArrayValue:null };
- if (Array.isArray(data2))
- {
- numberData.ArrayValue=data2;
- numberData.DataType=2;
- }
- else
- { //单值
- numberData.SingleValue=data2;
- numberData.DataType=1;
- if (IFrameSplitOperator.IsNumber(data2))
- {
- if (IFrameSplitOperator.IsInteger(data2)) numberData.SingleValue=data2.toString();
- else text=data2.toFixed(dec);
- }
- }
- if (Array.isArray(condition))
- {
- for(var i=0; i<condition.length; ++i)
- {
- drawData.Value[i]=null;
- if (!condition[i]) continue;
- drawData.Value[i]=this.DRAWNUMBER_Temp_PriceItem(i,priceData);
- drawData.Text[i]=this.DRAWNUMBER_Temp_NumberItem(i,numberData,dec);
- }
- }
- else if (this.IsNumber(condition) && condition)
- {
- for(var i=0;i<this.SymbolData.Data.Data.length;++i)
- {
- drawData.Value[i]=this.DRAWNUMBER_Temp_PriceItem(i,priceData);
- drawData.Text[i]=this.DRAWNUMBER_Temp_NumberItem(i,numberData,dec);
- }
- }
-
- return result;
- }
- this.DRAWNUMBER_Temp_PriceItem=function(index, priceData)
- {
- if (!priceData) return null;
- if (priceData.DataType==1) return priceData.SingleValue;
- if (!IFrameSplitOperator.IsNonEmptyArray(priceData.ArrayValue)) return null;
- return priceData.ArrayValue[index];
- }
- this.DRAWNUMBER_Temp_NumberItem=function(index,numberData,decimal)
- {
- if (!numberData) return null;
- if (numberData.DataType==1)
- {
- var value=numberData.SingleValue;
- if (IFrameSplitOperator.IsNumber(value)) return value.toFixed(decimal);
- else if (value) return value.toString();
- return null;
- }
- if (!IFrameSplitOperator.IsNonEmptyArray(numberData.ArrayValue)) return null;
- var value=numberData.ArrayValue[index];
- if (this.IsNumber(value))
- {
- if (IFrameSplitOperator.IsInteger(value)) return value.toString();
- else return value.toFixed(decimal);
- }
- return value.toString();
- }
- /*
- 在图形上绘制小图标.
- 用法:
- DRAWICON(COND,PRICE,TYPE),当COND条件满足时,在PRICE位置画TYPE号图标(TYPE为1--41).
- 例如:
- DRAWICON(CLOSE>OPEN,LOW,1)表示当收阳时在最低价位置画1号图标.
- */
- this.DRAWICON = function (condition, data, type, markID)
- {
- if (IFrameSplitOperator.IsString(type)) //把ICO1=>1
- {
- var value=type.replace('ICO',"");
- type=parseInt(value);
- }
- let icon = g_JSComplierResource.GetDrawTextIcon(type);
- if (!icon) icon = { Symbol: '●', Color: 'rgb(0,139,69)'};
- let drawData = [];
- let result = { DrawData: drawData, DrawType: 'DRAWICON', Icon: icon , IconID:type};
- if (markID) result.MarkID=markID;
- if (condition.length <= 0) return result;
- var IsNumber = typeof (data) == "number";
- if (typeof (condition) == 'number')
- {
- if (!condition) return result;
- for (var i = 0; i < this.SymbolData.Data.Data.length; ++i)
- {
- if (IsNumber)
- {
- drawData[i] = data;
- }
- else
- {
- if (i < data.length && this.IsNumber(data[i])) drawData[i] = data[i];
- else drawData[i] = null;
- }
- }
- return result;
- }
-
- for (var i in condition)
- {
- drawData[i] = null;
- if (!condition[i]) continue;
- if (IsNumber)
- {
- drawData[i] = data;
- }
- else
- {
- if (this.IsNumber(data[i])) drawData[i] = data[i];
- }
- }
- return result;
- }
- /*
- ICON:在k线图上,显示小图标。
- 用法:ICON(TYPE,ICON);
- 当TYPE为1,则在K线最高价位置显示图标ICON,当TYPE为0,则在最低价位置显示
- 图标ICON。
- 注:
- 1、该函数与判断条件连用,如:COND,ICON(TYPE,ICON);
- 2、该函数支持在函数后设置垂直对齐方式:VALIGN0(上对齐)、VALIGN1(中对齐)、VALIGN2(下对齐)
- 即可以写为如下格式:
- CLOSE<OPEN,ICON(1,'阴'),VALIGN0;
- 例1:
- CLOSE>OPEN,ICON(1,'ICO1');//表示K线收盘大于开盘时,在最高价上显示图标1。
- 写完“ICON(1,” 以后,点击插入图标按钮,再单击选中的图标插入到函数中,图标用
- 'ICO1'~'ICO105'表示
- */
- this.ICON=function(position, type)
- {
- if (IFrameSplitOperator.IsString(type)) //把ICO1=>1
- {
- var value=type.replace('ICO',"");
- type=parseInt(value);
- }
- var icon=g_JSComplierResource.GetDrawTextIcon(type);
- if (!icon) icon={ Symbol: '●', Color: 'rgb(0,139,69)'};
- let drawData=[];
- let result={DrawData:drawData, DrawType:'ICON',Icon:icon};
- for(var i=0;i<this.SymbolData.Data.Data.length;++i)
- {
- var kItem=this.SymbolData.Data.Data[i];
- if (!kItem) continue;
- if (position==0) drawData[i]=kItem.Low;
- else if (position==1) drawData[i]=kItem.High;
- }
- return result;
- }
- // 相对位置上画矩形.
- //用法: DRAWRECTREL(LEFT,TOP,RIGHT,BOTTOM,COLOR),以图形窗口(LEFT,TOP)为左上角,(RIGHT,BOTTOM)为右下角绘制矩形,坐标单位是窗口沿水平和垂直方向的1/1000,取值范围是0—999,超出范围则可能显示在图形窗口外,矩形中间填充颜色COLOR,COLOR为0表示不填充.
- //例如: DRAWRECTREL(0,0,500,500,RGB(255,255,0))表示在图形最左上部1/4位置用黄色绘制矩形
- this.DRAWRECTREL = function (left, top, right, bottom, color)
- {
- let drawData =
- {
- Rect:
- {
- Left: Math.min(left,right), Top: Math.min(top,bottom),
- Right: Math.max(left,right), Bottom: Math.max(top,bottom)
- },
- Color: color
- };
- if (color == 0) drawData.Color = null;
- let result = { DrawData: drawData, DrawType: 'DRAWRECTREL' };
- return result;
- }
- //DRAWTEXTREL(X,Y,TEXT),在图形窗口(X,Y)坐标位置书写文字TEXT,坐标单位是窗口沿水平和垂直方向的1/1000,X、Y取值范围是0—999,超出范围则可能显示在图形窗口外。
- //例如:DRAWTEXTREL(500,500,'注意')表示在图形中间位置显示'注意'字样。
- this.DRAWTEXTREL=function(x, y, text)
- {
- let drawData={ Point:{X:x, Y:y} };
- if (IFrameSplitOperator.IsString(text))
- drawData.Text=text;
- else if (IFrameSplitOperator.IsNonEmptyArray(text))
- drawData.Text=text[0];
-
- let result={DrawData:drawData, DrawType:'DRAWTEXTREL'};
- return result;
- }
- //DRAWTEXTABS(X,Y,TEXT),在图形窗口(X,Y)坐标位置书写文字TEXT,坐标单位是像素,图形窗口左上角坐标为(0,0)。
- //例如:DRAWTEXTABS(0,0,'注意')表示在图形最左上角位置显示'注意'字样。
- this.DRAWTEXTABS=function(x, y, text)
- {
- let drawData={ Point:{X:x, Y:y} };
- if (IFrameSplitOperator.IsString(text))
- drawData.Text=text;
- else if (IFrameSplitOperator.IsNonEmptyArray(text))
- drawData.Text=text[0];
-
- let result={DrawData:drawData, DrawType:'DRAWTEXTABS'};
- return result;
- }
- //填充背景.
- //用法: DRAWGBK(COND,COLOR1,COLOR2,colorAngle) colorAngle=渐近色角度
- //例如: DRAWGBK(O>C,RGB(0,255,0),RGB(255,0,0),0);
- this.DRAWGBK=function(condition, color, color2, colorAngle)
- {
- let drawData={ Color:[], Angle:colorAngle };
- if (color) drawData.Color.push(color);
- if (color2) drawData.Color.push(color2);
- let result={DrawData:null, DrawType:'DRAWGBK'};
- if (Array.isArray(condition))
- {
- for(var i in condition)
- {
- var item=condition[i];
- if (item)
- {
- result.DrawData=drawData;
- break;
- }
- }
- }
- else
- {
- if (condition) result.DrawData=drawData;
- }
- return result;
- }
- this.DRAWGBK2=function(condition, color, color2, colorAngle)
- {
- let drawData={ Color:[], Angle:colorAngle };
- if (color) drawData.Color.push(color);
- if (color2) drawData.Color.push(color2);
- let result={DrawData:null, DrawType:'DRAWGBK2'};
- if (Array.isArray(condition))
- {
- drawData.Data=[];
- for(var i in condition)
- {
- var item=condition[i];
- drawData.Data[i]=item ? 1:0;
- }
- result.DrawData=drawData;
- }
- else
- {
- if (condition)
- {
- result.DrawData=drawData;
- result.DrawType="DRAWGBK";
- }
- }
- return result;
- }
- //填充部分背景.
- //用法:
- //DRAWGBK_DIV(COND,COLOR1,COLOR2,填色方式,填充范围),填充满足COND条件的背景区域
- //填色方式:0是上下渐进 1是左右渐进 2是用COLOR1画框线 3是用COLOR1画框线, 用COLOR2填充
- //填充范围:0为整个区域 1为最高最低区 2为开盘收盘区
- //例如:
- //DRAWGBK_DIV(C>O,RGB(0,255,0),RGB(255,0,0),0,0);
- this.DRAWGBK_DIV=function(condition, color, color2, colorType, fillType)
- {
- var drawData={ AryColor:[color, color2], ColorType:colorType, FillType:fillType, Data:[] };
- var result={ DrawData:drawData, DrawType:'DRAWGBK_DIV' };
- if (!this.SymbolData || !this.SymbolData.Data || !IFrameSplitOperator.IsNonEmptyArray(this.SymbolData.Data.Data)) return result;
- var aryKData=this.SymbolData.Data.Data;
- if (Array.isArray(condition))
- {
- for(var i=0; i<aryKData.length; ++i)
- {
- var condItem=condition[i];
- var item=null;
- if (condItem)
- {
- var kItem=aryKData[i];
- if (fillType==1) item={ AryValue:[kItem.High, kItem.Low] }
- else if (fillType==2) item={ AryValue:[kItem.Open, kItem.Close] }
- else item={ AryValue:null };
- }
- drawData.Data[i]=item;
- }
- }
- else
- {
- if (condition)
- {
- for(var i=0; i<aryKData.length; ++i)
- {
- var kItem=aryKData[i];
- var item=null;
- if (fillType==1) item={ AryValue:[kItem.High, kItem.Low] }
- else if (fillType==2) item={ AryValue:[kItem.Open, kItem.Close] }
- else item={ AryValue:null };
-
- drawData.Data[i]=item;
- }
- }
- }
- return result;
- }
- this.RGB = function (r, g, b)
- {
- var rgb = `rgb(${r},${g},${b})`;
- return rgb;
- }
- this.RGBA = function (r, g, b, a)
- {
- var rgba = `rgba(${r},${g},${b},${a})`;
- return rgba;
- }
- this.UPCOLOR=function(color)
- {
- return color;
- }
- this.DOWNCOLOR=function(color)
- {
- return color;
- }
- this.STICKTYPE=function(value)
- {
- return value;
- }
- //数据左右偏移
- this.XMOVE=function(offset)
- {
- return offset;
- }
- //数据上下偏移
- this.YMOVE=function(offset)
- {
- return offset;
- }
- this.LINEDASH=function(aryData)
- {
- if (IFrameSplitOperator.IsNonEmptyArray(aryData)) return aryData.slice();
- return [];
- }
- //该函数和DRAWTEXT连用
- //{ Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] }
- this.BACKGROUND=function(color, borderColor, left, right, top, bottom)
- {
- var bg={ Margin:[0,1,1,1] };
- if (color) bg.Color=color;
- if (borderColor) bg.Border=borderColor;
- if (IFrameSplitOperator.IsNumber(left)) bg.Margin[2]=left;
- if (IFrameSplitOperator.IsNumber(right)) bg.Margin[3]=right;
- if (IFrameSplitOperator.IsNumber(top)) bg.Margin[0]=top;
- if (IFrameSplitOperator.IsNumber(bottom)) bg.Margin[1]=bottom;
- return bg;
- }
- //该函数和DRAWTEXT, DRAWNUMBER连用
- //{ color:线段颜色, lineWidth:宽度 lineType:线段样式0=直线 1=虚线}
- this.CKLINE=function(color, lineWidth, lineType, lineDotted)
- {
- var drawData={ Color:color, LineWidth: 1, LineType:0, LineDot:[3,3] };
- if (IFrameSplitOperator.IsPlusNumber(lineWidth)) drawData.LineWidth=lineWidth;
- if (IFrameSplitOperator.IsPlusNumber(lineType)) drawData.LineType=lineType;
- if (lineDotted)
- {
- let ary=lineDotted.split(',');
- var dotted=[];
- for(var i in ary)
- {
- var item=ary[i];
- if (!item) continue;
- var value=parseInt(ary[i]);
- if (value<=0) continue;
- dotted.push(value);
- }
- if (dotted.length>0) drawData.LineDotted=dotted;
- }
- drawData.Data=[];
- for(var i=0;i<this.SymbolData.Data.Data.length;++i)
- {
- var item=this.SymbolData.Data.Data[i];
- drawData.Data[i]={ High:item.High, Low:item.Low };
- }
-
- return drawData;
- }
- //用法:PARTLINE(PRICE,COND1,COLOR1,COND2,COLOR2...),
- //绘制PRICE线,当COND1条件满足时,用COLOR1颜色,当COND2条件满足时,用COLOR2颜色,否则不绘制,从COLOR1之后的参数均可以省略,最多可以有10组条件
- //例如:PARTLINE(CLOSE,CLOSE>OPEN,RGB(255,0,0),CLOSE<OPEN,RGB(0,255,0),1,RGB(0,0,255))
- //表示画收盘价线,阳线时用红色,阴线时用绿色,平盘用蓝色.注意最后一个条件为1,表示前面都不满足时必然满足这个条件
- this.PARTLINE=function(args)
- {
- let drawData=[];
- let result={DrawData:drawData, DrawType:'PARTLINE'};
- if (args.length<3) return result;
- var data=args[0];
- var condition=[];
- for(var i=1;i<args.length && i+1<args.length;i+=2)
- {
- condition.push({Cond:args[i], RGB:args[i+1]});
- }
- for(var i in data)
- {
- var drawItem={Value:null, RGB:null};
- drawData[i]=drawItem;
- var value=data[i];
- if (!this.IsNumber(value)) continue;
- var rgb=null;
- for(var j in condition)
- {
- var item=condition[j];
- if (Array.isArray(item.Cond))
- {
- if (i<item.Cond.length && item.Cond[i])
- {
- rgb=item.RGB;
- break;
- }
- }
- else
- {
- if (this.IsNumber(item.Cond) && item.Cond) //单数值条件
- {
- rgb=item.RGB;
- break;
- }
- }
- }
- if (rgb)
- {
- drawItem.Value=value;
- drawItem.RGB=rgb;
- }
- }
- return result;
- }
- }
- JSDraw.prototype.CalculateDrawLine=function(lineCache)
- {
- lineCache.List=[];
- for(let i=lineCache.Start.ID; i<=lineCache.End.ID; ++i) lineCache.List.push(i);
- let height=Math.abs(lineCache.Start.Value-lineCache.End.Value);
- let width=lineCache.List.length-1;
- var result=[];
- result.push({ID:lineCache.Start.ID, Value:lineCache.Start.Value}); //第1个点
- if (lineCache.Start.Value>lineCache.End.Value)
- {
- for(let i=1;i<lineCache.List.length-1;++i)
- {
- var value=height*(lineCache.List.length-1-i)/width+lineCache.End.Value;
- result.push({ID:lineCache.List[i], Value:value});
- }
- }
- else
- {
- for(let i=1;i<lineCache.List.length-1;++i)
- {
- var value=height*i/width+lineCache.Start.Value;
- result.push({ID:lineCache.List[i], Value:value});
- }
- }
- result.push({ID:lineCache.End.ID, Value:lineCache.End.Value}); //最后一个点
- return result;
- }
- //是否有是有效的数字
- JSDraw.prototype.IsNumber = function (value)
- {
- if (value == null) return false;
- if (isNaN(value)) return false;
- return true;
- }
- //是否是整形
- JSDraw.prototype.IsInteger=function(x)
- {
- return (typeof x === 'number') && (x % 1 === 0);
- }
- JSDraw.prototype.IsDrawFunction=function(name)
- {
- let setFunctionName = new Set(
- [
- "STICKLINE", "DRAWTEXT", 'SUPERDRAWTEXT', "DRAWTEXT_FIX", 'DRAWLINE', 'DRAWBAND', "DRAWKLINE1","DRAWCOLORKLINE",
- 'DRAWKLINE', 'DRAWKLINE_IF', 'PLOYLINE', 'POLYLINE', 'DRAWNUMBER', 'DRAWNUMBER_FIX', 'DRAWICON', "ICON", "PARTLINE",
- 'DRAWRECTREL', "DRAWTEXTABS","DRAWTEXTREL", "DRAWGBK", "DRAWGBK2","DRAWGBK_DIV"
- ]);
- if (setFunctionName.has(name)) return true;
- return false;
- }
- //http://www.newone.com.cn/helpcontroller/index?code=zszy_pc
- var DYNAINFO_ARGUMENT_ID=
- {
- YCLOSE:3,
- OPEN:4,
- HIGH:5,
- LOW:6,
- CLOSE: 7,
- VOL: 8,
- AMOUNT: 10,
- AMPLITUDE:13, //振幅
- INCREASE:14, //涨幅
- EXCHANGERATE:37, //换手率
- };
- function JSSymbolData(ast,option,jsExecute)
- {
- this.AST=ast; //语法树
- this.Execute=jsExecute;
- this.Symbol='600000.sh';
- this.Name;
- this.Data=null; //个股数据
- this.SourceData = null; //不复权的个股数据
- this.MarketValue = null; //总市值
- this.Period=0; //周期
- this.Right=0; //复权
- this.DataType = 0; //默认K线数据 2=分钟走势图数据
- this.KLineApiUrl = g_JSComplierResource.Domain+"/API/KLine2"; //日线
- this.MinuteKLineApiUrl = g_JSComplierResource.Domain +'/API/KLine3'; //分钟K线
- this.RealtimeApiUrl = g_JSComplierResource.Domain +'/API/stock'; //实时行情
- this.StockHistoryDayApiUrl = g_JSComplierResource.Domain +'/API/StockHistoryDay'; //历史财务数据
- this.StockHistoryDay3ApiUrl = g_JSComplierResource.Domain +'/API/StockHistoryDay3'; //历史财务数据
- this.StockNewsAnalysisApiUrl = g_JSComplierResource.CacheDomain+'/cache/newsanalyze'; //新闻分析数据
- this.MaxRequestDataCount=1000;
- this.MaxRequestMinuteDayCount=5;
- this.KLineDateTimeRange; //请求的K线日期范围
- this.LatestData=new Map(); //最新行情
- this.IndexData; //大盘指数
- this.MarginData = new Map(); //融资融券
- this.NewsAnalysisData = new Map(); //新闻统计
- this.ExtendData = new Map(); //其他的扩展数据
- this.ScriptIndexOutData=new Map(); //调用脚本执行返回的数据
- this.OtherSymbolData=new Map(); //其他股票信息 key=symbol value=[historydata]
- //股票数据缓存 key=函数名(参数) { Data: value=拟合的数据 , Error: }
- //FinValue(id)
- this.StockData=new Map();
- this.NetworkFilter; //网络请求回调 function(data, callback);
- this.DrawInfo; //当前屏信息
- //使用option初始化
- if (option)
- {
- if (option.HQDataType) this.DataType = option.HQDataType;
- if (option.Data)
- {
- this.Data=option.Data;
- if (this.DataType != 2) //2=分钟走势图数据 没有周期和复权
- {
- this.Period=option.Data.Period; //周期
- this.Right=option.Data.Right; //复权
- }
- //this.Data=null;
- }
- if (option.SourceData) this.SourceData = option.SourceData;
- if (option.Symbol) this.Symbol=option.Symbol;
- if (option.Symbol) this.Symbol = option.Symbol;
- if (option.MaxRequestDataCount>0) this.MaxRequestDataCount=option.MaxRequestDataCount;
- if (option.MaxRequestMinuteDayCount>0) this.MaxRequestMinuteDayCount=option.MaxRequestMinuteDayCount;
- if (option.KLineApiUrl) this.KLineApiUrl=option.KLineApiUrl;
- if (option.NetworkFilter) this.NetworkFilter = option.NetworkFilter;
- if (option.DayCount>0) this.DayCount=option.DayCount;
- if (option.IsApiPeriod) this.IsApiPeriod=option.IsApiPeriod;
- if (option.Right) this.Right=option.Right;
- if (option.Period) this.Period=option.Period;
- if (option.KLineRange) this.KLineDateTimeRange=option.KLineRange;
- if (option.DrawInfo) this.DrawInfo=option.DrawInfo;
- }
- this.GetLatestDataKey=function(key)
- {
- var key=`DYNAINFO-${key}`;
- return key;
- }
- //最新行情
- this.GetLatestData=function(jobItem)
- {
- var aryArgs=this.JobArgumentsToArray(jobItem, 1);
- var lID=aryArgs[0];
- var key=this.GetLatestDataKey(lID);
- if (this.LatestData.has(key)) return this.Execute.RunNextJob();
- var self=this;
- JSNetwork.HttpRequest({
- url: self.RealtimeApiUrl,
- data:
- {
- "field": ["name","symbol","yclose","open","price","high","low","vol","amount","date","time","increase","exchangerate","amplitude"],
- "symbol": [this.Symbol]
- },
- method:"POST",
- dataType: "json",
- success: function (recvData)
- {
- self.RecvLatestData(recvData);
- self.Execute.RunNextJob();
- },
- error: function(request)
- {
- self.RecvError(request);
- }
- });
- }
- this.RecvLatestData = function (recvData)
- {
- let data=recvData.data;
- if (data.ver==2.0)
- {
- this.RecvLatestDataVer2(data);
- return;
- }
- if (!data.stock || data.stock.length!=1) return;
- let stock=data.stock[0];
- if (!stock) return;
- if (IFrameSplitOperator.IsNumber(stock.yclose)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.YCLOSE),stock.yclose);
- if (IFrameSplitOperator.IsNumber(stock.open)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.OPEN),stock.open);
- if (IFrameSplitOperator.IsNumber(stock.high)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.HIGH),stock.high);
- if (IFrameSplitOperator.IsNumber(stock.low)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.LOW),stock.low);
- if (IFrameSplitOperator.IsNumber(stock.price)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.CLOSE),stock.price);
- if (IFrameSplitOperator.IsNumber(stock.vol)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.VOL),stock.vol);
- if (IFrameSplitOperator.IsNumber(stock.amount)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.AMOUNT),stock.amount);
- if (IFrameSplitOperator.IsNumber(stock.increase)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.INCREASE),stock.increase);
- if (IFrameSplitOperator.IsNumber(stock.exchangerate)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.EXCHANGERATE),stock.exchangerate);
- if (IFrameSplitOperator.IsNumber(stock.amplitude)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.AMPLITUDE),stock.amplitude);
- /*
- this.LatestData={ Symbol:stock.symbol, Name:stock.name, Date:stock.date, Time:stock.time,
- YClose:stock.yclose,Price:stock.price, Open:stock.open, High:stock.high, Low:stock.low, Vol:stock.vol, Amount:stock.amount,
- Increase:stock.increase, Exchangerate:stock.exchangerate, Amplitude:stock.amplitude};
- */
- JSConsole.Complier.Log('[JSSymbolData::RecvLatestData] symbol, LatestData', stock.symbol, this.LatestData);
- }
- //data:[{ id:, value: }]
- this.RecvLatestDataVer2=function(recvData)
- {
- let data=recvData.data;
- if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
- var symbol=data.symbol;
- for(var i=0;i<data.data.length;++i)
- {
- var item=data.data[i];
- if (!item) continue;
- if (!IFrameSplitOperator.IsNumber(item.id)) continue;
- if (IFrameSplitOperator.IsNumber(item.value) || IFrameSplitOperator.IsString(item.value))
- {
- JSConsole.Complier.Log(`[JSSymbolData::RecvLatestDataVer2] symbol=${symbol} DYNAINFO(${item.id})=${item.value}.`);
- this.LatestData.set(this.GetLatestDataKey(item.id), item.value);
- }
-
- }
- JSConsole.Complier.Log('[JSSymbolData::RecvLatestDataVer2]', this.LatestData);
- }
- this.GetLatestCacheData=function(dataID)
- {
- var key=this.GetLatestDataKey(dataID);
- if (!this.LatestData.has(key)) return null;
- var data=this.LatestData.get(key);
- //DYNAINFO(36) 自由流通换手率(序列数据,每个周期的数据不同,使用最新的自由流通股本) 转换成幅度需要乘100 比如DYNAINFO(36)>0.25表示换手超过25%
- //DYNAINFO(37) 换手率(序列数据,每个周期的数据不同,使用的流通股本为最近数据) 转换成幅度需要乘100 比如DYNAINFO(37)>0.1表示换手超过10%
- if (dataID==37 || dataID==36)
- {
- var value=null;
- if (IFrameSplitOperator.IsNumber(data)) value=data;
- else if (IFrameSplitOperator.IsNonEmptyArray(data) && IFrameSplitOperator.IsNumber(data[0])) value=data[0];
- else return null;
- if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null;
-
- var aryData=[];
- for(var i=0;i<this.Data.Data.length;++i)
- {
- var kItem=this.Data.Data[i];
- aryData[i]=null;
- if (!kItem || !IFrameSplitOperator.IsNumber(kItem.Vol)) continue;
- aryData[i]=kItem.Vol/value*100.0;// 换手率
- }
- return aryData;
- }
-
- return data;
- }
- this.GetDynaCacheData=function(name)
- {
- if (MAP_DYNAINFO_SHORTCUT.has(name))
- {
- var item=MAP_DYNAINFO_SHORTCUT.get(name);
- return this.GetLatestCacheData(item.ID);
- }
- return null;
- }
- this.GetVolRateData = function (job, node)
- {
- var volrKey = job.ID.toString() + '-VolRate-' + this.Symbol;
- if (this.ExtendData.has(volrKey)) return this.Execute.RunNextJob();
- var self=this;
- var dayCount=30;
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var dayCount=1;
- if (this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) dayCount=this.DayCount;
- var obj=
- {
- Name:'JSSymbolData::GetVolRateData', //类名:: 函数
- Explain:'分时量比数据(成交量)',
- Request:
- {
- Url:self.KLineApiUrl, Type:'POST' ,
- Data: { symbol:self.Symbol, dayCount:dayCount, field: ["name","symbol","vol"], period:0, right:0, dateRange:dateRange }
- },
- Self:this,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(recvData)
- {
- self.RecvVolRateData(recvData,volrKey);
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
- }
- JSNetwork.HttpRequest({
- url: self.KLineApiUrl,
- data:
- {
- "field": ["name","symbol","vol"],
- "symbol": self.Symbol,
- "start": -1,
- "count": dayCount
- },
- type:"post",
- dataType: "json",
- async:true,
- success: function (recvData)
- {
- self.RecvVolRateData(recvData,volrKey);
- self.Execute.RunNextJob();
- },
- error: function(request)
- {
- self.RecvError(request);
- }
- });
- }
- this.RecvVolRateData = function (recvData, key)
- {
- var data=recvData.data;
- var sumVol=0,avgVol5=0;
- var mapAvgVol5=new Map();
- if (data.Ver==2.0) // {Ver:2.0 , data:[ [日期,5日vol均值]] }
- {
- if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
- for(var i=0;i<data.data.length;++i)
- {
- var item=data.data[i];
- if (!IFrameSplitOperator.IsNonEmptyArray(item)) continue;
- if (item.length<2) continue;
- if (IFrameSplitOperator.IsNumber(item[0]) && IFrameSplitOperator.IsPlusNumber(item[1]))
- {
- mapAvgVol5.set(item[0],{ AvgVol5:item[1] } );
- }
- }
- }
- else
- {
- if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
- var minuteCount=241;
- if (IFrameSplitOperator.IsNumber(data.minutecount)) minuteCount=data.minutecount;
- for(var i=0,j=0,dayCount=0;i<data.data.length;++i) //每天的5日成交均量
- {
- sumVol=0;
- for(j=i,dayCount=0;j>=0 && dayCount<5;--j, ++dayCount)
- {
- var item=data.data[j];
- if (IFrameSplitOperator.IsNumber(item[6]))
- sumVol+=item[6];
- }
-
- if (dayCount>0)
- {
- avgVol5=sumVol/dayCount/minuteCount;
- var item=data.data[i];
- mapAvgVol5.set(item[0],
- {
- //for debug
- //Vol5:sumVol, MinuteCount:minuteCount,,Count:dayCount,
- AvgVol5:avgVol5
- } );
- }
- }
- }
-
- if (mapAvgVol5.size>0) this.ExtendData.set(key,mapAvgVol5);
- JSConsole.Complier.Log('[JSSymbolData::RecvVolRateData]', mapAvgVol5);
- }
- this.GetVolRateCacheData=function(node)
- {
- var key=JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA.toString()+'-VolRate-'+this.Symbol;
- if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node,'不支持VOLR');
- var result=[];
- var mapAvgVol5=this.ExtendData.get(key);
- var totalVol=0, preDate=0, avgVol5=null;
- for(var i=0, j=0;i<this.Data.Data.length;++i)
- {
- result[i]=null;
- var item=this.Data.Data[i];
- if (preDate!=item.Date)
- {
- avgVol5=null;
- j=0;
- totalVol=0;
- if (mapAvgVol5.has(item.Date))
- {
- var volItem=mapAvgVol5.get(item.Date);
- avgVol5=volItem.AvgVol5;
- }
-
- preDate=item.Date;
- }
- if (avgVol5==null) continue;
- totalVol+=item.Vol;
- result[i]=totalVol/(j+1)/avgVol5*100;
- ++j;
- }
- return result;
- }
- this.GetOtherSymbolParam=function(name)
- {
- var args=name.split("$");
- var setStockDataName=new Set(['CLOSE',"C",'VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT','AMO','VOLINSTK']);
- if (!setStockDataName.has(args[1])) return null;
-
- var symbol=args[0];
- if (symbol.length==6)
- {
- if (symbol[0]=="6" || symbol[0]=="5" || symbol[0]=="8" || symbol[0]=="9")
- symbol+=".SH";
- else if (symbol[0]=='0' || symbol[0]=='1' || symbol[0]=='2' || symbol[0]=='3')
- symbol+='.SZ';
- }
- else if (symbol.indexOf("SZ")==0)
- {
- symbol=symbol.substr(2)+".SZ";
- }
- else if (symbol.indexOf("SH")==0)
- {
- symbol=symbol.substr(2)+".SH";
- }
- else if (symbol.indexOf("_")>0)
- {
- var arySymbol=symbol.split("_");
- symbol=`${arySymbol[1]}.${arySymbol[0]}`;
- }
- else
- return null;
- return { Symbol:symbol.toLowerCase(), DataName:args[1] };
-
- }
- //获取其他股票数据
- this.GetOtherSymbolData=function(job)
- {
- var symbol=this.Symbol;
- if (job.Literal)
- {
- var args=this.GetOtherSymbolParam(job.Literal.toUpperCase());
- if (!args)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.Literal} Error.`);
- }
- symbol=args.Symbol;
- }
- else
- {
- var args=job.Args;
- if (args.length>0)
- {
- var item=args[0];
- if (item.Type==Syntax.Literal)
- {
- symbol=item.Value;
- }
- else if (item.Type==Syntax.Identifier) //变量 !!只支持默认的变量值
- {
- var isFind=false;
- for(var j in this.Arguments)
- {
- const argItem=this.Arguments[j];
- if (argItem.Name==item.Name)
- {
- symbol=argItem.Value;
- isFind=true;
- break;
- }
- }
-
- if (!isFind)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: can't read ${item.Name}`);
- }
- }
- }
- }
-
- job.Symbol=symbol.toLowerCase();
- if (job.Symbol==this.Symbol) return this.Execute.RunNextJob();
- if (this.OtherSymbolData.has(job.Symbol)) return this.Execute.RunNextJob();
- var self=this;
- if (this.DataType==HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
- {
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var obj=
- {
- Name:'JSSymbolData::GetOtherSymbolData', //类名::函数名
- Explain:'指定个股数据',
- Request:
- {
- Data:
- {
- symbol:job.Symbol,
- right:self.Right,
- period:self.Period,
- dateRange:dateRange
- }
- },
- Self:this,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(data)
- {
- self.RecvOtherSymbolKData(data,job);
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
- }
- JSNetwork.HttpRequest({
- url: self.KLineApiUrl,
- data:
- {
- "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
- "symbol": job.Symbol,
- "start": -1,
- "count": self.MaxRequestDataCount+500 //多请求2年的数据 确保股票剔除停牌日期以后可以对上
- },
- method: "POST",
- dataType: "json",
- async:true,
- success: function (recvData)
- {
- self.RecvOtherSymbolKDayData(recvData,job);
- self.Execute.RunNextJob();
- },
- error: function(request)
- {
- self.RecvError(request);
- }
- });
- }
- else if (ChartData.IsMinutePeriod(this.Period, true) || this.DataType==HQ_DATA_TYPE.MINUTE_ID || this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) //请求分钟数据
- {
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var obj=
- {
- Name:'JSSymbolData::GetOtherSymbolData', //类名::函数名
- Explain:'指定个股数据',
- Request:
- {
- Data:
- {
- symbol:job.Symbol,
- right:self.Right,
- period:self.Period,
- dateRange:dateRange
- }
- },
- Self:this,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(data)
- {
- self.RecvOtherSymbolKData(data,job);
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
- }
- JSNetwork.HttpRequest({
- url: self.MinuteKLineApiUrl,
- data:
- {
- "field": ["name","symbol","yclose","open","price","high","low","vol"],
- "symbol": job.Symbol,
- "start": -1,
- "count": self.MaxRequestMinuteDayCount+5
- },
- method: "POST",
- dataType: "json",
- async:true,
- success: function (data)
- {
- self.RecvOtherSymbolKMinuteData(data,job);
- self.Execute.RunNextJob();
- },
- error: function(request)
- {
- self.RecvError(request);
- }
- });
- }
- }
- //第3方数据对接
- this.RecvOtherSymbolKData=function(recvData,job)
- {
- var data=recvData.data;
- JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKData] recv data' , data);
- var kData=new ChartData();
- var hisData=null;
- var period=this.Period;
- if (this.DataType==HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //日线数据
- {
- hisData=this.JsonDataToHistoryData(data);
- kData.DataType=0;
- }
- else //分钟线数据
- {
- hisData=this.JsonDataToMinuteHistoryData(data);
- kData.DataType=1;
- //走势图使用1分钟K线模式
- if (this.DataType==HQ_DATA_TYPE.MINUTE_ID || this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID)
- period=4;
- }
-
- kData.Period=this.Period;
- kData.Right=this.Right;
- kData.Data=this.Data.FixKData(hisData,period);
- this.OtherSymbolData.set(job.Symbol, kData);
- }
- this.RecvOtherSymbolKDayData=function(recvData,job)
- {
- var data=recvData.data;
- JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKDayData] recv data' , data);
- let hisData=this.JsonDataToHistoryData(data);
- var kData=new ChartData();
- kData.DataType=0; //日线数据
- kData.Data=hisData;
- var aryOverlayData=this.SourceData.GetOverlayData(kData.Data); //和主图数据拟合以后的数据
- kData.Data=aryOverlayData;
- if (ChartData.IsDayPeriod(this.Period,false)) //周期数据
- {
- let periodData=kData.GetPeriodData(this.Period);
- kData.Data=periodData;
- }
- this.OtherSymbolData.set(job.Symbol, kData);
- }
- this.RecvOtherSymbolKMinuteData=function(recvData, job)
- {
- var data=recvData.data;
- JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKMinuteData] recv data' , data);
- let hisData=this.JsonDataToMinuteHistoryData(data);
- var kData=new ChartData();
- kData.DataType=1; /*分钟线数据 */
- kData.Data=hisData;
- if (ChartData.IsMinutePeriod(this.Period,false)) //周期数据
- {
- let periodData=kData.GetPeriodData(this.Period);
- kData.Data=periodData;
- }
- this.OtherSymbolData.set(job.Symbol, kData);
- }
- this.GetOtherSymolCacheData=function(obj)
- {
- var symbol,dataName;
- if (obj.FunctionName)
- {
- dataName=obj.FunctionName;
- var args=obj.Args;
- if (args.length<=0) return this.GetSymbolCacheData(dataName);
- symbol=args[0].toString().toLowerCase();
- }
- else if (obj.Literal)
- {
- var args=this.GetOtherSymbolParam(obj.Literal.toUpperCase());
- if (!args) return [];
- symbol=args.Symbol;
- dataName=args.DataName;
- }
-
- if (symbol==this.Symbol) return this.GetSymbolCacheData(dataName);
- if (!this.OtherSymbolData.has(symbol)) return [];
- var kData=this.OtherSymbolData.get(symbol);
- var upperSymbol=symbol.toUpperCase();
- switch(dataName)
- {
- case 'CLOSE':
- case 'C':
- return kData.GetClose();
- case 'VOL':
- case 'V':
- return kData.GetVol(MARKET_SUFFIX_NAME.GetVolUnit(upperSymbol));
- case 'OPEN':
- case 'O':
- return kData.GetOpen();
- case 'HIGH':
- case 'H':
- return kData.GetHigh();
- case 'LOW':
- case 'L':
- return kData.GetLow();
- case 'AMOUNT':
- case 'AMO':
- return kData.GetAmount();
- case 'VOLINSTK':
- return kData.GetPosition();
- }
- }
- //获取大盘指数数据
- this.GetIndexData=function()
- {
- if (this.IndexData) return this.Execute.RunNextJob();
- var self=this;
- if (JSCommonData.ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
- {
- JSNetwork.HttpRequest({
- url: self.KLineApiUrl,
- data:
- {
- "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", 'up', 'down', 'stop', 'unchanged'],
- "symbol": '000001.sh',
- "start": -1,
- "count": self.MaxRequestDataCount+500 //多请求2年的数据 确保股票剔除停牌日期以后可以对上
- },
- method: 'POST',
- dataType: "json",
- success: function (recvData)
- {
- self.RecvIndexHistroyData(recvData);
- self.Execute.RunNextJob();
- },
- error: function(request)
- {
- self.RecvError(request);
- }
- });
- }
- else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true)) //请求分钟数据
- {
- JSNetwork.HttpRequest({
- url: self.MinuteKLineApiUrl,
- data:
- {
- "field": ["name","symbol","yclose","open","price","high","low","vol"],
- "symbol": '000001.sh',
- "start": -1,
- "count": self.MaxRequestMinuteDayCount+5
- },
- method: 'POST',
- dataType: "json",
- success: function (data)
- {
- self.RecvIndexMinuteHistroyData(data);
- self.Execute.RunNextJob();
- },
- error: function(request)
- {
- self.RecvError(request);
- }
- });
- }
- }
- this.RecvIndexHistroyData=function(recvData)
- {
- let data = recvData.data;
- JSConsole.Complier.Log('[JSSymbolData::RecvIndexHistroyData] recv data' , data);
- let hisData=this.JsonDataToHistoryData(data);
- this.IndexData = new JSCommonData.ChartData();
- this.IndexData.DataType=0; /*日线数据 */
- this.IndexData.Data=hisData;
- var aryOverlayData = this.SourceData.GetOverlayData(this.IndexData.Data); //和主图数据拟合以后的数据
- this.IndexData.Data=aryOverlayData;
- if (JSCommonData.ChartData.IsDayPeriod(this.Period, false)) //周期数据
- {
- let periodData=this.IndexData.GetPeriodData(this.Period);
- this.IndexData.Data=periodData;
- }
- }
- this.RecvIndexMinuteHistroyData = function (recvData)
- {
- let data = recvData.data;
- JSConsole.Complier.Log('[JSSymbolData::RecvIndexMinuteHistroyData] recv data' , data);
- let hisData=this.JsonDataToMinuteHistoryData(data);
- this.IndexData = new JSCommonData.ChartData();
- this.IndexData.DataType=1; /*分钟线数据 */
- this.IndexData.Data=hisData;
- if (JSCommonData.ChartData.IsMinutePeriod(this.Period, false)) //周期数据
- {
- let periodData=this.IndexData.GetPeriodData(this.Period);
- this.IndexData.Data=periodData;
- }
- }
- //获取大盘指数缓存数据
- this.GetIndexCacheData=function(dataName)
- {
- if (!this.IndexData) return new Array();
- switch(dataName)
- {
- case 'INDEXA':
- return this.IndexData.GetAmount();
- case 'INDEXC':
- return this.IndexData.GetClose();
- case 'INDEXH':
- return this.IndexData.GetHigh();
- case 'INDEXL':
- return this.IndexData.GetLow();
- case 'INDEXO':
- return this.IndexData.GetOpen();
- case 'INDEXV':
- return this.IndexData.GetVol();
- case 'INDEXADV':
- return this.IndexData.GetUp();
- case 'INDEXDEC':
- return this.IndexData.GetDown();
- }
- }
- //分钟涨幅股票个数统计数据下载
- this.GetIndexIncreaseData = function (job)
- {
- var upKey = job.ID.toString() + '-UpCount-' + job.Symbol;
- var downKey = job.ID.toString() + '-DownCount-' + job.Symbol;
- if (this.ExtendData.has(upKey) && this.ExtendData.has(downKey)) return this.Execute.RunNextJob();
- var symbol = job.Symbol;
- symbol = symbol.replace('.CI', '.ci');
- var self = this;
- var apiUrl = g_JSComplierResource.CacheDomain + '/cache/analyze/increaseanalyze/' + symbol + '.json';
- JSConsole.Complier.Log('[JSSymbolData::GetIndexIncreaseData] Get url=', apiUrl);
- JSNetwork.HttpRequest({
- url: apiUrl,
- method: "GET",
- dataType: "json",
- success: function (data)
- {
- self.RecvMinuteIncreaseData(data, { UpKey: upKey, DownKey: downKey });
- self.Execute.RunNextJob();
- },
- error: function (request)
- {
- self.RecvError(request);
- }
- });
- }
- this.RecvMinuteIncreaseData = function (recvData, key)
- {
- JSConsole.Complier.Log('[JSSymbolData::RecvMinuteIncreaseData] recv data', recvData);
- var data=recvData.data;
- if (!data.minute) return;
- var minuteData = data.minute;
- if (!minuteData.time || !minuteData.up || !minuteData.down) return;
- var upData = [], downData = [];
- for (var i = 0; i < minuteData.time.length; ++i) {
- upData[i] = minuteData.up[i];
- downData[i] = minuteData.down[i];
- }
- this.ExtendData.set(key.UpKey, upData);
- this.ExtendData.set(key.DownKey, downData);
- }
- //分钟涨幅股票个数统计数据
- this.GetIndexIncreaseCacheData = function (funcName, symbol, node) {
- var key;
- if (funcName == 'UPCOUNT') key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA.toString() + '-UpCount-' + symbol;
- else if (funcName == 'DOWNCOUNT') key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA.toString() + '-DownCount-' + symbol;
- if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node, '不支持函数' + funcName + '(' + symbol + ')');
- return this.ExtendData.get(key);
- }
- this.GetSymbolData=function()
- {
- if (this.Data) return this.Execute.RunNextJob();
-
- let self=this;
- if (this.DataType === 2) //当天分钟数据
- {
- JSNetwork.HttpRequest({
- url: self.RealtimeApiUrl,
- data:
- {
- "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", "amount", "date", "minute", "time", "minutecount"],
- "symbol": [self.Symbol],
- "start": -1
- },
- method: 'POST',
- dataType: "json",
- async: true,
- success: function (recvData) {
- self.RecvMinuteData(recvData);
- self.Execute.RunNextJob();
- }
- });
- return;
- }
- if (JSCommonData.ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
- {
- if (this.NetworkFilter)
- {
- var obj=
- {
- Name:'JSSymbolData::GetSymbolData',
- Explain:"日线数据",
- Request:
- { Url:self.RealtimeApiUrl, Type:'POST' ,
- Data:
- {
- "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
- "symbol": self.Symbol,
- "start": -1,
- "count": self.MaxRequestDataCount,
- "period":this.Period,
- "right":this.Right
- }
- },
- Self:this,
- PreventDefault:false
- };
- if (this.KLineDateTimeRange)
- {
- obj.Request.KLineDataTimeRange={Start:{ Date:this.KLineDateTimeRange.Start.Date}, End:{ Date:this.KLineDateTimeRange.End.Date} };
- if (this.IsNumber(this.KLineDateTimeRange.Start.Time)) obj.Request.KLineDataTimeRange.Start.Time=this.KLineDateTimeRange.Start.Time;
- if (this.IsNumber(this.KLineDateTimeRange.End.Time)) obj.Request.KLineDataTimeRange.End.Time=this.KLineDateTimeRange.End.Time;
- }
- this.NetworkFilter(obj, function(data)
- {
- self.RecvHistroyData(data);
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
- }
- JSNetwork.HttpRequest({
- url: self.KLineApiUrl,
- data:
- {
- "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
- "symbol": self.Symbol,
- "start": -1,
- "count": self.MaxRequestDataCount
- },
- method: 'POST',
- dataType: "json",
- async:true,
- success: function (recvData)
- {
- self.RecvHistroyData(recvData);
- self.Execute.RunNextJob();
- },
- error: function(request)
- {
- self.RecvError(request);
- }
- });
- }
- else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true)) //请求分钟数据
- {
- if (this.NetworkFilter)
- {
- var obj=
- {
- Name:'JSSymbolData::GetSymbolData',
- Explain:"分钟K线数据",
- Request:
- { Url:self.MinuteKLineApiUrl, Type:'POST' ,
- Data:
- {
- "field": ["name","symbol","yclose","open","price","high","low","vol"],
- "symbol": self.Symbol,
- "start": -1,
- "count": self.MaxRequestMinuteDayCount,
- "period":this.Period,
- "right":this.Right
- }
- },
- Self:this,
- PreventDefault:false
- };
- if (this.KLineDateTimeRange)
- {
- obj.Request.KLineDataTimeRange={Start:{ Date:this.KLineDateTimeRange.Start.Date}, End:{ Date:this.KLineDateTimeRange.End.Date} };
- if (this.IsNumber(this.KLineDateTimeRange.Start.Time)) obj.Request.KLineDataTimeRange.Start.Time=this.KLineDateTimeRange.Start.Time;
- if (this.IsNumber(this.KLineDateTimeRange.End.Time)) obj.Request.KLineDataTimeRange.End.Time=this.KLineDateTimeRange.End.Time;
- }
- this.NetworkFilter(obj, function(data)
- {
- self.RecvMinuteHistroyData(data);
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
- }
- JSNetwork.HttpRequest({
- url: this.MinuteKLineApiUrl,
- data:
- {
- "field": ["name","symbol","yclose","open","price","high","low","vol"],
- "symbol": self.Symbol,
- "start": -1,
- "count": self.MaxRequestMinuteDayCount
- },
- method: 'POST',
- dataType: "json",
- async:true,
- success: function (data)
- {
- self.RecvMinuteHistroyData(data);
- self.Execute.RunNextJob();
- },
- error: function(request)
- {
- self.RecvError(request);
- }
- });
- }
- }
- this.RecvHistroyData=function(recvData)
- {
- let data=recvData.data;
- JSConsole.Complier.Log('[JSSymbolData::RecvHistroyData] recv data' , data);
- let hisData=this.JsonDataToHistoryData(data);
- this.Data=new JSCommonData.ChartData();
- this.Data.DataType=0; /*日线数据 */
- this.Data.Data=hisData;
- this.SourceData = new JSCommonData.ChartData;
- this.SourceData.Data = hisData;
- if (this.IsApiPeriod) //后台周期 前端不处理
- {
- }
- else
- {
- if (this.Right>0) //复权
- {
- let rightData=this.Data.GetRightDate(this.Right);
- this.Data.Data=rightData;
- }
-
- if (JSCommonData.ChartData.IsDayPeriod(this.Period, false)) //周期数据
- {
- let periodData=this.Data.GetPeriodData(this.Period);
- this.Data.Data=periodData;
- }
- }
-
- this.Data.Right=this.Right;
- this.Data.Period=this.Period;
- this.Name = data.name;
- }
- this.RecvMinuteHistroyData = function (recvData)
- {
- let data = recvData.data;
- JSConsole.Complier.Log('[JSSymbolData::RecvMinuteHistroyData] recv data' , data);
- let hisData=this.JsonDataToMinuteHistoryData(data);
- this.Data = new JSCommonData.ChartData();
- this.Data.DataType=1; /*分钟线数据 */
- this.Data.Data=hisData;
- this.SourceData = new JSCommonData.ChartData;
- this.SourceData.Data = hisData;
- if (this.IsApiPeriod) //后台周期 前端不处理
- {
- }
- else
- {
- if (JSCommonData.ChartData.IsMinutePeriod(this.Period, false)) //周期数据
- {
- let periodData=this.Data.GetPeriodData(this.Period);
- this.Data.Data=periodData;
- }
- }
-
- this.Data.Period=this.Period;
- this.Name = data.name;
- }
- //最新的分钟数据走势图
- this.RecvMinuteData = function (recvData)
- {
- let data = recvData.data;
- JSConsole.Complier.Log('[JSSymbolData::RecvMinuteData] recv data', data);
- var aryMinuteData = this.JsonDataToMinuteData(data);
- this.Data = new JSCommonData.ChartData();
- this.Data.DataType = 2; /*分钟走势图数据 */
- this.Data.Data = aryMinuteData;
- this.Name = data.stock[0].name;
- }
- this.GetSymbolCacheData=function(dataName)
- {
- if (!this.Data) return new Array();
- var upperSymbol=this.Symbol.toUpperCase();
- switch(dataName)
- {
- case 'CLOSE':
- case 'C':
- return this.Data.GetClose();
- case 'VOL':
- case 'V':
- return this.Data.GetVol(MARKET_SUFFIX_NAME.GetVolUnit(upperSymbol));
- case 'OPEN':
- case 'O':
- return this.Data.GetOpen();
- case 'HIGH':
- case 'H':
- return this.Data.GetHigh();
- case 'LOW':
- case 'L':
- return this.Data.GetLow();
- case 'AMOUNT':
- case 'AMO':
- return this.Data.GetAmount();
- case "OPI": //文华 持仓量
- case 'VOLINSTK':
- return this.Data.GetPosition();
- case "ZSTJJ": //均价
- return this.Data.GetAvPrice();
-
- case "SETTLE": //文华 结算价
- case "QHJSJ": //通达信 结算价
- return this.Data.GetSettlementPrice(); //结算价
- case "ISEQUAL": //平盘
- return this.Data.GetIsEqual();
- case "ISUP": //收阳
- return this.Data.GetIsUp();
- case "ISDOWN": //收阴
- return this.Data.GetIsDown();
- }
- }
- this.GetCurrBarsCount=function()
- {
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return new Array();
- let lCount=this.Data.Data.length;
- let result=[];
- for(let i=lCount-1;i>=0;--i)
- result.push(i);
- return result;
- }
- this.GetTotalBarsCount=function()
- {
- let lCount=this.Data.Data.length;
- return lCount;
- }
- this.GetTotalTradeMinuteCount=function()
- {
- var data=g_MinuteCoordinateData.GetCoordinateData(this.Symbol);
- if (data && data.Count>0) return data.Count-1;
- return 242;
- }
- //BARPOS 返回从第一根K线开始到当前的周期数。
- //注:
- //1、BARPOS返回本地已有的K线根数,从本机上存在的数据开始算起。
- //2、本机已有的第一根K线上返回值为1。
- this.GetBarPos=function()
- {
- let result=[];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- let lCount=this.Data.Data.length;
- for(let i=0;i<lCount;++i)
- result.push(i+1);
- return result;
- }
- this.GetIsLastBar = function ()
- {
- let result = [];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result
- let lCount = this.Data.Data.length;
- for (let i = 0; i < lCount; ++i)
- {
- if (i == lCount - 1) result.push(1);
- else result.push(0);
- }
- return result;
- }
- //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置.
- //例如:BARSTATUS=2表示当天是该数据的最后一个周期.
- this.GetBarStatus=function()
- {
- let result=[];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result
- let lCount=this.Data.Data.length;
- for(var i=0 ;i<lCount;++i)
- {
- if (i==0) result[i]=1;
- else if (i==lCount-1) result[i]=2;
- else result[i]=0;
- }
- return result;
- }
- //融资融券函数
- this.GetMarginCacheData = function (id, node)
- {
- let jobID = JS_EXECUTE_JOB_ID.GetMarginJobID(id);
- if (!jobID) this.Execute.ThrowUnexpectedNode(node, '不支持MARGIN(' + id + ')');
- if (this.MarginData.has(jobID)) return this.MarginData.get(jobID);
- return [];
- }
- //下融资融券
- this.GetMarginData = function (jobID)
- {
- if (this.MarginData.has(jobID)) return this.Execute.RunNextJob();
- JSConsole.Complier.Log('[JSSymbolData::GetMarginData] jobID=', jobID);
- var self = this;
- let fieldList = ["name", "date", "symbol"];
- switch (jobID)
- {
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE: //融资融券余额
- fieldList.push("margin.balance");
- break;
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE: //融资占比
- fieldList.push("margin.rate");
- break;
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
- fieldList.push("margin.buy");
- break;
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
- fieldList.push("margin.sell");
- break;
- }
- //请求数据
- JSNetwork.HttpRequest({
- url: this.StockHistoryDayApiUrl,
- data:
- {
- "field": fieldList,
- "symbol": [this.Symbol],
- "orderfield": "date"
- },
- method: 'POST',
- dataType: "json",
- async: true,
- success: function (recvData) {
- self.RecvMarginData(recvData, jobID);
- self.Execute.RunNextJob();
- }
- });
- }
- this.RecvMarginData = function (recvData, jobID)
- {
- var data = recvData.data;
- //JSConsole.Complier.Log(data);
- if (!data.stock || data.stock.length != 1) return;
- let stock = data.stock[0];
- var aryData = new Array();
- var aryData2 = [], aryData3 = [], aryData4 = []; //其他3个数据
- for (let i in stock.stockday)
- {
- var item = stock.stockday[i];
- var marginData = item.margin;
- if (!marginData) continue;
- let indexData = new JSCommonData.SingleData();
- indexData.Date = item.date;
- switch (jobID)
- {
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE:
- if (!this.IsNumber(marginData.balance)) continue;
- indexData.Value = marginData.balance; //融资融券余额
- aryData.push(indexData);
- break;
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE:
- if (!this.IsNumber(marginData.rate)) continue;
- indexData.Value = marginData.rate; //融资占比
- aryData.push(indexData);
- break;
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
- var buyData = marginData.buy;
- if (!buyData) continue;
- if (!this.IsNumber(buyData.balance) || !this.IsNumber(buyData.amount) || !this.IsNumber(buyData.repay) || !this.IsNumber(buyData.net)) continue;
- indexData.Value = buyData.balance;
- var indexData2 = new JSCommonData.SingleData();
- indexData2.Date = item.date;
- indexData2.Value = buyData.amount;
- var indexData3 = new JSCommonData.SingleData();
- indexData3.Date = item.date;
- indexData3.Value = buyData.repay;
- var indexData4 = new JSCommonData.SingleData();
- indexData4.Date = item.date;
- indexData4.Value = buyData.net;
- aryData.push(indexData);
- aryData2.push(indexData2);
- aryData3.push(indexData3);
- aryData4.push(indexData4);
- break;
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
- var sellData = marginData.sell;
- if (!sellData) continue;
- if (!this.IsNumber(sellData.balance) || !this.IsNumber(sellData.volume) || !this.IsNumber(sellData.repay) || !this.IsNumber(sellData.net)) continue;
- indexData.Value = buyData.balance;
- var indexData2 = new JSCommonData.SingleData();
- indexData2.Date = item.date;
- indexData2.Value = buyData.volume;
- var indexData3 = new JSCommonData.SingleData();
- indexData3.Date = item.date;
- indexData3.Value = buyData.repay;
- var indexData4 = new JSCommonData.SingleData();
- indexData4.Date = item.date;
- indexData4.Value = buyData.net;
- aryData.push(indexData);
- aryData2.push(indexData2);
- aryData3.push(indexData3);
- aryData4.push(indexData4);
- break;
- default:
- continue;
- }
- }
- var allData = [];
- if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE)
- {
- allData.push({ JobID: jobID, Data: aryData });
- }
- else if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT ||
- jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET)
- {
- allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE, Data: aryData });
- allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT, Data: aryData2 });
- allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY, Data: aryData3 });
- allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET, Data: aryData4 });
- }
- else if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME ||
- jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET)
- {
- allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE, Data: aryData });
- allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME, Data: aryData2 });
- allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY, Data: aryData3 });
- allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET, Data: aryData4 });
- }
- for (let i in allData)
- {
- let aryFixedData = this.Data.GetFittingData(allData[i].Data);
- var bindData = new JSCommonData.ChartData();
- bindData.Data = aryFixedData;
- bindData.Period = this.Period; //周期
- if (bindData.Period > 0) //周期数据
- {
- var periodData = bindData.GetPeriodSingleData(bindData.Period);
- bindData.Data = periodData;
- }
- let data = bindData.GetValue();
- this.MarginData.set(allData[i].JobID, data);
- }
- }
- this.GetNewsAnalysisCacheData = function (id, node)
- {
- let jobID = JS_EXECUTE_JOB_ID.GetNewsAnalysisID(id);
- if (!jobID) this.Execute.ThrowUnexpectedNode(node, '不支持NEWS(' + id + ')');
- if (this.NewsAnalysisData.has(jobID)) return this.NewsAnalysisData.get(jobID);
- return [];
- }
- //下载新闻统计
- this.GetNewsAnalysisData = function (jobID)
- {
- if (this.NewsAnalysisData.has(jobID)) return this.Execute.RunNextJob();
- var self = this;
- var mapFolder = new Map([
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE, "negative"],
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH, 'research'],
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT, 'interact'],
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE, 'holderchange'], //NEWS(4) 股东增持
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2, 'holderchange'], //NEWS(5) 股东减持
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER, 'trustholder'], //NEWS(6) 信托持股
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING, 'Blocktrading'], //NEWS(7) 大宗交易
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS, 'companynews'], //NEWS(8) 官网新闻
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS, 'topmanagers'], //NEWS(9) 高管要闻
- [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE, 'Pledge'], //NEWS(10) 股权质押
- ]);
- if (!mapFolder.has(jobID))
- {
- this.Execute.RunNextJob();
- return;
- }
- var folderName = mapFolder.get(jobID);
- var url = this.StockNewsAnalysisApiUrl + '/' + folderName + '/' + this.Symbol + '.json';
- //请求数据
- JSNetwork.HttpRequest({
- url: url,
- method: 'GET',
- dataType: "json",
- async: true,
- success: function (recvData)
- {
- if (recvData.statusCode==200)
- self.RecvNewsAnalysisData(recvData, jobID);
- else
- self.RecvNewsAnalysisDataError(recvData, jobID);
- self.Execute.RunNextJob();
- },
- fail: function (request, textStatus)
- {
- //self.RecvNewsAnalysisDataError(request, textStatus, jobID);
- self.Execute.RunNextJob();
- }
- });
- }
- this.RecvNewsAnalysisDataError = function (recvData, jobID)
- {
- JSConsole.Complier.Log('[JSSymbolData::RecvNewsAnalysisDataError] request error.', recvData.statusCode);
- //没有新闻使用0数据填充
- var aryData = [];
- for (var i = 0; i < this.Data.Data.length; ++i)
- {
- var item = new JSCommonData.SingleData();
- item.Date = this.Data.Data[i].Date;
- item.Value = 0
- aryData.push(item);
- }
- var bindData = new JSCommonData.ChartData();
- bindData.Data = aryData;
- this.NewsAnalysisData.set(jobID, bindData.GetValue());
- }
- this.RecvNewsAnalysisData = function (recvData, jobID)
- {
- var data=recvData.data;
- if (!data.data || !data.date) return;
- if (data.data.length <= 0 || data.data.length != data.date.length) return;
- JSConsole.Complier.Log('[JSSymbolData::RecvNewsAnalysisData] jobID', jobID, data.update);
- if (jobID == JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE || jobID == JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2)
- {
- var aryData = [], aryData2 = [];
- for (var i = 0; i < data.data.length; ++i)
- {
- var item = new JSCommonData.SingleData();
- item.Date = data.date[i];
- item.Value = data.data[i];
- if (this.IsNumber(item.Value)) aryData.push(item);
- if (i < data.data2.length)
- {
- item = new JSCommonData.SingleData();
- item.Date = data.date[i];
- item.Value = data.data2[i];
- if (this.IsNumber(item.Value)) aryData2.push(item);
- }
- }
- let aryFixedData = this.Data.GetFittingData2(aryData, 0);
- var bindData = new JSCommonData.ChartData();
- bindData.Data = aryFixedData;
- this.NewsAnalysisData.set(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE, bindData.GetValue());
- aryFixedData = this.Data.GetFittingData2(aryData2, 0);
- bindData = new JSCommonData.ChartData();
- bindData.Data = aryFixedData;
- this.NewsAnalysisData.set(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2, bindData.GetValue());
- }
- else
- {
- var aryData = [];
- for (var i = 0; i < data.data.length; ++i)
- {
- var item = new JSCommonData.SingleData();
- item.Date = data.date[i];
- item.Value = data.data[i];
- aryData.push(item);
- }
- let aryFixedData = this.Data.GetFittingData2(aryData, 0);
- var bindData = new JSCommonData.ChartData();
- bindData.Data = aryFixedData;
- this.NewsAnalysisData.set(jobID, bindData.GetValue());
- }
- }
- this.GetStockDataKey=function(jobItem, aryArgs)
- {
- var key=jobItem.FunctionName;
- if (aryArgs.length>0)
- {
- key+="(";
- for(var i=0;i<aryArgs.length;++i)
- {
- if (i>0) key+=",";
- key+=aryArgs[i].toString();
- }
- key+=")";
- }
- return key;
- }
- this.GetFinance=function(jobItem)
- {
- var aryArgs=this.JobArgumentsToArray(jobItem, 1);
- var lID=aryArgs[0];
- var key=this.GetStockDataKey(jobItem,aryArgs);
- if (this.StockData.has(key)) return this.Execute.RunNextJob();
- var self=this;
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var obj=
- {
- Name:'JSSymbolData::GetFinance', //类名::
- Explain:'财务数据FINANCE(ID)',
- JobID:jobItem.ID,
- Request:{ Url:self.RealtimeApiUrl, Type:'POST', Data:{ id:lID, symbol: this.Symbol, daterange:dateRange } },
- Self:this,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(recvData)
- {
- self.RecvStockValue(recvData,jobItem,key,0);
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
- }
- var apiDownload=new DownloadFinanceData(
- {
- Job:jobItem,
- Symbol:this.Symbol,
- Url:this.StockHistoryDayApiUrl,
- RealtimeUrl:this.RealtimeApiUrl,
- Args:aryArgs,
- DataKey:key,
- Callback:function(recvData, jobItem, key)
- {
- self.RecvStockValue(recvData, jobItem, key,0);
- self.Execute.RunNextJob();
- },
- ErrorCallback:function(strError)
- {
- self.AddStockValueError(key,strError);
- }
- });
- apiDownload.Download();
- }
- this.GetVariantData=function(jobItem)
- {
- var key=jobItem.VariantName;
- if (this.StockData.has(key)) return this.Execute.RunNextJob();
- var self=this;
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var obj=
- {
- Name:'JSSymbolData::GetVariantData', //类名::
- Explain:'变量数据下载',
- JobID:jobItem.ID,
- Request:{ Url:"数据地址", Type:'POST', Data:{ VariantName:jobItem.VariantName, symbol: this.Symbol, daterange:dateRange } },
- Self:this,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(recvData)
- {
- if (recvData.Error)
- {
- self.AddStockValueError(key,recvData.Error);
- }
- else
- {
- var dataType=0;
- if (IFrameSplitOperator.IsNumber(recvData.DataType)) dataType=recvData.DataType;
- self.RecvStockValue(recvData.Data,jobItem,key,dataType);
- }
-
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
- }
- var errorCallback=function(strError)
- {
- self.AddStockValueError(key,strError);
- };
- var apiDownload;
- if (jobItem.VariantName=="CAPITAL" || jobItem.VariantName=="TOTALCAPITAL" || jobItem.VariantName=="EXCHANGE")
- {
- var callback=function(recvData, jobItem, key)
- {
- self.RecvStockValue(recvData, jobItem, key,0);
- self.Execute.RunNextJob();
- };
- apiDownload=new DownloadFinanceData(
- {
- Job:jobItem,
- Symbol:this.Symbol,
- Url:this.StockHistoryDayApiUrl,
- RealtimeUrl:this.RealtimeApiUrl,
- Args:[jobItem.VariantName],
- DataKey:key,
- Callback:callback,
- ErrorCallback:errorCallback
- });
- }
- else if (jobItem.VariantName=="HYBLOCK" || jobItem.VariantName=="DYBLOCK" || jobItem.VariantName=="GNBLOCK")
- {
- var callback=function(recvData, jobItem, key, dataType)
- {
- self.RecvStockValue(recvData, jobItem, key, dataType);
- self.Execute.RunNextJob();
- };
- apiDownload=new DownloadGroupData(
- {
- Job:jobItem,
- Symbol:this.Symbol,
- Url:this.StockHistoryDayApiUrl,
- RealtimeUrl:this.RealtimeApiUrl,
- Args:[jobItem.VariantName],
- DataKey:key,
- Callback:callback,
- ErrorCallback:errorCallback
- });
- }
- else if (jobItem.VariantName=="INBLOCK")
- {
- var errorMessage=`${jobItem.VariantName}, 请对接外部数据.`;
- this.AddStockValueError(key,errorMessage);
- this.Execute.RunNextJob();
- return;
- }
- else
- {
- var errorMessage=`不支持变量${jobItem.VariantName}, 请对接外部数据.`;
- this.AddStockValueError(key,errorMessage);
- this.Execute.RunNextJob();
- return;
- }
- apiDownload.Download();
- }
- this.GetProFinance=function(jobItem)
- {
- var jobID=jobItem.ID;
- var finder=null;
- for(var i=0;i<JS_ARRAY_PROFESSIONAL_FINANCE.length;++i)
- {
- var item=JS_ARRAY_PROFESSIONAL_FINANCE[i];
- if (item.JobID==jobID)
- {
- finder=item;
- break;
- }
- }
- if (!finder) return this.Execute.RunNextJob();
- var aryArgs=this.JobArgumentsToArray(jobItem, finder.ArgCount);
- var key=this.GetStockDataKey(jobItem,aryArgs);
- if (this.StockData.has(key)) return this.Execute.RunNextJob();
- var self=this;
- var dataType=0;
- if ([JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE,JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE,JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE].includes(jobID))
- {
- dataType=aryArgs[2]==1?0:2; //TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
- }
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var obj=
- {
- Name:finder.FuncName, //类名::
- Explain:finder.Explain,
- JobID:jobID,
- Request:{ Url:self.StockHistoryDayApiUrl, Type:'POST', Data:{ Args:aryArgs, symbol: this.Symbol, daterange:dateRange } },
- Self:this,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(recvData)
- {
- self.RecvStockValue(recvData,jobItem,key,dataType);
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
- }
- JSConsole.Chart.Warn(`[JSSymbolData::GetProFinance] ${finder.FuncName} Not implemented.`);
- }
- //自定义变量数据下载
- this.GetCustomVariantData=function(jobItem)
- {
- var key=jobItem.VariantName;
- if (this.StockData.has(key)) return this.Execute.RunNextJob();
- var variantInfo=g_JSComplierResource.CustomVariant.Data.get(key);
- var self=this;
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var obj=
- {
- Name:'JSSymbolData::GetCustomVariantData', //类名::函数名
- Explain:'自定义变量数据下载',
- JobID:jobItem.ID,
- Request:{ Url:"数据地址", Type:'POST', Data:{ VariantName:jobItem.VariantName, symbol: this.Symbol, daterange:dateRange } },
- Self:this,
- VariantInfo:variantInfo,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(recvData)
- {
- if (recvData.Error) self.AddStockValueError(key,recvData.Error);
- else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
- self.Execute.RunNextJob();
- });
- }
- else
- {
- this.AddStockValueError(key, `自定义变量${key}下载失败`);
- this.Execute.RunNextJob();
- }
- }
- this.GetCustomFunctionData=function(jobItem)
- {
- var key=jobItem.FunctionName;
- var functionInfo=g_JSComplierResource.CustomFunction.Data.get(key);
- if (!functionInfo.IsDownload) return this.Execute.RunNextJob();
- if (this.StockData.has(key)) return this.Execute.RunNextJob(); //一个函数只能缓存一个数据, 保存多个外部自己保存
- var self=this;
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var obj=
- {
- Name:'JSSymbolData::GetCustomFunctionData', //类名::函数名
- Explain:'自定义函数数据下载',
- JobID:jobItem.ID,
- Request:
- {
- Url:"数据地址", Type:'POST',
- Data:
- {
- FunctionName:jobItem.FunctionName,
- symbol: this.Symbol, daterange:dateRange,
- JobItem:jobItem //函数编译信息
- }
- },
- Self:this,
- FunctionInfo:functionInfo,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(recvData)
- {
- if (recvData.Error) self.AddStockValueError(key,recvData.Error);
- else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
- self.Execute.RunNextJob();
- });
- }
- else
- {
- this.AddStockValueError(key, `自定义函数${key}下载失败`);
- this.Execute.RunNextJob();
- }
- }
- this.GetCustomFunctionDataV2=function(jobItem)
- {
- var funcName=jobItem.FunctionName;
- var functionInfo=g_JSComplierResource.CustomDataFunction.Data.get(funcName);
- if (!functionInfo) return;
- var aryArgs=this.JobArgumentsToArray(jobItem, functionInfo.ArgCount);
- var key=this.GetStockDataKey(jobItem,aryArgs);
-
- if (this.StockData.has(key)) return this.Execute.RunNextJob(); //一个函数只能缓存一个数据, 保存多个外部自己保存
- var self=this;
- if (this.NetworkFilter)
- {
- var dateRange=this.Data.GetDateRange();
- var obj=
- {
- Name:'JSSymbolData::GetCustomFunctionData', //类名::函数名
- Explain:'自定义函数数据下载',
- JobID:jobItem.ID,
- Request:
- {
- Url:"数据地址", Type:'POST',
- Data:
- {
- FunctionName:jobItem.FunctionName,
- symbol: this.Symbol, daterange:dateRange,
- JobItem:jobItem, //函数编译信息
- Key:key,
- period:this.Period,
- right:this.Right,
- }
- },
- Self:this,
- FunctionInfo:functionInfo,
- PreventDefault:false
- };
- this.NetworkFilter(obj, function(recvData)
- {
- if (recvData.Error) self.AddStockValueError(key,recvData.Error);
- else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
- self.Execute.RunNextJob();
- });
- }
- else
- {
- this.AddStockValueError(key, `自定义函数${key}下载失败`);
- this.Execute.RunNextJob();
- }
- }
- this.RecvStockValue=function(recvData,jobItem,key,dataType)
- {
- if (!recvData)
- {
- JSConsole.Complier.Log(`[JSSymbolData::RecvStockValue] key=${key} data is null`);
- return;
- }
- if (dataType==0)
- {
- if (Array.isArray(recvData))
- {
- var kdata=this.Data; //K线
- var aryFittingData;
- if (this.DataType==HQ_DATA_TYPE.KLINE_ID)
- {
- if (JSCommonData.ChartData.IsDayPeriod(this.Period,true))
- aryFittingData=kdata.GetFittingFinanceData(recvData); //数据和主图K线拟合
- else if (JSCommonData.ChartData.IsMinutePeriod(this.Period,true))
- aryFittingData=kdata.GetMinuteFittingFinanceData(recvData); //数据和主图K线拟合
- else
- return;
- }
- else
- {
- aryFittingData=kdata.GetMinuteFittingFinanceData(recvData); //数据和主图分时拟合
- }
-
- var bindData=new JSCommonData.ChartData();
- bindData.Data=aryFittingData;
- var result=bindData.GetValue();
- if (key=="EXCHANGE") //计算换手率=成交量/流通股本*100
- {
- for(var i in result)
- {
- var kitem=kdata.Data[i];
- if (result[i]>0)
- result[i]=kitem.Vol/result[i] * 100;
- }
- }
-
- this.StockData.set(key,{ Data:result });
- }
- else
- {
- this.StockData.set(key,{ Data:recvData.Value });
- }
- }
- else if (dataType==1) //单数值
- {
- this.StockData.set(key,{ Data:recvData.Value });
- }
- else if (dataType==2) //数据不做平滑处理
- {
- var kdata=this.Data; //K线
- var aryFittingData;
- if (this.DataType==HQ_DATA_TYPE.KLINE_ID)
- {
- if (JSCommonData.ChartData.IsDayPeriod(this.Period,true))
- aryFittingData=kdata.GetFittingTradeData(recvData, 0, false); //数据和主图K线拟合
- else if (JSCommonData.ChartData.IsMinutePeriod(this.Period,true))
- aryFittingData=kdata.GetMinuteFittingTradeData(recvData, 0, false); //数据和主图K线拟合
- else
- return;
- }
- else
- {
- aryFittingData=kdata.GetMinuteFittingTradeData(recvData, 0); //数据和主图分钟拟合
- }
-
- var bindData=new JSCommonData.ChartData();
- bindData.Data=aryFittingData;
- var result=bindData.GetValue();
-
- this.StockData.set(key,{ Data:result });
- }
- }
- this.AddStockValueError=function(key, message)
- {
- this.StockData.set(key,{ Error:message });
- }
- this.GetStockCacheData=function(obj)
- {
- var key;
- if (obj.FunctionName)
- key=this.GetStockDataKey({FunctionName:obj.FunctionName}, obj.Args);
- else if (obj.VariantName)
- key=obj.VariantName;
- else if (obj.CustomName)
- key=obj.CustomName; //自定义名字
- else
- return null;
- if (!this.StockData.has(key)) return null;
- var data=this.StockData.get(key);
- if (data.Error) this.Execute.ThrowUnexpectedNode(obj.Node, data.Error);
- return data.Data;
- }
- this.IsInBlock=function(blockName, node)
- {
- var data=this.GetStockCacheData({ VariantName:"INBLOCK", Node:node });
- if (!data) return 0;
- var aryBlock=data.split('|');
- for(var i=0; i<aryBlock.length; ++i)
- {
- var item=aryBlock[i];
- if (item==blockName) return 1;
- }
- return 0;
- }
- /*
- 飞狐函数 SYSPARAM
- SYSPARAM(1)画面上光标位置(K线序号)
- SYSPARAM(2)主图可见K线最初位置
- SYSPARAM(3)主图可见K线最后位置,注意:该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
- SYSPARAM(4)主图可见K线最高价,注意:该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
- SYSPARAM(5)主图可见K线最低价,注意:该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
- SYSPARAM(6)画面上光标数值,注意:该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
- */
- this.SysParam=function(id, jsExec)
- {
- if (!this.DrawInfo) return [];
- if (id==2)
- {
- jsExec.IsUsePageData=true;
- if (IFrameSplitOperator.IsNumber(this.DrawInfo.Start))
- return this.DrawInfo.Start+1;
- }
- else if (id==3)
- {
- jsExec.IsUsePageData=true;
- if (IFrameSplitOperator.IsNumber(this.DrawInfo.End))
- return this.DrawInfo.End+1;
- }
- else if (id==4)
- {
- jsExec.IsUsePageData=true;
- if (!IFrameSplitOperator.IsNumber(this.DrawInfo.End) ||!IFrameSplitOperator.IsNumber(this.DrawInfo.Start)) return [];
- if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return [];
- var high=null;
- for(var i=this.DrawInfo.Start; i<=this.DrawInfo.End && i<this.Data.Data.length; ++i)
- {
- var item=this.Data.Data[i];
- if (!IFrameSplitOperator.IsNumber(item.High)) continue;
- if (high==null) high=item.High;
- else if(high<item.High) high=item.High;
- }
- return high;
- }
- else if (id==5)
- {
- jsExec.IsUsePageData=true;
- if (!IFrameSplitOperator.IsNumber(this.DrawInfo.End) ||!IFrameSplitOperator.IsNumber(this.DrawInfo.Start)) return [];
- if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return [];
- var low=null;
- for(var i=this.DrawInfo.Start;i<=this.DrawInfo.End && i<this.Data.Data.length;++i)
- {
- var item=this.Data.Data[i];
- if (!IFrameSplitOperator.IsNumber(item.Low)) continue;
- if (low==null) low=item.Low;
- else if(low>item.Low) low=item.Low;
- }
- return low;
- }
- return [];
- }
- this.JobArgumentsToArray=function(job, lCount)
- {
- var args=job.Args;
- if (args.length!=lCount)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: argument count error.`);
- }
- var aryValue=[];
- for(var i=0;i<args.length;++i)
- {
- var item=args[i];
- if (this.IsNumber(item))
- {
- aryValue.push(item);
- }
- else if (item.Type==Syntax.Literal)
- {
- aryValue.push(item.Value);
- }
- else if (item.Type==Syntax.Identifier) //变量 !!只支持默认的变量值
- {
- var isFind=false;
- for(var j in this.Arguments)
- {
- const argItem=this.Arguments[j];
- if (argItem.Name==item.Name)
- {
- aryValue.push(argItem.Value);
- isFind=true;
- break;
- }
- }
- if (!isFind)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: can't read ${item.Name}`);
- }
- }
- }
- return aryValue;
- }
- this.DownloadCustomAPIData = function (job)
- {
- if (!this.NetworkFilter) return this.Execute.RunNextJob();
- var args = [];
- for (var i in job.Args)
- {
- var item = job.Args[i];
- if (item.Type == Syntax.Literal)
- {
- args.push(item.Value);
- }
- else if (item.Type == Syntax.Identifier) //变量 !!只支持默认的变量值
- {
- var isFind = false;
- for (var j in this.Arguments)
- {
- const argItem = this.Arguments[j];
- if (argItem.Name == item.Name)
- {
- args.push(argItem.Value);
- isFind = true;
- break;
- }
- }
- if (!isFind)
- {
- var token = job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index, token.Line, 0, `LoadAPIData() Error: can't read ${item.Name}`);
- }
- }
- else
- {
- return this.Execute.RunNextJob();
- }
- }
- var self = this;
- var obj =
- {
- Name: 'JSSymbolData::DownloadCustomAPIData', //类名::函数名
- Explain: '下载自定义api数据',
- Period: this.Period,
- Right: this.Right,
- Symbol: this.Symbol,
- KData: this.Data, //K线数据
- Cache: this.CustomAPIData,
- Args: args,
- Self: this,
- PreventDefault: false
- };
- this.NetworkFilter(obj, function (data) {
- self.RecvCustomAPIData(data, args);
- self.Execute.RunNextJob();
- });
- if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
- this.Execute.RunNextJob();
- }
- this.RecvCustomAPIData = function (recvData, args)
- {
- if (!recvData || !recvData.data) return;
- var data = recvData.data;
- var apiKey = this.GenerateCustomAPIKey(args);
- if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true))
- {
- if (!data.date || !data.time) return;
- var date = data.date;
- var time = data.time;
- for (var key in data)
- {
- if (key == 'date' || key == 'time') continue;
- var item = data[key];
- }
- }
- else if (JSCommonData.ChartData.IsDayPeriod(this.Period, true))
- {
- if (!data.date) return;
- var date = data.date;
- var result = { __Type__: "Object" };
- for (var key in data) {
- if (key == 'date') continue;
- var item = data[key];
- if (Array.isArray(item))
- {
- var value = this.FittingCustomAPIArray(item, date);
- result[key] = value;
- }
- else if (this.IsNumber(item))
- {
- result[key] = item;
- }
- }
- this.CustomAPIData.set(apiKey, result);
- }
- }
- this.FittingCustomAPIArray = function (data, date, time)
- {
- var kdata = this.Data; //K线
- var arySingleData = [];
- for (var i in data)
- {
- var value = data[i];
- var indexItem = new JSCommonData.SingleData(); //单列指标数据
- indexItem.Date = date[i];
- if (time && i < time.length) indexItem.Time = time[i];
- indexItem.Value = value;
- arySingleData.push(indexItem);
- }
- var aryFittingData;
- if (JSCommonData.ChartData.IsDayPeriod(this.Period, true))
- aryFittingData = kdata.GetFittingData(arySingleData); //数据和主图K线拟合
- else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true))
- aryFittingData = kdata.GetMinuteFittingData(arySingleData); //数据和主图K线拟合
- else
- return null;
- var bindData = new JSCommonData.ChartData();
- bindData.Data = aryFittingData;
- var result = bindData.GetValue();
- return result;
- }
- //MA.MA1#WEEK
- this.ReadIndexFunctionValue=function(item, result) //返回 {Period:周期, Out:输出变量, Error:, Name:脚本名字 }
- {
- var indexParam={};
- if (typeof(item)=== 'object')
- {
- if (!this.ReadArgumentValue(item,indexParam))
- {
- result.Error=indexParam.Error;
- return false;
- }
- }
- else
- {
- indexParam.Value=item;
- }
-
- var pos=indexParam.Value.indexOf("\.");
- if (pos!=-1)
- {
- result.Name=indexParam.Value.slice(0, pos); //名字
- var pos2=indexParam.Value.indexOf('#', pos+1);
- if (pos2!=-1)
- {
- result.Out=indexParam.Value.slice(pos+1, pos2); //输出变量
- result.Period=indexParam.Value.slice(pos2+1); //周期
- }
- else
- {
- result.Out=indexParam.Value.slice(pos+1);
- }
- }
- else
- {
- var pos2=indexParam.Value.indexOf('#');
- if (pos2!=-1)
- {
- result.Name=indexParam.Value.slice(0,pos2);
- result.Period=indexParam.Value.slice(pos2+1); //周期
- }
- else
- {
- result.Name=indexParam.Value;
- }
- }
- const PERIOD_MAP=new Map([
- ["DAY",0 ], ["WEEK", 1 ], ["MONTH",2 ], ["SEASON",9 ], ["YEAR", 3], ["HALFYEAR",22], ["WEEK2",21],
- ["MIN1", 4], ["MIN5", 5 ], ["MIN15", 6 ], ["MIN30",7 ], ["MIN60", 8 ],["MIN120",11],["MIN240",12],
- ["DAY2", 40002],["MULTIDAY",40002],["DAY3", 40003],["DAY4", 40004],["DAY5",40005],
- ["DAY6", 40006],["DAY7", 40007],["DAY8", 40008],["DAY9", 40009],["DAY10",40010],
- ["DAY11", 40011],["DAY12", 40012],["DAY13", 40013],["DAY14", 40014],["DAY15", 40015],
- ]);
- if (result.Period)
- {
- if (!PERIOD_MAP.has(result.Period))
- {
- result.Error=`${result.Period}, 周期错误`;
- return false;
- }
- result.PeriodID=PERIOD_MAP.get(result.Period);
- }
- return true;
- }
- this.ReadSymbolArgumentValue=function(item, result) //返回{ Value:股票代码, Error:错误信息}
- {
- var readArgument={};
- if (typeof(item)=== 'object')
- {
- if (!this.ReadArgumentValue(item,readArgument))
- {
- result.Error=readArgument.Error;
- return false;
- }
- }
- else
- {
- readArgument.Value=item;
- }
- if (readArgument.Value=='') readArgument.Value=this.Symbol; //缺省使用股票代码
- var symbol=readArgument.Value;
- //支持 SH60000, SZ000001
- //A股后缀小写
- if (symbol.indexOf('.SH')>0) result.Symbol=symbol.replace('.SH', ".sh");
- else if (symbol.indexOf('.SZ')>0) result.Symbol=symbol.replace('.SZ', ".sz");
- else if (symbol.indexOf("SH")==0) result.Symbol=symbol.slice(2)+".sh";
- else if (symbol.indexOf("SZ")==0) result.Symbol=symbol.slice(2)+".sz";
- else result.Symbol=symbol;
- return true;
- }
- this.ReadIndexArgumentValue=function(args, result)
- {
- result.Args=[];
- for(var i in result.SytemIndex.Args) //复制参数
- {
- var item=result.SytemIndex.Args[i];
- result.Args.push({Value:item.Value, Name:item.Name});
- }
- if (args.length>2 && result.SytemIndex.Args && result.SytemIndex.Args.length>0)
- {
- for(var i=2, j=0; i<args.length && j<result.SytemIndex.Args.length; ++i, ++j)
- {
- var readArgument={};
- var item=args[i];
- if (typeof(item)=== 'object')
- {
- if (!this.ReadArgumentValue(item,readArgument))
- {
- result.Error=readArgument.Error;
- return false;
- }
- }
- else
- {
- readArgument.Value=item;
- }
- result.Args[j].Value=readArgument.Value;
- }
- }
- return true;
- }
- this.ReadArgumentValue=function(item, result) //读取变量值
- {
- result.Name=item.Name;
- if (item.Type==Syntax.Literal)
- {
- result.Value=item.Value;
- return true;
- }
- if (item.Type==Syntax.Identifier)
- {
- var isFind=false;
- for(var i in this.Arguments)
- {
- const argItem=this.Arguments[i];
- if (argItem.Name==item.Name)
- {
- result.Value=argItem.Value;
- isFind=true;
- return true;
- }
- }
- if (!isFind)
- {
- result.Error=`can't read ${item.Name}` ;
- return false;
- }
- }
- result.Error=`can't read ${item.Name}, type error.`;
- return false;
- }
-
- this.ReadIndexFunctionOut=function(item, result)
- {
- var indexParam={};
- if (typeof(item)=== 'object')
- {
- if (!this.ReadArgumentValue(item,indexParam))
- {
- result.Error=indexParam.Error;
- return false;
- }
- }
- else
- {
- indexParam.Value=item;
- }
- result.OutIndex=indexParam.Value;
- result.Out=null;
- return true;
- }
- //TMP2:=KDJ.K#WEEK;
- this.CallMemberScriptIndex=function(job)
- {
- if (job.Member.Object.Type!=Syntax.Identifier ||job.Member.Property.Type!=Syntax.Identifier)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: 参数错误`);
- }
- var objName=job.Member.Object.Name;
- var PropertyName=job.Member.Property.Name;
- if (PropertyName=="" || PropertyName==null)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: ${objName}.${PropertyName} 指标输出变量错误`);
- }
-
- if (this.Execute.VarTable.has(objName))
- {
- var memberValue=this.Execute.VarTable.get(objName);
- if (memberValue.hasOwnProperty(PropertyName))
- {
- JSConsole.Complier.Log(`[JSSymbolData::CallMemberScriptIndex] index data ${objName}.${PropertyName} in cache.`);
- return this.Execute.RunNextJob();
- }
- }
-
- var callInfo=objName+"."+PropertyName;
- var indexInfo={ Job:job, PeriodID:this.Period , Symbol:this.Symbol };
- if (!this.ReadIndexFunctionValue(callInfo,indexInfo)) //读取指标
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: '${callInfo}' ${indexInfo.Error}`);
- }
- var systemIndex=new JSIndexScript();
- var systemItem=systemIndex.Get(indexInfo.Name);
- if (!systemItem)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: '${callInfo}' ${indexInfo.Name} 指标不存在`);
- }
- if (Array.isArray(systemItem.Args) && systemItem.Args.length>0)
- {
- indexInfo.Args=[];
- for(var i in systemItem.Args) //复制参数
- {
- var item=systemItem.Args[i];
- indexInfo.Args.push({Value:item.Value, Name:item.Name});
- }
- }
- JSConsole.Complier.Log('[JSSymbolData::CallMemberScriptIndex] call script index', indexInfo);
- var dateTimeRange=this.Data.GetDateRange();
- var option=
- {
- HQDataType:this.DataType,
- Symbol:indexInfo.Symbol,
- Name:'',
- Right:this.Right, //复权
- Period:indexInfo.PeriodID, //周期
- Data:null,
- SourceData:null,
- Callback:(outVar,job, symbolData)=> {
- this.RecvMemberScriptIndexData(outVar,job,symbolData);
- this.Execute.RunNextJob();
- },
- CallbackParam:indexInfo,
- Async:true,
- MaxRequestDataCount:this.MaxRequestDataCount+30*2,
- MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
- Arguments:indexInfo.Args,
- //Condition:this.Condition,
- IsBeforeData:this.IsBeforeData,
- NetworkFilter:this.NetworkFilter,
- IsApiPeriod:this.IsApiPeriod,
- KLineRange:dateTimeRange //K线数据范围
- };
- //执行脚本
- var run=JSComplier.Execute(systemItem.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
-
- }
- this.CallDynamicScriptIndex=function(job, varTable)
- {
- var callInfo=job.DynamicName;
- var indexInfo={ Job:job, PeriodID:this.Period , Symbol:this.Symbol };
- if (!this.ReadIndexFunctionValue(callInfo,indexInfo)) //读取指标
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() Error: '${callInfo}' ${indexInfo.Error}`);
- }
- var systemIndex=new JSIndexScript(); //系统指标
- var systemItem=systemIndex.Get(indexInfo.Name);
- if (!systemItem)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() Error: '${callInfo}' ${indexInfo.Name} 指标不存在`);
- }
- indexInfo.SytemIndex=systemItem;
- if (!this.ReadDynamicIndexArgumentValue(job.Args, indexInfo, varTable))
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() ${indexInfo.Name} 指标参数错误 : ${indexInfo.Error} `);
- }
- JSConsole.Complier.Log('[JSSymbolData::CallMemberScriptIndex] call script index', indexInfo);
- var dateTimeRange=this.Data.GetDateRange();
- var option=
- {
- HQDataType:this.DataType,
- Symbol:indexInfo.Symbol,
- Name:'',
- Right:this.Right, //复权
- Period:indexInfo.PeriodID, //周期
- Data:null,
- SourceData:null,
- Callback:(outVar,job, symbolData)=> {
- this.RecvDynamicScriptIndexData(outVar,job,symbolData);
- this.Execute.RunNextJob();
- },
- CallbackParam:indexInfo,
- Async:true,
- MaxRequestDataCount:this.MaxRequestDataCount+30*2,
- MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
- Arguments:indexInfo.Args,
- //Condition:this.Condition,
- IsBeforeData:this.IsBeforeData,
- NetworkFilter:this.NetworkFilter,
- IsApiPeriod:this.IsApiPeriod,
- KLineRange:dateTimeRange //K线数据范围
- };
- //执行脚本
- var run=JSComplier.Execute(systemItem.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
- }
- this.ReadDynamicIndexArgumentValue=function(args, result, varTable)
- {
- result.Args=[];
- for(var i =0;i<result.SytemIndex.Args.length; ++i) //复制参数
- {
- var item=result.SytemIndex.Args[i];
- result.Args.push({ Value:item.Value, Name:item.Name, IsDefault:true });
- }
- if (!IFrameSplitOperator.IsNonEmptyArray(args)) return true;
- for(var i=0;i<args.length;++i)
- {
- var item=args[i];
- var argItem=result.Args[i];
- if (!argItem) continue;
- if (item.Type==Syntax.Literal)
- {
- argItem.Value=item.Value;
- argItem.IsDefault=false;
- }
- else if (item.Type==Syntax.Identifier) //支持传参
- {
- if (varTable.has(item.Name))
- {
- argItem.Value=varTable.get(item.Name);
- argItem.IsDefault=false;
- }
- }
- }
- return true;
- }
- /*****************************************************************************************************************************
- 脚本调用
- STKINDI
- STKINDI('600000.sh','MA.MA1#WEEK',5,10,20,30,60,120);
- 1=股票代码 2=指标名字.输出变量#周期, 3....参数
- CALCSTOCKINDEX
- 用法:CALCSTOCKINDEX(品种代码,指标名称,指标线),返回该指标相应输出的计算值.
- 例如:
- CALCSTOCKINDEX('SH600000','KDJ',3)表示上证600000的KDJ指标第3个输出即J之值,第一个参数可在前面加SZ(深市),SH(沪市),BJ(京市),或市场_,,
- CALCSTOCKINDEX('47_IFL0','MACD',2)表示IFL0品种的MACD指标第2个输出值.
- "MA.MA1"(6,12,18)
- *******************************************************************************************************************************/
- this.CallScriptIndex=function(job, varTable)
- {
- if (job.Member) return this.CallMemberScriptIndex(job);
- if (job.DynamicName) return this.CallDynamicScriptIndex(job, varTable);
- if (!job.Args || !(job.Args.length>=2))
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${job.FunctionName} 参数错误`);
- }
- var indexInfo={ Job:job, PeriodID:this.Period };
- if (!this.ReadSymbolArgumentValue(job.Args[0],indexInfo)) //读取代码
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
- }
- if (!this.ReadIndexFunctionValue(job.Args[1],indexInfo)) //读取指标
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
- }
- if (job.FunctionName=="CALCSTOCKINDEX")
- {
- if (!this.ReadIndexFunctionOut(job.Args[2],indexInfo)) //读取返回值索引
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
- }
- }
- var systemIndex=new JSIndexScript();
- var systemItem=systemIndex.Get(indexInfo.Name);
- if (!systemItem)
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标不存在`);
- }
- indexInfo.SytemIndex=systemItem; //系统指标
- if (!this.ReadIndexArgumentValue(job.Args,indexInfo))
- {
- var token=job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标参数错误 : ${indexInfo.Error} `);
- }
- JSConsole.Complier.Log('[JSSymbolData::CallScriptIndex] call script index', indexInfo);
- var DateTimeRange=null;
- if (this.Data && this.Data.Data.length>0)
- {
- var start=this.Data.Data[0];
- var end=this.Data.Data[this.Data.Data.length-1];
- DateTimeRange=
- {
- Start:{Date:start.Date, Time: start.Time},
- End:{Date:end.Date, Time: end.Time},
- }
- }
- var option=
- {
- HQDataType:this.DataType,
- Symbol:indexInfo.Symbol,
- Name:'',
- Right:this.Right, //复权
- Period:indexInfo.PeriodID, //周期
- Data:null,
- SourceData:null,
- Callback:(outVar,job, symbolData)=> {
- this.RecvScriptIndexData(outVar,job,symbolData);
- this.Execute.RunNextJob();
- },
- CallbackParam:indexInfo,
- Async:true,
- MaxRequestDataCount:this.MaxRequestDataCount+30*2,
- MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
- Arguments:indexInfo.Args,
- //Condition:this.Condition,
- IsBeforeData:this.IsBeforeData,
- NetworkFilter:this.NetworkFilter,
- IsApiPeriod:this.IsApiPeriod,
- KLineRange:DateTimeRange //K线数据范围
- };
- //执行脚本
- var run=JSComplier.Execute(indexInfo.SytemIndex.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
- }
- this.RecvMemberScriptIndexData=function(outVar,indexInfo,symbolData)
- {
- JSConsole.Complier.Log('[JSSymbolData::RecvMemberScriptIndexData] ', outVar, indexInfo, symbolData);
- var kLine=symbolData.Data.Data;
- var aryOutVar=outVar;
- var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
- var member=indexInfo.Job.Member;
- var objName=member.Object.Name;
- var propertyName=member.Property.Name;
- var memberValue={};
- if (this.Execute.VarTable.has(objName))
- memberValue=this.Execute.VarTable.get(objName);
- else
- this.Execute.VarTable.set(objName, memberValue);
- //保存所有的指标数据, 下面用到了就可以不用算了
- for(var i in data)
- {
- var key=outVar[i].Name;
- if (indexInfo.Period) key+='#'+indexInfo.Period; //带周期的变量
- memberValue[key]=data[i].Data;
- }
- }
- this.RecvScriptIndexData=function(outVar,indexInfo,symbolData)
- {
- var key=this.GenerateScriptIndexKey(indexInfo);
- JSConsole.Complier.Log('[JSSymbolData::RecvScriptIndexData] ', outVar, indexInfo, symbolData, key);
- var kLine=symbolData.Data.Data;
- var aryOutVar=outVar;
- if (indexInfo.Out)
- {
- for(var i=0;i<outVar.length; ++i)
- {
- var item=outVar[i];
- if (item.Name==indexInfo.Out)
- {
- aryOutVar=[item];
- break;
- }
- }
- var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
- this.ScriptIndexOutData.set(key,data[0].Data);
- }
- else if (IFrameSplitOperator.IsPlusNumber(indexInfo.OutIndex))
- {
- var index=indexInfo.OutIndex-1;
- aryOutVar=[outVar[index]];
- var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
- this.ScriptIndexOutData.set(key,data[0].Data);
- }
- else
- {
- var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
- var result={ __Type__:"Object" };
- for(var i in data)
- {
- var item=data[i];
- result[item.Name]=item.Data;
- }
- this.ScriptIndexOutData.set(key,result);
- }
- }
- this.RecvDynamicScriptIndexData=function(outVar,indexInfo,symbolData)
- {
- JSConsole.Complier.Log('[JSSymbolData::RecvDynamicScriptIndexData] ', outVar, indexInfo, symbolData);
- var kLine=symbolData.Data.Data;
- var aryOutVar=outVar;
- var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
- var objName=indexInfo.Name;
- var memberValue={};
- if (this.Execute.VarTable.has(objName))
- memberValue=this.Execute.VarTable.get(objName);
- else
- this.Execute.VarTable.set(objName, memberValue);
- var strValue="";
- for(var i=0; i<indexInfo.Args.length; ++i)
- {
- var item=indexInfo.Args[i];
- if (item.IsDefault===false)
- {
- if (strValue.length>0) strValue+=",";
- strValue+=`${item.Value}`;
- }
- }
- var strArgs=`(${strValue})`;
- //保存所有的指标数据, 下面用到了就可以不用算了
- for(var i=0; i<data.length; ++i)
- {
- var key=`${outVar[i].Name}#${strArgs}`;
- if (indexInfo.Period) key+='#'+indexInfo.Period; //带周期的变量
-
- memberValue[key]=data[i].Data;
- }
- }
- //key= (代码,周期),指标(参数) => 输出
- this.GenerateScriptIndexKey=function(indexInfo)
- {
- var indexParam='';
- var args=indexInfo.Args;
- for(var i in args)
- {
- if (indexParam.length>0) indexParam+=',';
- var item=args[i];
- indexParam+=item.Value.toString();
- }
- var out="ALL";
- if (indexInfo.Out) out=indexInfo.Out;
- else if (IFrameSplitOperator.IsPlusNumber(indexInfo.OutIndex)) out=`Out[${indexInfo.OutIndex-1}]`;
- var key=`(${indexInfo.Symbol},${indexInfo.PeriodID}), ${indexInfo.Name}(${indexParam})=>${out}`;
- return key;
- }
- this.ExecuteScriptIndexError=function(error,indexInfo)
- {
- var token=indexInfo.Job.Token;
- this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标执行错误 : ${error} `);
- }
- this.GetScriptIndexOutData=function(args,node, funcName)
- {
- var indexInfo={ PeriodID:this.Period };
- if (!this.ReadSymbolArgumentValue(args[0],indexInfo)) //读取代码
- this.Execute.ThrowUnexpectedNode(node,`${funcName}() 股票代码错误: ${indexInfo.Error}`);
- if (!this.ReadIndexFunctionValue(args[1],indexInfo)) //读取指标
- this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标错误: ${indexInfo.Error}`);
- if (funcName=="CALCSTOCKINDEX")
- {
- if (!this.ReadIndexFunctionOut(args[2],indexInfo)) //读取返回值索引
- this.Execute.ThrowUnexpectedNode(node, `${funcName}() Error: ${indexInfo.Error}`);
- }
- var systemIndex=new JSIndexScript();
- var systemItem=systemIndex.Get(indexInfo.Name);
- if (!systemItem)
- this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标错误: ${indexInfo.Name} 指标不存在`);
- indexInfo.SytemIndex=systemItem; //系统指标
- if (!this.ReadIndexArgumentValue(args,indexInfo))
- this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标参数错误: ${indexInfo.Error}`);
- var key=this.GenerateScriptIndexKey(indexInfo);
- if (!this.ScriptIndexOutData.has(key)) return null;
- return this.ScriptIndexOutData.get(key);
- }
-
- this.JsonDataToHistoryData=function(data)
- {
- var list = data.data;
- var aryDayData=new Array();
- var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7;
- var up = 8, down = 9, stop = 10, unchanged = 11;
- for (var i = 0; i < list.length; ++i)
- {
- var item = new JSCommonData.HistoryData();
- item.Date = list[i][date];
- item.Open = list[i][open];
- item.YClose = list[i][yclose];
- item.Close = list[i][close];
- item.High = list[i][high];
- item.Low = list[i][low];
- item.Vol = list[i][vol]; //原始单位股
- item.Amount = list[i][amount];
- if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除
- //上涨 下跌家数
- if (list[i].length > up) item.Up = list[i][up];
- if (list[i].length > down) item.Down = list[i][down];
- if (list[i].length > stop) item.Stop = list[i][stop];
- if (list[i].length > unchanged) item.Unchanged = list[i][unchanged];
- aryDayData.push(item);
- }
- return aryDayData;
- }
- this.JsonDataToMinuteHistoryData=function(data)
- {
- var list = data.data;
- var aryDayData=new Array();
- var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, time = 8;
- for (var i = 0; i < list.length; ++i)
- {
- let item = new JSCommonData.HistoryData();
- item.Date = list[i][date];
- item.Open = list[i][open];
- item.YClose = list[i][yclose];
- item.Close = list[i][close];
- item.High = list[i][high];
- item.Low = list[i][low];
- item.Vol = list[i][vol]; //原始单位股
- item.Amount = list[i][amount];
- item.Time=list[i][time];
- // if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除
- aryDayData.push(item);
- }
- // 无效数据处理
- for(let i = 0; i < aryDayData.length; ++i)
- {
- var minData = aryDayData[i];
- if (minData == null) coninue;
- if (isNaN(minData.Open) || minData.Open <= 0 || isNaN(minData.High) || minData.High <= 0 || isNaN(minData.Low) || minData.Low <= 0
- || isNaN(minData.Close) || minData.Close <= 0 || isNaN(minData.YClose) || minData.YClose <= 0)
- {
- if (i == 0)
- {
- if (minData.YClose > 0)
- {
- minData.Open = minData.YClose;
- minData.High = minData.YClose;
- minData.Low = minData.YClose;
- minData.Close = minData.YClose;
- }
- }
- else // 用前一个有效数据填充
- {
- for(let j = i-1; j >= 0; --j)
- {
- var minData2 = aryDayData[j];
- if (minData2 == null) coninue;
- if (minData2.Open > 0 && minData2.High > 0 && minData2.Low > 0 && minData2.Close > 0)
- {
- if (minData.YClose <= 0) minData.YClose = minData2.Close;
- minData.Open = minData2.Open;
- minData.High = minData2.High;
- minData.Low = minData2.Low;
- minData.Close = minData2.Close;
- break;
- }
- }
- }
- }
- }
- return aryDayData;
- }
- //API 返回数据 转化为array[]
- this.JsonDataToMinuteData = function (data)
- {
- var aryMinuteData = new Array();
- for (var i in data.stock[0].minute)
- {
- var jsData = data.stock[0].minute[i];
- var item = new JSCommonData.MinuteData();
- item.Close = jsData.price;
- item.Open = jsData.open;
- item.High = jsData.high;
- item.Low = jsData.low;
- item.Vol = jsData.vol; //股
- item.Amount = jsData.amount;
- if (i == 0) //第1个数据 写死9:25
- item.DateTime = data.stock[0].date.toString() + " 0925";
- else
- item.DateTime = data.stock[0].date.toString() + " " + jsData.time.toString();
- item.Date = data.stock[0].date;
- item.Time = jsData.time;
- item.Increate = jsData.increate;
- item.Risefall = jsData.risefall;
- item.AvPrice = jsData.avprice;
- aryMinuteData[i] = item;
- }
- return aryMinuteData;
- }
- //CODELIKE 模糊股票代码
- this.CODELIKE=function(value)
- {
- if (this.Symbol.indexOf(value)==0) return 1;
- return 0;
- }
- this.NAMELIKE = function (value)
- {
- if (this.Name && this.Name.indexOf(value) == 0) return 1;
- return 0;
- }
- /*
- SETCODE 市场类型
- 0:深圳 1:上海,47:中金所期货 28:郑州商品 29:大连商品 30:上海商品,27:香港指数 31:香港主板,48:香港创业板...
- */
- this.SETCODE=function()
- {
- if (this.Symbol.indexOf('.sh')) return 1;
- if (this.Symbol.indexOf('.sz')) return 0;
- return 0;
- }
- this.GetSymbol = function () { return this.Symbol; }
- this.GetName = function () { return this.Name; }
- this.TIME=function()
- {
- var result = [];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- for(let i in this.Data.Data)
- {
- var item=this.Data.Data[i];
- if (this.IsNumber(item.Time))
- result[i]=item.Time;
- else
- result[i]=0;
- }
- return result;
- }
- this.DATE = function ()
- {
- var result = [];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- for (let i in this.Data.Data)
- {
- var item = this.Data.Data[i];
- result[i] = item.Date - 19000000;;
- }
- return result;
- }
- /*
- 取得该周期的时分秒,适用于日线以下周期.
- 用法: TIME2
- 函数返回有效值范围为(000000-235959)
- */
- this.TIME2=function()
- {
- var result=[];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- for(let i=0;i<this.Data.Data.length;++i)
- {
- var item=this.Data.Data[i];
- if (this.IsNumber(item.Time))
- result[i]=item.Time*100;
- else
- result[i]=0;
- }
- return result;
- }
- this.DateTime=function()
- {
- var result=[];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- var isKLineMinute=ChartData.IsMinutePeriod(this.Period, true);
- for(var i=0;i<this.Data.Data.length;++i)
- {
- var item=this.Data.Data[i];
- if (isKLineMinute)
- {
- result[i]=item.Date*10000+item.Time;
- }
- else
- {
- result[i]=item.Date;
- }
- }
- return result;
- }
-
- this.YEAR = function ()
- {
- var result = [];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- for (let i in this.Data.Data)
- {
- var item = this.Data.Data[i];
- if (this.IsNumber(item.Date))
- result[i] = parseInt(item.Date / 10000);
- else
- result[i] = null;
- }
- return result;
- }
- this.MONTH = function ()
- {
- var result = [];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- for (let i in this.Data.Data)
- {
- var item = this.Data.Data[i];
- if (this.IsNumber(item.Date))
- result[i] = parseInt(item.Date % 10000 / 100);
- else
- result[i] = null;
- }
- return result;
- }
- //星期 1-7
- this.WEEK = function ()
- {
- var result = [];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- var tempDate = new Date();
- for (let i in this.Data.Data)
- {
- var item = this.Data.Data[i];
- result[i] = null;
- if (!this.IsNumber(item.Date)) continue;
- var year = parseInt(item.Date / 10000);
- var month = parseInt(item.Date % 10000 / 100);
- var day = item.Date % 100;
- tempDate.setFullYear(year, month - 1, day);
- result[i] = tempDate.getDay();
- }
- return result;
- }
- /*
- 取得该周期的日期离今天的天数.
- 用法: DAYSTOTODAY
- */
- this.DAYSTOTODAY=function()
- {
- var result=[];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- var nowDate=new Date();
- var endDate=new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate());
- for(let i=0; i<this.Data.Data.length; ++i)
- {
- var item=this.Data.Data[i];
- result[i]=null;
- if (!this.IsNumber(item.Date)) continue;
- var year=parseInt(item.Date/10000);
- var month=parseInt(item.Date%10000/100);
- var day=item.Date%100;
-
- var beginDate=new Date(year,month-1,day);
- var diffDays = Math.ceil((endDate - beginDate)/(24*60*60*1000));
- result[i]=diffDays;
- }
- return result;
- }
- /*
- 取得该周是年内第几个周.
- 用法:WEEKOFYEAR
- */
- this.WEEKOFYEAR=function()
- {
- var result=[];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- for(let i in this.Data.Data)
- {
- var item=this.Data.Data[i];
- result[i]=null;
- if (!this.IsNumber(item.Date)) continue;
- var year=parseInt(item.Date/10000);
- var month=parseInt(item.Date%10000/100);
- var day=item.Date%100;
-
- var endDate=new Date(year,month-1,day);
- var beginDate=new Date(year,0,1);
- var diffDays = Math.ceil((endDate - beginDate)/(24*60*60*1000));
- diffDays+=((beginDate.getDay() + 1) - 1);
- var week = Math.ceil(diffDays/7);
- var value=week;
- result[i]=value;
- }
- return result;
- }
- this.GetYearWeek=function(endDate)
- {
- var beginDate = new Date(endDate.getFullYear(), 0, 1);
- //星期从0-6,0代表星期天,6代表星期六
- var endWeek = endDate.getDay();
- if (endWeek == 0) endWeek = 7;
- var beginWeek = beginDate.getDay();
- if (beginWeek == 0) beginWeek = 7;
- //计算两个日期的天数差
- var millisDiff = endDate.getTime() - beginDate.getTime();
- var dayDiff = Math.floor(( millisDiff + (beginWeek - endWeek) * (24 * 60 * 60 * 1000)) / 86400000);
- return Math.ceil(dayDiff / 7) + 1;
- }
- this.REFDATE = function (data, date)
- {
- var result = null;
- var findDate=null;
- if (Array.isArray(date))
- {
- if (date.length>0) findDate=date[date.length-1];
- }
- else if (this.IsNumber(date))
- {
- findDate=date;
- }
- if (findDate==null) return null;
- if (findDate<5000000) findDate+=19000000;
- var index = null;
- for (let i in this.Data.Data) //查找日期对应的索引
- {
- if (this.Data.Data[i].Date == findDate)
- {
- index = parseInt(i);
- break;
- }
- }
- if (index == null || index >= data.length) return null;
- return data[index];
- }
- //用法:结果从0到11,依次分别是1/5/15/30/60分钟,日/周/月,多分钟,多日,季,年
- this.PERIOD=function()
- {
- //Period周期 0=日线 1=周线 2=月线 3=年线 9=季线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟
- const PERIOD_MAP=[5,6,7,11, 0,1,2,3,4,5, 9];
- if (this.Period >= 0 && this.Period <= PERIOD_MAP.length - 1)
- return PERIOD_MAP[this.Period];
-
- return this.Period;
- }
- this.GetDrawNull = function ()
- {
- var result = [];
- if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
- for (let i in this.Data.Data)
- {
- result[i] = null;
- }
- return result;
- }
- this.HOUR=function()
- {
- var result=[];
- if (!this.Data || !this.Data.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return result;
- for(var i=0;i<this.Data.Data.length;++i)
- {
- var item=this.Data.Data[i];
- result[i]=0;
- if (IFrameSplitOperator.IsNumber(item.Time)) result[i]=parseInt(item.Time/100);
- }
- return result;
- }
- this.MINUTE=function()
- {
- var result=[];
- if (!this.Data || !this.Data.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return result;
- for(var i=0;i<this.Data.Data.length;++i)
- {
- var item=this.Data.Data[i];
- result[i]=0;
- if (IFrameSplitOperator.IsNumber(item.Time)) result[i]=item.Time%100;
- }
- return result;
- }
- }
- //是否有是有效的数字
- JSSymbolData.prototype.IsNumber = function (value)
- {
- if (value == null) return false;
- if (isNaN(value)) return false;
- return true;
- }
- JSSymbolData.prototype.IsDivideNumber = function (value)
- {
- if (value == null) return false;
- if (isNaN(value)) return false;
- if (value == 0) return false;
- return true;
- }
- JSSymbolData.prototype.JsonDataToFinance = function (data)
- {
- var financeData;
- for (let i = 1; i <= 4; ++i)
- {
- switch (i)
- {
- case 1:
- var finance = data.finance1;
- var announcement = data.announcement1;
- break;
- case 2:
- var finance = data.finance2;
- var announcement = data.announcement2;
- break;
- case 3:
- var finance = data.finance3;
- var announcement = data.announcement3;
- break;
- case 4:
- var finance = data.finance4;
- var announcement = data.announcement4;
- break;
- default:
- break;
- }
- if (!finance || !announcement || !this.IsNumber(announcement.year) || !this.IsNumber(announcement.quarter)) continue;
- if (financeData) //如果存在1天公布多个报告期数据 只取最新的一个公告期数据
- {
- if (financeData.Announcement.year < announcement.year)
- financeData = { Date: data.date, Finance: finance, Announcement: announcement };
- }
- else
- {
- financeData = { Date: data.date, Finance: finance, Announcement: announcement };
- }
- }
- return financeData;
- }
- var JS_EXECUTE_DEBUG_LOG=false;
- var JS_EXECUTE_JOB_ID=
- {
- JOB_DOWNLOAD_SYMBOL_DATA:1, //下载股票的K线数据
- JOB_DOWNLOAD_INDEX_DATA:2, //下载大盘的K线数据
- JOB_DOWNLOAD_SYMBOL_LATEST_DATA:3, //最新的股票行情数据
- JOB_DOWNLOAD_INDEX_INCREASE_DATA: 4, //涨跌股票个数统计数据
- JOB_DOWNLOAD_VOLR_DATA: 5, //5日量比均量下载量比数据
- JOB_DOWNLOAD_OTHER_SYMBOL_DATA:9, //下载其他股票的K线数据
- JOB_DOWNLOAD_FINVALUE:301, //引用专业财务数据 FINVALUE(ID),ID为数据编号
- JOB_DOWNLOAD_FINONE:302, //引用指定年和月日的某类型的财务数据 FINONE(ID,Y,MMDD),ID为数据编号,Y和MMDD表示年和月日.
- JOB_DOWNLOAD_FINANCE:303, //FINANCE(ID) 基础财务数据
- JOB_DOWNLOAD_GPJYVALUE:304, //引用股票交易类数据 GPJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据,TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
- JOB_DOWNLOAD_VARIANT:305, //CAPITAL , TOTALCAPITAL, EXCHANGE
- JOB_DOWNLOAD_SCJYVALUE:306, //引用市场总的交易类数据.SCJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据,TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
- JOB_DOWNLOAD_GPJYONE:307, //GPJYONE(ID,N,Y,MMDD),ID为数据编号,N表示第几个数据(取1或2),Y和MMDD表示年和月日. 如果Y为0,MMDD为0,表示最新数据,MMDD为1,2,3...,表示倒数第2,3,4...个数据
- JOB_DOWNLOAD_SCJYONE:308, //SCJYONE(ID,N,Y,MMDD),ID为数据编号,N表示第几个数据(取1或2),Y和MMDD表示年和月日.如果Y为0,MMDD为0,表示最新数据,MMDD为1,2,3...,表示倒数第2,3,4...个数据
- JOB_DOWNLOAD_BKJYVALUE:309, //BKJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据(取1或2),TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理;2表示没有数据则为0.
- JOB_DOWNLOAD_BKJYONE:310, //BKJYONE(ID,N,Y,MMDD),ID为数据编号,N表示第几个数据(取1或2),Y和MMDD表示年和月日.如果Y为0,MMDD为0,表示最新数据,MMDD为1,2,3...,表示倒数第2,3,4...个数据
- JOB_CUSTOM_FUNCTION_DATA:6000, //自定义函数
- JOB_CUSTOM_VARIANT_DATA:6001, //自定义变量
- JOB_CUSTOM_DATA_FUNCTION:6002, //自定义数据函数
- JOB_DOWNLOAD_MARGIN_BALANCE: 1000, //融资融券余额
- JOB_DOWNLOAD_MARGIN_RATE: 1001, //融资占比
- JOB_DOWNLOAD_MARGIN_BUY_BALANCE: 1010, //买入信息-融资余额
- JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: 1011, //买入信息-买入额
- JOB_DOWNLOAD_MARGIN_BUY_REPAY: 1012, //买入信息-偿还额
- JOB_DOWNLOAD_MARGIN_BUY_NET: 1013, //买入信息-融资净买入
- JOB_DOWNLOAD_MARGIN_SELL_BALANCE: 1020, //卖出信息-融券余量
- JOB_DOWNLOAD_MARGIN_SELL_VOLUME: 1021, //卖出信息-卖出量
- JOB_DOWNLOAD_MARGIN_SELL_REPAY: 1022, //卖出信息-偿还量
- JOB_DOWNLOAD_MARGIN_SELL_NET: 1023, //卖出信息-融券净卖出
- JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: 2000, //负面新闻统计
- JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: 2001, //机构调研
- JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: 2002, //互动易
- JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: 2003, //股东增持
- JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: 2004, //股东减持
- JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: 2005, //信托持股
- JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: 2006, //大宗交易
- JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: 2007, //官网新闻
- JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: 2008, //高管要闻
- JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: 2009, //股权质押
- JOB_DOWNLOAD_CUSTOM_API_DATA: 30000, //自定义数据
- //调用其他脚本指标
- //KDJ.K , KDJ.K#WEEK
- //STKINDI('600000.sh','MA.MA1#WEEK',5,10,20,30,60,120);
- JOB_EXECUTE_INDEX:30010,
- JOB_RUN_SCRIPT:10000, //执行脚本
- //融资融券
- GetMarginJobID: function (value)
- {
- let dataMap = new Map([
- [1, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE], //MARGIN(1) 融资融券余额
- [2, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE], //MARGIN(2) 融资占比
- [3, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE], //MARGIN(3) 买入信息-融资余额
- [4, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT], //MARGIN(4) 买入信息-买入额
- [5, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY], //MARGIN(5) 买入信息-偿还额
- [6, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET], //MARGIN(6) 买入信息-融资净买入
- [7, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE], //MARGIN(7) 卖出信息-融券余量
- [8, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME], //MARGIN(8) 卖出信息-卖出量
- [9, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY], //MARGIN(9) 卖出信息-偿还量
- [10, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET], //MARGIN(10) 卖出信息-融券净卖出
- ]);
- if (dataMap.has(value)) return dataMap.get(value);
- return null;
- },
- GetNewsAnalysisID: function (value)
- {
- let dataMap = new Map([
- [1, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE], //NEWS(1) 负面新闻统计
- [2, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH], //NEWS(2) 机构调研统计
- [3, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT], //NEWS(3) 互动易
- [4, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE], //NEWS(4) 股东增持
- [5, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2], //NEWS(5) 股东减持
- [6, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER], //NEWS(6) 信托持股
- [7, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING], //NEWS(7) 大宗交易
- [8, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS], //NEWS(8) 官网新闻
- [9, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS], //NEWS(9) 高管要闻
- [10, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE], //NEWS(10) 股权质押
- ]);
- if (dataMap.has(value)) return dataMap.get(value);
- return null;
- }
- };
- //专业财务数据
- var JS_ARRAY_PROFESSIONAL_FINANCE=
- [
- {
- Name:"GPJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE,
- Explain:"股票交易类数据GPJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetGPJYValue", ArgCount:3
- },
- {
- Name:"GPJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYONE,
- Explain:"股票交易类数据GPJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetGPJYOne", ArgCount:4
- },
- {
- Name:"SCJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE,
- Explain:"市场交易类数据SCJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetSCJYValue",ArgCount:3
- },
- {
- Name:"SCJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYONE,
- Explain:"市场交易类数据SCJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetSCJYOne",ArgCount:4
- },
- {
- Name:"BKJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE,
- Explain:"板块交易类数据BKJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetBKJYValue",ArgCount:3
- },
- {
- Name:"BKJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYONE,
- Explain:"板块交易类数据BKJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetBKJYOne",ArgCount:4
- },
- {
- Name:"FINVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE,
- Explain:"财务数据FINVALUE(ID)", FuncName:"JSSymbolData::GetFinValue",ArgCount:1
- },
- {
- Name:"FINONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE,
- Explain:"财务数据FINONE(ID,Y,MMDD)", FuncName:"JSSymbolData::GetFinOne",ArgCount:3
- }
- ];
- function JSExecute(ast,option)
- {
- this.AST=ast; //语法树
- this.ErrorHandler=new ErrorHandler();
- this.VarTable=new Map(); //变量表
- this.VarDrawTable=new Map(); //绘图变量表
- this.OutVarTable=new Array(); //输出变量
- this.Arguments=[];
- //脚本自动变量表, 只读
- this.ConstVarTable=new Map([
- //个股数据
- ['CLOSE', null], ['VOL', null], ['OPEN', null], ['HIGH', null], ['LOW', null], ['AMOUNT', null], ['AMO', null],
- ['C', null], ['V', null], ['O', null], ['H', null], ['L', null],
- ['VOLR', null],
- ['VOLINSTK',null], ["OPI",null], //持仓量
- ["QHJSJ",null], ["SETTLE",null], //结算价
- ["ZSTJJ",null], //分时图均价线,对于分时图周期指标有效.
- ["ISEQUAL",null], ["ISUP",null],["ISDOWN"], //ISUP=收阳 ISEQUAL=平盘 ISDOWN=收阴
- //日期类
- ['DATE', null], ['YEAR', null], ['MONTH', null], ['PERIOD', null], ['WEEK', null],['WEEKDAY',null],["TIME",null],["DATETIME",null],["TIME2",null],
- ["WEEKOFYEAR", null],["DAYSTOTODAY", null],
- ["HOUR",null],["MINUTE",null],
-
- //大盘数据
- ['INDEXA',null],['INDEXC',null],['INDEXH',null],['INDEXL',null],['INDEXO',null],['INDEXV',null],
- ['INDEXADV', null], ['INDEXDEC', null],
- ['FROMOPEN',null], //已开盘有多长分钟
- ['TOTALFZNUM', null], //该品种的每天的总交易分钟数.
- ['CURRBARSCOUNT', null], //到最后交易日的周期数
- ['TOTALBARSCOUNT',null],
- ['ISLASTBAR', null], //判断是否为最后一个周期
- ['BARSTATUS',null], //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置.
- ["BARPOS", null], //返回从第一根K线开始到当前的周期数
-
- ["TOTALCAPITAL",null], //总股本
- ['CAPITAL', null], //流通股本(手)
- ['EXCHANGE', null], //换手率
- ['SETCODE', null], //市场类型
- ['CODE', null], //品种代码
- ['STKNAME', null], //品种名称
- ["TQFLAG",null], //TQFLAG 当前的复权状态,0:无复权 1:前复权 2:后复权
- ['HYBLOCK', null], //所属行业板块
- ['DYBLOCK', null], //所属地域板块
- ['GNBLOCK', null], //所属概念
- ["FGBLOCK",null], //所属风格板块
- ["ZSBLOCK",null], //所属指数板块
- ["ZHBLOCK",null], //所属组合板块
- ["ZDBLOCK",null], //所属自定义板块
- ["HYZSCODE",null],
- ["GNBLOCKNUM",null], //所属概念板块的个数
- ["FGBLOCKNUM",null], //所属风格板块的个数
- ["ZSBLOCKNUM",null], //所属指数板块的个数
- ["ZHBLOCKNUM",null], //所属组合板块的个数
- ["ZDBLOCKNUM",null], //所属自定义板块的个数
- ["HYSYL",null], //指数市盈率或个股所属行业的市盈率
- ["HYSJL",null], //指数市净率或个股所属行业的市净率
- ['DRAWNULL', null],
- ["NULL",null],
- ["MACHINEDATE",null],["MACHINETIME",null],["MACHINEWEEK",null],
- ["DYNA_NOW",null], //DYNA_NOW 现价 DYNAINFO(7) 即时行情数据 没有现价时(比如在开盘前),返回昨收盘价
- ["DYNA_ZAF",null], //DYNA_ZAF 涨幅 DYNAINFO(14) 即时行情数据(沪深京早盘竞价期间使用匹配价的涨幅) 转换成幅度需要乘100
- ["DYNA_LB", null], //DYNA_LB DYNAINFO(17) 量比 即时行情数据
- ["DYNA_ZAS",null], //DYNA_ZAS DYNAINFO(24) 返回涨速 报价界面行情数据 转换成幅度需要乘100
- ["SELLVOL", null], //返回内盘,即DYNAINFO(22) 即时行情数据
- ["BUYVOL", null], //返回外盘,即DYNAINFO(21) 即时行情数据
- ['LARGEINTRDVOL', null], //逐笔买入大单成交量,相当于L2_VOL(0,0)+L2_VOL(1,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ['LARGEOUTTRDVOL', null], //逐笔卖出大单成交量,相当于L2_VOL(0,1)+L2_VOL(1,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ["TRADENUM", null], //逐笔成交总单数,沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ["TRADEINNUM", null], //逐笔买入成交单数,相当于L2_VOLNUM(0,0)+L2_VOLNUM(1,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ["TRADEOUTNUM", null], //逐笔卖出成交单数,相当于L2_VOLNUM(0,1)+L2_VOLNUM(1,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ["LARGETRDINNUM", null], //逐笔买入大单成交单数,相当于L2_VOLNUM(0,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ["LARGETRDOUTNUM", null], //逐笔卖出大单成交单数,相当于L2_VOLNUM(0,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ["CUR_BUYORDER", null], //总委买量,序列数据,专业版等(资金流向功能)沪深京品种行情专用
- ["CUR_SELLORDER", null], //总委卖量,序列数据,专业版等(资金流向功能)沪深京品种行情专用
- ["ACTINVOL", null], //主动买成交量,相当于L2_VOL(0,2)+L2_VOL(1,2)+L2_VOL(2,2)+L2_VOL(3,2),沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ["ACTOUTVOL", null], //主动卖成交量,相当于L2_VOL(0,3)+L2_VOL(1,3)+L2_VOL(2,3)+L2_VOL(3,3),沪深京品种的资金流向,仅日线以上周期,用于特定版本
- ["BIDORDERVOL", null], //累计总有效委买量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委买量-累计总有效撤买量=总买+总成交量
- ["BIDCANCELVOL", null], //累计总有效撤买量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委买量-累计总有效撤买量=总买+总成交量
- ["AVGBIDPX", null], //专业版等(资金流向功能)沪深京品种行情专用:最新委买均价
- ["OFFERORDERVOL", null], //累计总有效委卖量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委卖量-累计总有效撤卖量=总卖+总成交量
- ["OFFERCANCELVOL", null], //累计总有效撤卖量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委卖量-累计总有效撤卖量=总卖+总成交量
- ["AVGOFFERPX", null], //专业版等(资金流向功能)沪深京品种行情专用:最新委卖均价
- ]);
- this.SymbolData=new JSSymbolData(this.AST,option,this);
- this.Algorithm = new JSAlgorithm(this.ErrorHandler, this.SymbolData);
- this.Draw = new JSDraw(this.ErrorHandler, this.SymbolData);
- this.JobList=[]; //执行的任务队列
- this.UpdateUICallback=null; //回调
- this.CallbackParam=null;
- this.Interrupt={ Exit:false }; //中断信息
- if (option)
- {
- if (option.Callback) this.UpdateUICallback=option.Callback;
- if (option.CallbackParam) this.CallbackParam=option.CallbackParam;
- if (option.Arguments) this.Arguments=option.Arguments;
- }
- this.Execute=function()
- {
- JSConsole.Complier.Log('[JSExecute::Execute] JobList', this.JobList);
- this.RunNextJob();
- }
- this.RunNextJob=function()
- {
- if (this.JobList.length<=0) return;
- var jobItem=this.JobList.shift();
- switch (jobItem.ID)
- {
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA:
- return this.SymbolData.GetSymbolData();
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA:
- return this.SymbolData.GetIndexData();
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA:
- return this.SymbolData.GetIndexIncreaseData(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA:
- return this.SymbolData.GetLatestData(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA: //量比
- return this.SymbolData.GetVolRateData(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA: //指定股票数据
- return this.SymbolData.GetOtherSymbolData(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE:
- return this.SymbolData.GetFinance(jobItem);
- //专业财务数据
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYONE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYONE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYONE:
- return this.SymbolData.GetProFinance(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT: //CAPITAL, TOTALCAPITAL
- return this.SymbolData.GetVariantData(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA:
- return this.SymbolData.GetCustomVariantData(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA:
- return this.SymbolData.GetCustomFunctionData(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_CUSTOM_DATA_FUNCTION:
- return this.SymbolData.GetCustomFunctionDataV2(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE:
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
- return this.SymbolData.GetMarginData(jobItem.ID);
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: //负面新闻
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: //机构调研
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: //互动易
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: //股东增持
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: //股东减持
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: //信托持股
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: //大宗交易
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: //官网新闻
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: //高管要闻
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: //股权质押
- return this.SymbolData.GetNewsAnalysisData(jobItem.ID);
- case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA:
- return this.SymbolData.DownloadCustomAPIData(jobItem);
- case JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX:
- return this.SymbolData.CallScriptIndex(jobItem, this.VarTable);
- case JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT:
- return this.Run();
- }
- }
- this.ReadSymbolData=function(name,node)
- {
- switch(name)
- {
- case 'CLOSE':
- case 'C':
- case 'VOL':
- case 'V':
- case 'OPEN':
- case 'O':
- case 'HIGH':
- case 'H':
- case 'LOW':
- case 'L':
- case 'AMOUNT':
- case "OPI":
- case 'VOLINSTK':
- case "SETTLE":
- case "QHJSJ":
- case "ZSTJJ":
- case "ISEQUAL": //平盘
- case "ISUP": //收阳
- case "ISDOWN": //收阴
- return this.SymbolData.GetSymbolCacheData(name);
- case 'VOLR':
- return this.SymbolData.GetVolRateCacheData(node);
- //大盘数据
- case 'INDEXA':
- case 'INDEXC':
- case 'INDEXH':
- case 'INDEXO':
- case 'INDEXV':
- case 'INDEXL':
- case 'INDEXADV':
- case 'INDEXDEC':
- return this.SymbolData.GetIndexCacheData(name);
- case 'CURRBARSCOUNT':
- return this.SymbolData.GetCurrBarsCount();
- case "BARPOS":
- return this.SymbolData.GetBarPos();
- case "TOTALBARSCOUNT":
- return this.SymbolData.GetTotalBarsCount();
- case "TOTALFZNUM":
- return this.SymbolData.GetTotalTradeMinuteCount();
- case 'ISLASTBAR':
- return this.SymbolData.GetIsLastBar();
- case "BARSTATUS":
- return this.SymbolData.GetBarStatus();
- case "TOTALCAPITAL":
- case 'CAPITAL':
- case 'EXCHANGE':
- case "HYBLOCK":
- case "DYBLOCK":
- case "GNBLOCK":
- case "FGBLOCK":
- case "ZSBLOCK":
- case "ZHBLOCK":
- case "ZDBLOCK":
- case "HYZSCODE":
-
- case "GNBLOCKNUM":
- case "FGBLOCKNUM":
- case "ZSBLOCKNUM":
- case "ZHBLOCKNUM":
- case "ZDBLOCKNUM":
-
- case "HYSYL":
- case "HYSJL":
- case 'FROMOPEN':
- case "LARGEINTRDVOL":
- case "LARGEOUTTRDVOL":
- case "TRADENUM":
- case "TRADEINNUM":
- case "TRADEOUTNUM":
- case "LARGETRDINNUM":
- case "LARGETRDOUTNUM":
- case "CUR_BUYORDER":
- case "CUR_SELLORDER":
- case "ACTINVOL":
- case "ACTOUTVOL":
- case "BIDORDERVOL":
- case "BIDCANCELVOL":
- case "AVGBIDPX":
- case "OFFERORDERVOL":
- case "OFFERCANCELVOL":
- case "AVGOFFERPX":
- return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node });
- case 'SETCODE':
- return this.SymbolData.SETCODE();
- case 'CODE':
- return this.SymbolData.GetSymbol();
- case 'STKNAME':
- return this.SymbolData.GetName();
-
- case 'TIME':
- return this.SymbolData.TIME();
- case "TIME2":
- return this.SymbolData.TIME2();
- case 'DATE':
- return this.SymbolData.DATE();
- case "DATETIME":
- return this.SymbolData.DateTime();
- case 'YEAR':
- return this.SymbolData.YEAR();
- case 'MONTH':
- return this.SymbolData.MONTH();
- case 'WEEK':
- case "WEEKDAY":
- return this.SymbolData.WEEK();
- case 'PERIOD':
- return this.SymbolData.PERIOD();
- case 'DRAWNULL':
- case "NULL":
- return this.SymbolData.GetDrawNull();
- case "HOUR":
- return this.SymbolData.HOUR();
- case "MINUTE":
- return this.SymbolData.MINUTE();
- case "TQFLAG":
- return this.SymbolData.Right;
- case "MACHINEDATE":
- {
- var now=new Date();
- return (now.getFullYear()*10000+(now.getMonth()*1)*100+now.getDate())-19000000;
- }
- case "MACHINETIME":
- {
- var now=new Date();
- return now.getHours()*10000+(now.getMinutes()*1)*100+now.getSeconds();
- }
- case "MACHINEWEEK":
- {
- var now=new Date();
- return now.getDay();
- }
- case "WEEKOFYEAR":
- return this.SymbolData.WEEKOFYEAR();
- case "DAYSTOTODAY":
- return this.SymbolData.DAYSTOTODAY();
- case "DYNA_NOW":
- case "DYNA_ZAF":
- case "DYNA_LB":
- case "DYNA_ZAS":
- case "SELLVOL":
- case "BUYVOL":
- return this.SymbolData.GetDynaCacheData(name);
- default:
- this.ThrowUnexpectedNode(node, '变量'+name+'不存在', name);
- }
- }
- this.ReadCustomVariant=function(name,node)
- {
- return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node });
- }
- //读取变量
- this.ReadVariable=function(name,node)
- {
- if (this.ConstVarTable.has(name))
- {
- let data=this.ConstVarTable.get(name);
- if (data==null) //动态加载,用到再加载
- {
- data=this.ReadSymbolData(name,node);
- this.ConstVarTable.set(name,data);
- }
- return data;
- }
- if (g_JSComplierResource.IsCustomVariant(name)) return this.ReadCustomVariant(name,node); //读取自定义变量
- if (this.VarTable.has(name)) return this.VarTable.get(name);
- if (name.indexOf("COLOR")==0)
- {
- var colorValue=JSComplier.ColorVarToRGB(name);
- if (colorValue) return colorValue;
- }
- this.ThrowUnexpectedNode(node, '变量'+name+'不存在');
- return null;
- }
- this.ReadMemberVariable = function (node)
- {
- var obj = node.Object;
- var member = node.Property;
- let maiObj;
- if (obj.Type == Syntax.BinaryExpression || obj.Type == Syntax.LogicalExpression)
- maiObj = this.VisitBinaryExpression(obj);
- else if (obj.Type == Syntax.CallExpression)
- maiObj = this.VisitCallExpression(obj);
- else
- maiObj = this.GetNodeValue(obj);
- if (!maiObj) return null;
- var value = maiObj[member.Name];
- if (value) return value;
- return null;
- }
- //单数据转成数组 个数和历史数据一致
- this.SingleDataToArrayData = function (value)
- {
- let count = this.SymbolData.Data.Data.length;
- let result = [];
- for (let i = 0; i < count; ++i)
- {
- result[i] = value;
- }
- return result;
- }
- this.RunAST=function()
- {
- //预定义的变量
- for(var i=0; i<this.Arguments.length; ++i)
- {
- var item =this.Arguments[i];
- this.VarTable.set(item.Name,item.Value);
- }
- if (!this.AST) this.ThrowError();
- if (!this.AST.Body) this.ThrowError();
- for(var i=0;i<this.AST.Body.length; ++i)
- {
- var item =this.AST.Body[i];
- this.VisitNode(item);
- //输出变量
- if (item.Type==Syntax.ExpressionStatement && item.Expression)
- {
- if (item.Expression.Type==Syntax.AssignmentExpression && item.Expression.Operator==':' && item.Expression.Left)
- {
- let assignmentItem=item.Expression;
- let varName=assignmentItem.Left.Name;
- let outVar=this.VarTable.get(varName);
- if (this.VarDrawTable.has(varName)) //绘图函数赋值
- {
- let draw=this.VarDrawTable.get(varName);
- this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
- }
- else
- {
- var type=0;
- if (!Array.isArray(outVar))
- {
- if (typeof (outVar) == 'string')
- {
- var floatValue=parseFloat(outVar);
- if (IFrameSplitOperator.IsNumber(floatValue))
- {
- outVar=this.SingleDataToArrayData(floatValue);
- }
- else
- {
- outVar=this.SingleDataToArrayData(outVar);
- type=1001;
- }
- }
- else outVar = this.SingleDataToArrayData(outVar);
- }
- this.OutVarTable.push({Name:varName, Data:outVar,Type:type});
- }
- }
- else if (item.Expression.Type==Syntax.CallExpression)
- {
- let callItem=item.Expression;
- if (this.Draw.IsDrawFunction(callItem.Callee.Name))
- {
- let draw=callItem.Draw;
- draw.Name=callItem.Callee.Name;
- this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
- }
- else if (callItem.Callee.Name==="IFC" && callItem.Draw)
- {
- let draw=callItem.Draw;
- draw.Name=draw.DrawType;
- this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
- }
- else
- {
- let outVar=callItem.Out;
- varName=`__temp_c_${callItem.Callee.Name}_${i}__`;
- var type=0;
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- this.OutVarTable.push({Name:varName, Data:outVar,Type:type,NoneName:true});
- }
- }
- else if (item.Expression.Type==Syntax.Identifier)
- {
- let varName=item.Expression.Name;
- let outVar=this.ReadVariable(varName,item.Expression);
- var type=0;
- if (!Array.isArray(outVar))
- {
- if (typeof(outVar)=='string') outVar=this.SingleDataToArrayData(parseFloat(outVar));
- else outVar=this.SingleDataToArrayData(outVar);
- }
- varName="__temp_i_"+i+"__";
- this.OutVarTable.push({Name:varName, Data:outVar, Type:type, NoneName:true});
- }
- else if (item.Expression.Type==Syntax.Literal) //常量
- {
- let outVar=item.Expression.Value;
- if (IFrameSplitOperator.IsString(outVar) && outVar.indexOf("$")>0)
- outVar=this.SymbolData.GetOtherSymolCacheData({ Literal:outVar });
- varName="__temp_li_"+i+"__";
- var type=0;
- this.OutVarTable.push({Name:varName, Data:outVar, Type:type, NoneName:true});
- }
- else if (item.Expression.Type==Syntax.BinaryExpression)
- {
- var varName="__temp_b_"+i+"__";
- let outVar=item.Expression.Out;
- var type=0;
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
- }
- else if (item.Expression.Type==Syntax.LogicalExpression) //逻辑语句 如 T1 AND T2
- {
- var varName="__temp_l_"+i+"__";
- let outVar=item.Expression.Out;
- var type=0;
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
- }
- else if (item.Expression.Type==Syntax.UnaryExpression)
- {
- var varName="__temp_u_"+i+"__";
- var varInfo={ };
- if (this.ReadUnaryExpression(item.Expression, varInfo))
- {
- var type=0;
- this.OutVarTable.push({Name:varName, Data:varInfo.OutVar,Type:type, NoneName:true});
- }
- }
- else if (item.Expression.Type==Syntax.MemberExpression) //MA.MA2
- {
- var outVar=this.ReadMemberVariable(item.Expression);
- if (outVar)
- {
- var type=0;
- var varName="__temp_di_"+i+"__";
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
- }
- }
- else if (item.Expression.Type==Syntax.SequenceExpression)
- {
- var varName;
- var draw;
- var color, upColor, downColor, stickType;
- var lineWidth;
- var colorStick=false;
- var pointDot=false;
- var upDownDot=false;
- var circleDot=false;
- var lineStick=false;
- var isDotLine=false;
- var stick=false;
- var volStick=false;
- var lineArea=false;
- var stepLine=false;
- var isShow = true;
- var isExData = false;
- var isOverlayLine = false; //叠加线
- var isSingleLine=false; //独立线段
- var isNoneName=false;
- var isShowTitle=true;
- //显示在位置之上,对于DRAWTEXT和DRAWNUMBER等函数有用,放在语句的最后面(不能与LINETHICK等函数共用),比如:
- //DRAWNUMBER(CLOSE>OPEN,HIGH,CLOSE),DRAWABOVE;
- var isDrawAbove=false;
- //VALIGN0,VALIGN1,VALIGN2 设置文字垂直对齐方式(上中下)
- //ALIGN0,ALIGN1,ALIGN2 设置文字水平对齐方式(左中右)
- var drawAlign=-1, drawVAlign=-1;
- var fontSize=-1;
- var bgConfig=null;
- var vLineConfig=null;
- var xOffset=null, yOffset=null;
- var lineDash=null;
- for(var j=0 ; j<item.Expression.Expression.length; ++j)
- {
- let itemExpression=item.Expression.Expression[j];
- if (itemExpression.Type==Syntax.AssignmentExpression && itemExpression.Operator==':' && itemExpression.Left)
- {
- if (j==0)
- {
- varName = itemExpression.Left.Name;
- let varValue = this.VarTable.get(varName);
- if (this.VarDrawTable.has(varName)) //绘图函数赋值
- {
- draw=this.VarDrawTable.get(varName);
- }
- else if (!Array.isArray(varValue))
- {
- varValue = this.SingleDataToArrayData(varValue);
- this.VarTable.set(varName, varValue); //把常量放到变量表里
- }
- }
- }
- else if (itemExpression.Type==Syntax.Identifier)
- {
- let value=itemExpression.Name;
- if (value==='COLORSTICK') colorStick=true;
- else if (value==='POINTDOT') pointDot=true;
- else if (value=="UPDOWNDOT") upDownDot=true;
- else if (value==='CIRCLEDOT') circleDot=true;
- else if (value == 'DOTLINE') isDotLine = true;
- else if (value==='LINESTICK') lineStick=true;
- else if (value==='STICK') stick=true;
- else if (value==='VOLSTICK') volStick=true;
- else if (value=="LINEAREA") lineArea=true;
- else if (value=="STEPLINE") stepLine=true;
- else if (value==="DRAWABOVE") isDrawAbove=true;
- else if (value==="SINGLELINE") isSingleLine=true;
- else if (value.indexOf('COLOR')==0) color=value;
- else if (value.indexOf("RGBX")==0 && value.length==10) color=value; //RGBX+“RRGGBB”
- else if (value.indexOf('LINETHICK')==0) lineWidth=value;
- else if (value=="ALIGN0") drawAlign=0;
- else if (value=="ALIGN1") drawAlign=1;
- else if (value=="ALIGN2") drawAlign=2;
-
- else if (value=="VALIGN0") drawVAlign=0;
- else if (value=="VALIGN1") drawVAlign=1;
- else if (value=="VALIGN2") drawVAlign=2;
- else if (value.indexOf('NODRAW') == 0) isShow = false;
- else if (value.indexOf('EXDATA') == 0) isExData = true; //扩展数据, 不显示再图形里面
- else if (value.indexOf('LINEOVERLAY') == 0) isOverlayLine = true;
- else if (value.indexOf("NOTEXT")==0 || value.indexOf("NOTITLE")==0) isShowTitle=false; //标题不显示
- else if (value.indexOf("FONTSIZE")==0)
- {
- var strFontSize=value.replace("FONTSIZE","");
- fontSize=parseInt(strFontSize);
- }
- else
- {
- if (j==0)
- {
- varName=itemExpression.Name;
- let varValue=this.ReadVariable(varName,itemExpression);
- if (!Array.isArray(varValue)) varValue=this.SingleDataToArrayData(varValue);
- varName="__temp_si_"+i+"__";
- isNoneName=true;
- this.VarTable.set(varName,varValue); //放到变量表里
- }
- }
- }
- else if (itemExpression.Type == Syntax.Literal) //常量
- {
- if (j==0)
- {
- let aryValue = this.SingleDataToArrayData(itemExpression.Value);
- varName = itemExpression.Value.toString();
- this.VarTable.set(varName, aryValue); //把常量放到变量表里
- }
- }
- else if (itemExpression.Type==Syntax.CallExpression)
- {
- if (j==0)
- {
- if (this.Draw.IsDrawFunction(itemExpression.Callee.Name))
- {
- draw=itemExpression.Draw;
- draw.Name=itemExpression.Callee.Name;
- }
- else
- {
- let varValue=itemExpression.Out;
- varName=`__temp_sc_${itemExpression.Callee.Name}_${i}__`;
- isNoneName=true;
- this.VarTable.set(varName,varValue);
- }
- }
- else
- {
- if (itemExpression.Callee.Name=="RGB" || itemExpression.Callee.Name=="RGBA")
- {
- color=itemExpression.Out;
- }
- else if (itemExpression.Callee.Name=="UPCOLOR")
- {
- upColor=itemExpression.Out;
- }
- else if (itemExpression.Callee.Name=="DOWNCOLOR")
- {
- downColor=itemExpression.Out;
- }
- else if (itemExpression.Callee.Name=="STICKTYPE")
- {
- stickType=itemExpression.Out;
- }
- else if (itemExpression.Callee.Name=="XMOVE")
- {
- xOffset=itemExpression.Out;
- }
- else if (itemExpression.Callee.Name=="YMOVE")
- {
- yOffset=itemExpression.Out;
- }
- else if (itemExpression.Callee.Name=="LINEDASH")
- {
- if (IFrameSplitOperator.IsNonEmptyArray(itemExpression.Out))
- lineDash=itemExpression.Out.slice();
- }
- else if (itemExpression.Callee.Name=="SOUND")
- {
- var event=this.GetSoundEvent();
- if (event)
- {
- }
- varName=null;
- }
- else if (itemExpression.Callee.Name=="ICON")
- {
- let drawCond=this.VarTable.get(varName);
- if (drawCond)
- {
- draw=this.GetOutIconData(drawCond,itemExpression.Draw);
- if (draw) draw.Name=itemExpression.Callee.Name;
- }
- varName=null;
- }
- else if (itemExpression.Callee.Name=="BACKGROUND")
- {
- bgConfig=itemExpression.Draw;
- varName=null;
- }
- else if (itemExpression.Callee.Name=="CKLINE")
- {
- vLineConfig=itemExpression.Draw;
- varName=null;
- }
- }
- }
- else if (itemExpression.Type==Syntax.BinaryExpression)
- {
- if (j==0)
- {
- varName="__temp_sb_"+i+"__";
- let aryValue=itemExpression.Out;
- isNoneName=true;
- this.VarTable.set(varName,aryValue);
- }
- }
- else if (itemExpression.Type==Syntax.UnaryExpression)
- {
- if (j==0)
- {
- varName="__temp_su_"+i+"__";
- var varInfo={ };
- if (this.ReadUnaryExpression(itemExpression, varInfo))
- {
- isNoneName=true;
- this.VarTable.set(varName,varInfo.OutVar);
- }
- }
- }
- else if (itemExpression.Type==Syntax.MemberExpression) //"MA.MA2"(5,12,29), COLORRED;
- {
- if (j==0)
- {
- var outVar=this.ReadMemberVariable(itemExpression);
- if (outVar)
- {
- if (!Array.isArray(outVar)) varValue=this.SingleDataToArrayData(outVar);
- isNoneName=true;
- varName="__temp_di_"+i+"__";
- this.VarTable.set(varName,outVar); //把常量放到变量表里
- }
- }
- }
- }
- if (pointDot && varName) //圆点
- {
- let outVar=this.VarTable.get(varName);
- let value={Name:varName, Data:outVar, Radius:g_JSChartResource.POINTDOT.Radius, Type:3};
- if (color) value.Color=color;
- if (lineWidth) value.LineWidth = lineWidth;
- this.OutVarTable.push(value);
- }
- else if (circleDot && varName) //圆点
- {
- let outVar=this.VarTable.get(varName);
- let value={Name:varName, Data:outVar, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3};
- if (color) value.Color=color;
- if (lineWidth) value.LineWidth = lineWidth;
- this.OutVarTable.push(value);
- }
- else if (upDownDot && varName) //彩色点
- {
- let outVar=this.VarTable.get(varName);
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- let value={Name:varName, Data:outVar, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3, UpDownDot:true };
- if (color) value.Color=color;
- if (upColor) value.UpColor=upColor;
- if (downColor) value.DownColor=downColor;
- if (lineWidth) value.LineWidth=lineWidth;
- this.OutVarTable.push(value);
- }
- else if (lineStick && varName) //LINESTICK 同时画出柱状线和指标线
- {
- let outVar=this.VarTable.get(varName);
- let value={Name:varName, Data:outVar, Type:4};
- if (color) value.Color=color;
- if (lineWidth) value.LineWidth=lineWidth;
- this.OutVarTable.push(value);
- }
- else if (stick && varName) //STICK 画柱状线
- {
- let outVar=this.VarTable.get(varName);
- let value={Name:varName, Data:outVar, Type:5};
- if (color) value.Color=color;
- if (lineWidth) value.LineWidth=lineWidth;
- this.OutVarTable.push(value);
- }
- else if (volStick && varName) //VOLSTICK 画彩色柱状线
- {
- let outVar=this.VarTable.get(varName);
- let value={Name:varName, Data:outVar, Type:6};
- if (color) value.Color=color;
- if (upColor) value.UpColor=upColor;
- if (downColor) value.DownColor=downColor;
- if (IFrameSplitOperator.IsNumber(stickType)) value.StickType=stickType;
- this.OutVarTable.push(value);
- }
- else if (lineArea && varName) //LINEAREA 面积
- {
- let outVar=this.VarTable.get(varName);
- let value={Name:varName, Data:outVar, Type:9};
- if (color) value.Color=color;
- if (upColor) value.UpColor=upColor;
- if (downColor) value.DownColor=downColor;
- if (lineWidth) value.LineWidth=lineWidth;
- this.OutVarTable.push(value);
- }
- else if (colorStick && varName) //CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子
- {
- let outVar=this.VarTable.get(varName);
- let value={Name:varName, Data:outVar, Color:color, Type:2};
- if (lineWidth) value.LineWidth=lineWidth;
- if (color) value.Color=color;
- if (upColor) value.UpColor=upColor;
- if (downColor) value.DownColor=downColor;
- this.OutVarTable.push(value);
- }
- else if (varName && color && !draw)
- {
- let outVar=this.VarTable.get(varName);
- let value={Name:varName, Data:outVar, Color:color, Type:0};
- if (lineWidth) value.LineWidth=lineWidth;
- if (isShow == false) value.IsShow = false;
- if (isExData == true) value.IsExData = true;
- if (IFrameSplitOperator.IsBool(isDotLine)) value.IsDotLine = isDotLine;
- if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) value.LineDash=lineDash;
- if (isOverlayLine == true) value.IsOverlayLine = true;
- if (isSingleLine == true) value.IsSingleLine = true;
- if (isNoneName==true) value.NoneName=true;
- if (isShowTitle==false) value.IsShowTitle=false;
- if (stepLine==true) value.Type=7;
- this.OutVarTable.push(value);
- }
- else if (draw) //绘图函数
- {
- var outVar = { Name: draw.Name, Draw: draw, Type: 1 };
- if (color) outVar.Color = color;
- if (IFrameSplitOperator.IsBool(isDotLine)) outVar.IsDotLine=isDotLine;
- if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) outVar.LineDash=lineDash;
- if (lineWidth) outVar.LineWidth = lineWidth;
- if (isDrawAbove) outVar.IsDrawAbove=true;
- if (drawAlign>=0) outVar.DrawAlign=drawAlign;
- if (drawVAlign>=0) outVar.DrawVAlign=drawVAlign;
- if (fontSize>0) outVar.DrawFontSize=fontSize;
- if (bgConfig) outVar.Background=bgConfig;
- if (vLineConfig) outVar.VerticalLine=vLineConfig;
- if (IFrameSplitOperator.IsNumber(xOffset)) outVar.XOffset=xOffset;
- if (IFrameSplitOperator.IsNumber(yOffset)) outVar.YOffset=yOffset;
- this.OutVarTable.push(outVar);
- }
- else if (varName)
- {
- let outVar = this.VarTable.get(varName);
- let value = { Name: varName, Data: outVar, Type: 0 };
- if (color) value.Color = color;
- if (lineWidth) value.LineWidth = lineWidth;
- if (isShow == false) value.IsShow = false;
- if (isExData == true) value.IsExData = true;
- if (isDotLine == true) value.IsDotLine = true;
- if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) value.LineDash=lineDash;
- if (isOverlayLine == true) value.IsOverlayLine = true;
- if (isSingleLine == true) value.IsSingleLine = true;
- if (isShowTitle==false) value.IsShowTitle=false;
- if (stepLine==true) value.Type=7;
- this.OutVarTable.push(value);
- }
- }
- }
- if (this.Interrupt && this.Interrupt.Exit)
- {
- JSConsole.Complier.Log('[JSExecute::RunAST] Interrupt', this.Interrupt); //中断退出
- break;
- }
- }
- JSConsole.Complier.Log('[JSExecute::RunAST]', this.VarTable);
- return this.OutVarTable;
- }
- this.ReadUnaryExpression=function(item, varInfo)
- {
- var argument=item.Argument;
- var outVar=null;
- if (argument.Type==Syntax.Literal)
- {
- outVar=argument.Value;
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- }
- else if (argument.Type==Syntax.Identifier)
- {
- var varName=argument.Name;
- outVar=this.ReadVariable(varName,item.Expression);
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- }
- else if (argument.Type==Syntax.BinaryExpression)
- {
- outVar=argument.Out;
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- }
- else if (argument.Type==Syntax.CallExpression)
- {
- var callItem=argument;
- if (this.Draw.IsDrawFunction(callItem.Callee.Name) )
- {
- return false;
- }
- else if (callItem.Callee.Name==="IFC" && callItem.Draw)
- {
- return false;
- }
- else
- {
- outVar=callItem.Out;
- if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
- }
- }
- else
- {
- return false;
- }
-
- if (item.Operator=='-')
- {
- if (outVar) outVar=this.Algorithm.Subtract(0,outVar);
- }
- varInfo.OutVar=outVar;
- return true;
- }
- this.GetOutIconData=function(cond, iconDraw)
- {
- if (Array.isArray(cond))
- {
- for(var i=0; i<cond.length && i<iconDraw.DrawData.length; ++i)
- {
- var item=cond[i];
- if (item<=0) iconDraw.DrawData[i]=null;
- }
- return iconDraw;
- }
- if (cond) return iconDraw;
- return null;
- }
- this.GetSoundEvent=function()
- {
- if (!this.GetEventCallback) return null;
- return this.GetEventCallback(JSCHART_EVENT_ID.ON_PLAY_SOUND);
- }
- this.Run=function()
- {
- let data=this.RunAST();//执行脚本
- JSConsole.Complier.Log('[JSComplier.Run] execute finish', data);
-
- if (this.UpdateUICallback)
- {
- JSConsole.Complier.Log('[JSComplier.Run] invoke UpdateUICallback.');
- if (this.CallbackParam && this.CallbackParam.Job && this.CallbackParam.Job.ID==JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX)
- {
- this.UpdateUICallback(data,this.CallbackParam, this.SymbolData);
- }
- else
- {
- if (this.CallbackParam && this.CallbackParam.Self && this.CallbackParam.Self.ClassName==='ScriptIndexConsole') this.CallbackParam.JSExecute=this;
- if (this.IsUsePageData==true) this.CallbackParam.Self.IsUsePageData=true;
- this.UpdateUICallback(data,this.CallbackParam);
- }
-
- }
- }
- this.VisitNode=function(node)
- {
- switch(node.Type)
- {
- case Syntax.SequenceExpression:
- this.VisitSequenceExpression(node);
- break;
- case Syntax.ExpressionStatement:
- this.VisitNode(node.Expression);
- break;
- case Syntax.AssignmentExpression:
- this.VisitAssignmentExpression(node);
- break;
- case Syntax.BinaryExpression:
- case Syntax.LogicalExpression:
- this.VisitBinaryExpression(node);
- break;
- case Syntax.CallExpression:
- this.VisitCallExpression(node);
- break;
- case Syntax.UnaryExpression:
- this.VisitUnaryExpression(node);
- break;
- }
- }
- this.VisitSequenceExpression=function(node)
- {
- for(let i in node.Expression)
- {
- let item =node.Expression[i];
- this.VisitNode(item);
- }
- }
- this.VisitUnaryExpression=function(node)
- {
- if (node.Operator=='-')
- {
- var tempValue=this.GetNodeValueEx(node.Argument);
- var value=this.Algorithm.Subtract(0,tempValue);
- }
- else
- {
- var value=node.Argument.Value;
- }
- return value;
- }
- this.GetDynamicScriptIndex=function(node, args)
- {
- var dynamicName=node.Callee.Value;
- var aryValue=dynamicName.split(".");
- if (aryValue.length!=2)
- {
- this.ThrowUnexpectedNode(node,`调用指标格式'${dynamicName}'错误`);
- }
- var name=aryValue[0];
- var outName=aryValue[1];
- var period=null;
- var pos=outName.indexOf('#');
- if (pos!=-1)
- {
- period=outName.slice(pos+1); //周期
- outName=outName.slice(0,pos);
- }
- var strValue="";
- for(var i=0; i<args.length; ++i)
- {
- var value=args[i];
- if (strValue.length>0) strValue+=",";
- strValue+=`${value}`;
- }
- var strArgs=`(${strValue})`;
- var key=`${outName}#${strArgs}`;
- if (period) key+=`#${period}`;
-
- if (!this.VarTable.has(name)) return null;
- var indexData=this.VarTable.get(name);
- var value=indexData[key];
- return value;
- }
- //函数调用
- this.VisitCallExpression=function(node)
- {
- let funcName=node.Callee.Name;
- let args=[];
- for(let i=0; i<node.Arguments.length; ++i)
- {
- let item=node.Arguments[i];
- let value;
- if (funcName==="IFC" && i>=1)
- break; //IFC先处理第1个条件参数
- if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
- value=this.VisitBinaryExpression(item);
- else if (item.Type==Syntax.CallExpression)
- value=this.VisitCallExpression(item);
- else
- value=this.GetNodeValue(item);
- args.push(value);
- }
- if (node.Callee.Type==Syntax.Literal) //指标调用'MA.MA1'(6,12,18)
- {
- node.Out=[];
- node.Draw=null;
- var data=this.GetDynamicScriptIndex(node, args);
- if (data) node.Out=data;
- return node.Out;
- }
- if (funcName==="IFC")
- {
- //IFC(X,A,B)若X不为0则执行A,否则执行B.IFC与IF函数的区别:根据X的值来选择性执行A、B表达式.
- var bResult=this.Algorithm.IFC(args[0]);
- var item=bResult? node.Arguments[1] : node.Arguments[2];
- var value;
- if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
- value=this.VisitBinaryExpression(item);
- else if (item.Type==Syntax.CallExpression)
- value=this.VisitCallExpression(item);
- else
- value=this.GetNodeValue(item);
- node.Out=value;
- if (item.Draw) node.Draw=item.Draw;
- return node.Out;
- }
- //if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitCallExpression]' , funcName, '(', args.toString() ,')');
- if (g_JSComplierResource.IsCustomFunction(funcName)) //自定义函数
- {
- var data=this.Algorithm.CallCustomFunction(funcName, args, this.SymbolData, node);
- node.Out=[];
- node.Draw=null;
- if (data)
- {
- if (data.Out) node.Out=data.Out;
- if (data.Draw) node.Draw=data.Draw;
- }
- return node.Out;
- }
- if (g_JSComplierResource.IsCustomDataFunction(funcName))
- {
- var functionInfo=g_JSComplierResource.CustomDataFunction.Data.get(funcName);
- node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:functionInfo.ArgCount, Node:node } );
- node.Draw=null;
- return node.Out;
- }
- switch(funcName)
- {
- case 'DYNAINFO': //行情最新数据
- node.Out=this.SymbolData.GetLatestCacheData(args[0]);
- break;
- case 'STICKLINE':
- node.Draw=this.Draw.STICKLINE(args[0],args[1],args[2],args[3],args[4]);
- node.Out=[];
- break;
- case 'DRAWTEXT':
- node.Draw=this.Draw.DRAWTEXT(args[0],args[1],args[2]);
- node.Out=[];
- break;
- case 'SUPERDRAWTEXT':
- node.Draw = this.Draw.SUPERDRAWTEXT(args[0], args[1], args[2], args[3], args[4]);
- node.Out = [];
- break;
- case 'DRAWTEXT_FIX':
- node.Draw=this.Draw.DRAWTEXT_FIX(args[0],args[1],args[2],args[3],args[4]);
- node.Out=[];
- break;
- case "DRAWNUMBER_FIX":
- node.Draw=this.Draw.DRAWNUMBER_FIX(args[0],args[1],args[2],args[3],args[4],args[5]);
- node.Out=[];
- break;
- case 'DRAWICON':
- node.Draw = this.Draw.DRAWICON(args[0], args[1], args[2], args[3]);
- node.Out = [];
- break;
- case "ICON":
- node.Draw=this.Draw.ICON(args[0],args[1]);
- node.Out=[];
- break;
- case "BACKGROUND":
- node.Draw=this.Draw.BACKGROUND(args[0],args[1],args[2],args[3],args[4],args[5]);
- node.Out=[];
- break;
- case "CKLINE":
- node.Draw=this.Draw.CKLINE(args[0],args[1],args[2],args[3],args[4]);
- node.Out=[];
- break;
- case 'DRAWLINE':
- node.Draw=this.Draw.DRAWLINE(args[0],args[1],args[2],args[3],args[4]);
- node.Out=node.Draw.DrawData;
- break;
- case 'DRAWBAND':
- node.Draw=this.Draw.DRAWBAND(args[0],args[1],args[2],args[3]);
- node.Out=[];
- break;
- case 'DRAWKLINE':
- case "DRAWKLINE1":
- node.Draw = this.Draw.DRAWKLINE(args[0], args[1], args[2], args[3]);
- node.Out = [];
- break;
- case 'DRAWKLINE_IF':
- node.Draw = this.Draw.DRAWKLINE_IF(args[0], args[1], args[2], args[3], args[4]);
- node.Out = [];
- break;
- case "DRAWCOLORKLINE":
- node.Draw=this.Draw.DRAWCOLORKLINE(args[0],args[1],args[2]);
- node.Out=[];
- break;
- case 'PLOYLINE':
- case 'POLYLINE':
- node.Draw = this.Draw.POLYLINE(args[0], args[1]);
- node.Out = node.Draw.DrawData;
- break;
- case 'DRAWNUMBER':
- node.Draw = this.Draw.DRAWNUMBER(args[0], args[1], args[2], args[3]);
- node.Out = node.Draw.DrawData.Value;
- break;
- case 'RGB':
- node.Out = this.Draw.RGB(args[0], args[1], args[2]);
- break;
- case 'RGBA':
- node.Out = this.Draw.RGBA(args[0], args[1], args[2],args[3]);
- break;
- case "UPCOLOR":
- node.Out=this.Draw.UPCOLOR(args[0]);
- break;
- case "DOWNCOLOR":
- node.Out=this.Draw.DOWNCOLOR(args[0]);
- break;
- case "STICKTYPE":
- node.Out=this.Draw.STICKTYPE(args[0]);
- break;
- case "XMOVE":
- node.Out=this.Draw.XMOVE(args[0]);
- break;
- case "YMOVE":
- node.Out=this.Draw.YMOVE(args[0]);
- break;
- case "LINEDASH":
- node.Out=this.Draw.LINEDASH(args);
- break;
- case 'PARTLINE':
- node.Draw=this.Draw.PARTLINE(args);
- node.Out=[];
- break;
- case 'DRAWRECTREL':
- node.Draw = this.Draw.DRAWRECTREL(args[0], args[1], args[2], args[3], args[4]);
- node.Out = [];
- break;
- case "DRAWTEXTREL":
- node.Draw=this.Draw.DRAWTEXTREL(args[0],args[1],args[2]);
- node.Out=[];
- break;
- case "DRAWTEXTABS":
- node.Draw=this.Draw.DRAWTEXTABS(args[0],args[1],args[2]);
- node.Out=[];
- break;
- case 'DRAWGBK':
- node.Draw=this.Draw.DRAWGBK(args[0],args[1],args[2],args[3]);
- node.Out=[];
- break;
- case 'DRAWGBK2':
- node.Draw=this.Draw.DRAWGBK2(args[0],args[1],args[2],args[3]);
- node.Out=[];
- break;
- case "DRAWGBK_DIV":
- node.Draw=this.Draw.DRAWGBK_DIV(args[0],args[1],args[2],args[3],args[4]);
- node.Out=[];
- break;
- case 'CODELIKE':
- node.Out=this.SymbolData.CODELIKE(args[0]);
- break;
- case 'NAMELIKE':
- case "NAMEINCLUDE":
- node.Out = this.SymbolData.NAMELIKE(args[1]);
- break;
- case 'REFDATE':
- node.Out = this.SymbolData.REFDATE(args[0], args[1]);
- break;
- case 'FINANCE':
- node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } );
- break;
- case "FINVALUE":
- node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } );
- break;
- case "FINONE":
- node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } );
- break;
- case "GPJYVALUE":
- case "SCJYVALUE":
- case "BKJYVALUE":
- node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } );
- break;
- case "GPJYONE":
- case "SCJYONE":
- case "BKJYONE":
- node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:4, Node:node } );
- break;
- case "MARGIN":
- node.Out = this.SymbolData.GetMarginCacheData(args[0], node);
- break;
- case "NEWS":
- node.Out = this.SymbolData.GetNewsAnalysisCacheData(args[0], node);
- break;
- case 'UPCOUNT':
- case 'DOWNCOUNT':
- node.Out = this.SymbolData.GetIndexIncreaseCacheData(funcName, args[0], node);
- break;
- case 'LOADAPIDATA':
- node.Out = this.SymbolData.GetCustomApiData(args);
- break;
- case "STKINDI":
- case "CALCSTOCKINDEX":
- node.Out=this.SymbolData.GetScriptIndexOutData(args,node,funcName);
- break;
- case 'CLOSE':
- case 'C':
- case 'VOL':
- case 'V':
- case 'OPEN':
- case 'O':
- case 'HIGH':
- case 'H':
- case 'LOW':
- case 'L':
- case 'AMOUNT':
- case 'AMO':
- node.Out=this.SymbolData.GetOtherSymolCacheData( {FunctionName:funcName, Args:args} );
- break;
- case "INBLOCK":
- node.Out=this.SymbolData.IsInBlock(args[0],node);
- break;
- case "SYSPARAM":
- node.Out=this.SymbolData.SysParam(args[0], this);
- break;
- case "TESTSKIP":
- var bExit=this.Algorithm.TESTSKIP(args[0],node);
- node.Out=null;
- if (bExit)
- {
- this.Interrupt.Exit=true;
- if (node && node.Marker)
- {
- var marker=node.Marker;
- this.Interrupt.Line=marker.Line;
- this.Interrupt.Index=marker.Index;
- this.Interrupt.Column=marker.Column;
- }
- }
- break;
- default:
- node.Out=this.Algorithm.CallFunction(funcName, args,node);
- break;
- }
- return node.Out;
- }
- //赋值
- this.VisitAssignmentExpression=function(node)
- {
- let left=node.Left;
- if (left.Type!=Syntax.Identifier) this.ThrowUnexpectedNode(node);
- let varName=left.Name;
- let right=node.Right;
- let value=null,drawValue=null;
- if (right.Type==Syntax.BinaryExpression || right.Type==Syntax.LogicalExpression)
- value=this.VisitBinaryExpression(right);
- else if (right.Type==Syntax.CallExpression)
- {
- value=this.VisitCallExpression(right);
- if (right.Draw) drawValue=right.Draw;
- }
- else if (right.Type==Syntax.Literal)
- {
- value=right.Value;
- if (IFrameSplitOperator.IsString(value) && right.Value.indexOf("$")>0)
- value=this.SymbolData.GetOtherSymolCacheData( {Literal:value} );
- }
- else if (right.Type==Syntax.Identifier) //右值是变量
- value=this.ReadVariable(right.Name,right);
- else if (right.Type == Syntax.MemberExpression)
- value = this.ReadMemberVariable(right);
- else if (right.Type==Syntax.UnaryExpression)
- value=this.VisitUnaryExpression(right);
- if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitAssignmentExpression]' , varName, ' = ',value);
- if (drawValue) this.VarDrawTable.set(varName, drawValue);
- this.VarTable.set(varName,value);
- }
- //逻辑运算
- this.VisitBinaryExpression=function(node)
- {
- let stack=[];
- stack.push(node);
- let temp=null;
- while(stack.length!=0)
- {
- temp=stack[stack.length-1];
- if (temp.Left && node!=temp.Left && node!=temp.Right)
- {
- stack.push(temp.Left);
- }
- else if (temp.Right && node!=temp.Right)
- {
- stack.push(temp.Right);
- }
- else
- {
- let value=stack.pop();
- if (value.Type==Syntax.BinaryExpression) //只遍历操作符就可以
- {
- let leftValue=this.GetNodeValue(value.Left);
- let rightValue=this.GetNodeValue(value.Right);
- if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue);
- value.Out=null; //保存中间值
- switch(value.Operator)
- {
- case '-':
- value.Out=this.Algorithm.Subtract(leftValue,rightValue);
- break;
- case '*':
- value.Out=this.Algorithm.Multiply(leftValue,rightValue);
- break;
- case '/':
- value.Out=this.Algorithm.Divide(leftValue,rightValue)
- break;
- case '+':
- value.Out=this.Algorithm.Add(leftValue,rightValue);
- break;
- case '>':
- value.Out=this.Algorithm.GT(leftValue,rightValue);
- break;
- case '>=':
- value.Out=this.Algorithm.GTE(leftValue,rightValue);
- break;
- case '<':
- value.Out=this.Algorithm.LT(leftValue,rightValue);
- break;
- case '<=':
- value.Out=this.Algorithm.LTE(leftValue,rightValue);
- break;
- case '==':
- case '=':
- value.Out=this.Algorithm.EQ(leftValue,rightValue);
- break;
- case '!=':
- case '<>':
- value.Out = this.Algorithm.NEQ(leftValue, rightValue);
- break;
- }
- if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value);
- }
- else if (value.Type==Syntax.LogicalExpression)
- {
- let leftValue=this.GetNodeValue(value.Left);
- let rightValue=this.GetNodeValue(value.Right);
- if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue);
- value.Out=null; //保存中间值
- switch(value.Operator)
- {
- case '&&':
- case 'AND':
- value.Out=this.Algorithm.And(leftValue,rightValue);
- break;
- case '||':
- case 'OR':
- value.Out=this.Algorithm.Or(leftValue,rightValue);
- break;
- }
- if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value);
- }
-
- node=temp;
- }
- }
- return node.Out;
- }
- //获取节点值,BinaryExpression,LogicalExpression会重新计算
- this.GetNodeValueEx=function(item)
- {
- var value=null;
- if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
- value=this.VisitBinaryExpression(item);
- else if (item.Type==Syntax.CallExpression)
- value=this.VisitCallExpression(item);
- else
- value=this.GetNodeValue(item);
- return value;
- }
- this.GetNodeValue=function(node)
- {
- switch(node.Type)
- {
- case Syntax.Literal: //数字
- return node.Value;
- case Syntax.UnaryExpression:
- var value=this.VisitUnaryExpression(node);
- return value;
- case Syntax.Identifier:
- var value=this.ReadVariable(node.Name,node);
- return value;
- case Syntax.BinaryExpression:
- case Syntax.LogicalExpression:
- return node.Out;
- case Syntax.CallExpression:
- return this.VisitCallExpression(node);
- case Syntax.MemberExpression:
- return this.ReadMemberVariable(node);
- default:
- this.ThrowUnexpectedNode(node);
- }
- }
- this.ThrowUnexpectedNode=function(node,message)
- {
- let marker=node.Marker;
- let msg=message || "执行异常";
-
- return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
-
- }
- this.ThrowError=function()
- {
- }
- }
- //对外导出类
- function JSComplier()
- {
-
- }
- //词法分析
- JSComplier.Tokenize=function(code)
- {
- JSConsole.Complier.Log('[JSComplier.Tokenize]', code);
- let tokenizer=new Tokenizer(code);
- let tokens=[];
- try
- {
- while(true)
- {
- let token=tokenizer.GetNextToken();
- if (!token) break;
- tokens.push(token);
- }
- }
- catch(e)
- {
- }
- return tokens;
- }
- //语法解析 生成抽象语法树(Abstract Syntax Tree)
- JSComplier.Parse=function(code)
- {
- JSConsole.Complier.Log('[JSComplier.Parse]',code);
- let parser=new JSParser(code);
- parser.Initialize();
- let program=parser.ParseScript();
- let ast=program;
- return ast;
- }
- //颜色转rgb
- JSComplier.ColorVarToRGB=function(colorName)
- {
- let COLOR_MAP=new Map(
- [
- ['COLORBLACK','rgb(0,0,0)'],
- ['COLORBLUE','rgb(18,95,216)'],
- ['COLORGREEN','rgb(25,158,0)'],
- ['COLORCYAN','rgb(0,255,198)'],
- ['COLORRED','rgb(238,21,21)'],
- ['COLORMAGENTA','rgb(255,0,222)'],
- ['COLORBROWN','rgb(149,94,15)'],
- ['COLORLIGRAY','rgb(218,218,218)'], //画淡灰色
- ['COLORGRAY','rgb(133,133,133)'], //画深灰色
- ['COLORLIBLUE','rgb(94,204,255)'], //淡蓝色
- ['COLORLIGREEN','rgb(183,255,190)'], //淡绿色
- ['COLORLICYAN','rgb(154,255,242)'], //淡青色
- ['COLORLIRED','rgb(255,172,172)'], //淡红色
- ['COLORLIMAGENTA','rgb(255,145,241)'], //淡洋红色
- ['COLORWHITE','rgb(255,255,255)'], //白色
- ['COLORYELLOW','rgb(255,198,0)']
- ]);
- if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName);
- //COLOR 自定义色
- //格式为COLOR+“BBGGRR”:BB、GG、RR表示蓝色、绿色和红色的分量,每种颜色的取值范围是00-FF,采用了16进制。
- //例如:MA5:MA(CLOSE,5),COLOR00FFFF表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。
- if (colorName.indexOf('COLOR')==0)
- {
- var strColor=colorName.substr(5);
- if (strColor.length!=6) return null;
-
- var value=strColor.substr(0,2);
- var b=parseInt(value,16);
- value=strColor.substr(2,2);
- var g=parseInt(value,16);
- value=strColor.substr(4,2);
- var r=parseInt(value,16);
-
- return `rgb(${r},${g},${b})`;
- }
- //格式为RGBX+“RRGGBB”:RR、GG、BB表示红色、绿色和的蓝色分量,每种颜色的取值范围是00-FF,采用了16进制。
- //例如:MA5:MA(CLOSE,5),RGBXFFFF00表示纯红色与纯绿色的混合色:RGBX008080表示淡蓝色和淡绿色的混合色。
- if (colorName.indexOf("RGBX")==0)
- {
- var strColor=colorName.substr(4);
- if (strColor.length!=6) return null;
- var value=strColor.substr(0,2);
- var r=parseInt(value,16);
- value=strColor.substr(2,2);
- var g=parseInt(value,16);
- value=strColor.substr(4,2);
- var b=parseInt(value,16);
-
- return `rgb(${r},${g},${b})`;
- }
- return null;
- }
- /*
- 执行
- option.Symbol=股票代码
- option.Name=股票名称
- option.Data=这个股票的ChartData
- option.Right=复权
- option.MaxRequestDataCount=请求数据的最大个数
- */
- JSComplier.Execute=function(code,option,errorCallback)
- {
- //异步调用
- var asyncExecute= function()
- {
- try
- {
- JSConsole.Complier.Log('[JSComplier.Execute] code ',code);
- JSConsole.Complier.Log('[JSComplier.Execute] parser .....');
- let parser=new JSParser(code);
- parser.Initialize();
- let program=parser.ParseScript();
-
- let ast=program;
- JSConsole.Complier.Log('[JSComplier.Execute] parser finish.', ast);
- JSConsole.Complier.Log('[JSComplier.Execute] execute .....');
- let execute=new JSExecute(ast,option);
- execute.JobList=parser.Node.GetDataJobList();
- execute.JobList.push({ID:JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT});
- let result=execute.Execute();
- }catch(error)
- {
- JSConsole.Complier.Log(error);
- if (errorCallback) errorCallback(error);
- }
- }
- asyncExecute();
- JSConsole.Complier.Log('[JSComplier.Execute] async execute.');
- }
- JSComplier.SetDomain = function (domain, cacheDomain)
- {
- if (domain) g_JSComplierResource.Domain = domain;
- if (cacheDomain) g_JSComplierResource.CacheDomain = cacheDomain;
- }
- JSComplier.AddFunction=function(obj) //添加函数 { Name:函数名, Description:描述信息, IsDownload:是否需要下载数据, Invoke:函数执行(可选) }
- {
- if (!obj || !obj.Name) return;
- var ID=obj.Name.toUpperCase();
- g_JSComplierResource.CustomFunction.Data.set(ID, obj);
- }
- JSComplier.AddVariant=function(obj) //{ Name:变量名, Description:描述信息 }
- {
- if (!obj || !obj.Name) return;
- var ID=obj.Name.toUpperCase();
- g_JSComplierResource.CustomVariant.Data.set(ID, obj);
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- //数据下载
- function DownloadFinanceData(obj)
- {
- this.Url=obj.Url;
- this.RealtimeUrl=obj.RealtimeUrl;
- this.Job=obj.Job;
- this.Symbol=obj.Symbol;
- this.Args=obj.Args;
- this.DataKey=obj.DataKey;
- this.RecvCallback=obj.Callback;
- this.ErrorCallback=obj.ErrorCallback;
-
- this.Download=function()
- {
- var id=this.Args[0];
- switch(id)
- {
- case 1: //FINANCE(1) 总股本(随时间可能有变化) 股
- case 7: //FINANCE(7) 流通股本(随时间可能有变化) 股
- case "EXCHANGE": //换手率
- this.DownloadHistoryData(id);
- break;
- case 9: //FINANCE(9) 资产负债率
- case 18: //FINANCE(18) 每股公积金
- case 30: //FINANCE(30) 净利润
- case 32: //FINANCE(32) 每股未分配利润
- case 33: //FINANCE(33) 每股收益(折算为全年收益),对于沪深品种有效
- case 34: //FINANCE(34) 每股净资产
- case 38: //FINANCE(38) 每股收益(最近一期季报)
- case 40: //FINANCE(40) 流通市值
- case 41: //FINANCE(41) 总市值
- case 42: //FINANCE(42) 上市的天数
- case 43: //FINANCE(43) 利润同比
- case "CAPITAL":
- case "TOTALCAPITAL":
- //定制
- case 100: //股东人数
- this.DownloadRealtimeData(id);
- break;
-
- default:
- this.DownloadRealtimeData(id);
- break;
- }
- }
- //最新一期数据
- this.DownloadRealtimeData=function(id)
- {
- var self=this;
- var fieldList=this.GetFieldList();
- if (!fieldList)
- {
- if (this.Job.FunctionName2) message=`${this.Job.FunctionName2} can't support.`;
- else if (this.Job.FunctionName) message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
- else message=`${this.Args[0]} can't support.`;
- this.ErrorCallback(message);
- self.RecvCallback(null, self.Job, self.DataKey);
- return;
- }
- //请求数据
- JSNetwork.HttpRequest({
- url: this.RealtimeUrl,
- data:
- {
- "field": fieldList,
- "symbol": [this.Symbol],
- "condition":[ ] ,
- "start": 0,
- "end": 10
- },
- method: 'POST',
- dataType: "json",
- async:true,
- success: function (recvData)
- {
- var data=self.RealtimeDataToHQChartData(recvData.data);
- self.RecvCallback(data, self.Job, self.DataKey);
- }
- });
- }
- //历史数据
- this.DownloadHistoryData=function(id)
- {
- var self=this;
- var fieldList=this.GetFieldList();
- if (!fieldList)
- {
- message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
- this.ErrorCallback(message);
- self.RecvCallback(null, self.Job, self.DataKey);
- return;
- }
- //请求数据
- JSNetwork.HttpRequest({
- url: this.Url,
- data:
- {
- "field": fieldList,
- "symbol": [this.Symbol],
- "condition":[ ] ,
- "start": 0,
- "end": 200
- },
- method: 'POST',
- dataType: "json",
- async:true,
- success: function (recvData)
- {
- var data=self.ToHQChartData(recvData.data);
- if (data) //排序
- data.sort(function (a, b) { return (a.Date - b.Date) });
- self.RecvCallback(data, self.Job, self.DataKey);
- }
- });
- }
- this.GetFieldList=function()
- {
- var id=this.Args[0];
- switch(id)
- {
- case 1:
- return ["capital.total", "capital.date"];
- case 7:
- return ["capital.a", "capital.date"];
- case "EXCHANGE":
- return ["capital.a", "capital.date"];
- case 9:
- return ["finance.peruprofit","symbol","date"];
- case 18:
- return ["finance.percreserve","symbol","date"];
- case 30:
- return ["finance.nprofit","symbol","date"];
- case 32:
- return ["finance.peruprofit","symbol","date"];
- case 33:
- return ["finance.persearning","symbol","date"];
- case 34:
- return ["finance.pernetasset","symbol","date"];
- case 38:
- return ["finance.persearning","symbol","date"];
- case 40:
- return ["capital.a", "capital.date","symbol","date", "price"];
- case 41:
- return ["capital.total", "capital.date","symbol","date","price"];
- case "CAPITAL":
- return ["capital.a", "capital.date","symbol","date"];
- case "TOTALCAPITAL":
- return ["capital.total", "capital.date","symbol","date"];
- case 42:
- return ["company.releasedate","symbol","date"];
- case 43:
- return ["dividendyield","symbol","date"];
- case 100:
- return ["shareholder","symbol","date"]
- default:
- return null;
- }
- }
- //最新报告期数据
- this.RealtimeDataToHQChartData=function(recvData,id)
- {
- if (!recvData.stock || recvData.stock.length!=1) return null;
- var stock=recvData.stock[0];
- var id=this.Args[0];
- var date=stock.date;
- switch(id)
- {
- case 9:
- if (!stock.finance) return null;
- return { Date:date, Value:stock.finance.peruprofit };
- case 18:
- if (!stock.finance) return null;
- return { Date:date, Value:stock.finance.percreserve };
- case 30:
- if (!stock.finance) return null;
- return { Date:date, Value:stock.finance.nprofit };
- case 32:
- if (!stock.finance) return null;
- return { Date:date, Value:stock.finance.peruprofit };
- case 33:
- if (!stock.finance) return null;
- return { Date:date, Value:stock.finance.persearning };
- case 34:
- if (!stock.finance) return null;
- return { Date:date, Value:stock.finance.pernetasset };
- case 38:
- if (!stock.finance) return null;
- return { Date:date, Value:stock.finance.persearning };
- case 40: //FINANCE(40) 流通市值
- if (!stock.capital) return null;
- return { Date:date, Value:stock.capital.a*stock.price }; //流通股*最新价格
- case 41: //FINANCE(41) 总市值
- if (!stock.capital) return null;
- return { Date:date, Value:stock.capital.total*stock.price }; //总股本*最新价格
- case 42: //FINANCE(42) 上市的天数
- if (!stock.company) return null;
- {
- var releaseDate=stock.company.releasedate;
- var year=parseInt(releaseDate/10000);
- var month=parseInt((releaseDate%10000)/100);
- var day=releaseDate%100;
- var firstDate=new Date(year, month-1, day);
- var nowDate=new Date();
- var days=parseInt((nowDate.getTime()-firstDate.getTime())/(1000 * 60 * 60 * 24));
- return { Date:date, Value:days+1 };
- }
- case 43:
- if (!stock.dividendyield) return null;
- return { Date:date, Value:stock.dividendyield.quarter4 };
- case 100:
- if (!stock.shareholder) return null;
- return { Date:date, Value:stock.shareholder.count };
- case "CAPITAL":
- if (!stock.capital) return null;
- return { Date:date, Value:stock.capital.a/100 }; //当前流通股本 手
- case "TOTALCAPITAL":
- if (!stock.capital) return null;
- return { Date:date, Value:stock.capital.total/100 }; //当前流通股本 手
- }
- }
- //历史数据转
- this.ToHQChartData=function(recvData)
- {
- if (!recvData.stock || recvData.stock.length!=1) return null;
- var aryData=[];
- var setDate=new Set(); //有重复数据 去掉
- var stock=recvData.stock[0];
- var id=this.Args[0];
- for(var i in stock.stockday)
- {
- var item=stock.stockday[i];
- var hqchartItem=this.ToHQChartItemData(item,id);
- if (hqchartItem && !setDate.has(hqchartItem.Date))
- {
- aryData.push(hqchartItem);
- setDate.add(hqchartItem.Date);
- }
- }
- return aryData;
- }
- this.ToHQChartItemData=function(item, id)
- {
- if (!item) return null;
- var date=item.date;
- switch(id)
- {
- case 1:
- if (!item.capital) return null;
- return { Date:date, Value:item.capital.total };
- case 7:
- case "EXCHANGE": //换手率 历史流通股本
- if (!item.capital) return null;
- return { Date:date, Value:item.capital.a };
-
- default:
- return null;
- }
- }
- }
- function DownloadGroupData(obj)
- {
- this.Url=obj.Url;
- this.RealtimeUrl=obj.RealtimeUrl;
- this.Job=obj.Job;
- this.Symbol=obj.Symbol;
- this.Args=obj.Args;
- this.DataKey=obj.DataKey;
- this.RecvCallback=obj.Callback;
- this.ErrorCallback=obj.ErrorCallback;
- this.Download=function()
- {
- var varName=this.Args[0];
- switch(varName)
- {
- case "HYBLOCK":
- case "DYBLOCK":
- case "GNBLOCK":
- this.DownloadGroupName(varName);
- break;
- }
- }
- this.DownloadGroupName=function(blockType)
- {
- var self=this;
- var field=["name","symbol"];
- if (blockType=="HYBLOCK") field.push("industry");
- else if (blockType=="DYBLOCK") field.push("region");
- else if (blockType=="GNBLOCK") field.push("concept");
- JSNetwork.HttpRequest({
- url: self.RealtimeUrl,
- data:
- {
- "field": field,
- "symbol": [this.Symbol]
- },
- method:"post",
- dataType: "json",
- async:true,
- success: function (recvData)
- {
- var data=self.RecvGroupName(recvData.data);
- self.RecvCallback(data, self.Job, self.DataKey, 1);
- },
- error: function(request)
- {
- self.ErrorCallback(request);
- }
- });
- }
- this.RecvGroupName=function(recvData)
- {
- if (!recvData.stock || recvData.stock.length!=1) return null;
- var stock=recvData.stock[0];
- var varName=this.Args[0];
- var value=null;
- if (varName=="HYBLOCK")
- {
- var industry=stock.industry;
- if (!industry) return null;
- var value;
- for(var i in industry)
- {
- var item=industry[i];
- value=item.name;
- }
- }
- else if (varName=="DYBLOCK")
- {
- var region=stock.region;
- if (!region) return null;
- for(var i in region)
- {
- var item=region[i];
- value=item.name;
- }
- }
- else if (varName=="GNBLOCK")
- {
- var concept=stock.concept;
- if (!concept) return null;
- value="";
- for(var i in concept)
- {
- var item=concept[i];
- if (value.length>0) value+=' ';
- value+=item.name;
- }
-
- }
- return { Value:value };
- }
- }
- /* 测试例子
- var code1='VARHIGH:IF(VAR1<=REF(HH,-1),REF(H,BARSLAST(VAR1>=REF(HH,1))),DRAWNULL),COLORYELLOW;';
- var code2='VAR1=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);';
- var code3='mm1=1-2*-9+20;';
- JSConsole.Complier.Log(code1+code2)
- var tokens=JSComplier.Tokenize(code1+code2);
- var ast=JSComplier.Parse(code2+code1);
- JSConsole.Complier.Log(ast);
- */
- var JSCommonComplier=
- {
- JSComplier: JSComplier,
- g_JSComplierResource: g_JSComplierResource,
- };
- export
- {
- JSCommonComplier,
- ErrorHandler,
- JSComplier,
- JSParser,
- Syntax,
- JS_EXECUTE_JOB_ID,
- g_JSComplierResource,
- };
- /*
- module.exports =
- {
- JSCommonComplier:
- {
- JSComplier: JSComplier,
- g_JSComplierResource: g_JSComplierResource,
- },
- //单个类导出
- JSCommonComplier_ErrorHandler: ErrorHandler,
- JSCommonComplier_JSComplier:JSComplier,
- JSCommonComplier_JSParser:JSParser,
- JSCommonComplier_Syntax:Syntax,
- JS_EXECUTE_JOB_ID:JS_EXECUTE_JOB_ID,
- g_JSComplierResource:g_JSComplierResource,
- };
- */
|