umychart.complier.wechat.js 513 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391
  1. /*
  2. copyright (c) 2018 jones
  3. http://www.apache.org/licenses/LICENSE-2.0
  4. 开源项目 https://github.com/jones2000/HQChart
  5. jones_2000@163.com
  6. 分析家语法编译器
  7. */
  8. //日志
  9. import { JSConsole } from "./umychart.console.wechat.js"
  10. import { JSCommonData } from "./umychart.data.wechat.js"; //行情数据结构体 及涉及到的行情算法(复权,周期等)
  11. import { JSNetwork } from "./umychart.network.wechart.js"
  12. //配色资源
  13. import {
  14. g_JSChartResource,
  15. JSCHART_LANGUAGE_ID,
  16. g_JSChartLocalization,
  17. } from './umychart.resource.wechat.js'
  18. import
  19. {
  20. IFrameSplitOperator,
  21. } from './umychart.framesplit.wechat.js'
  22. import
  23. {
  24. JSIndexScript,
  25. } from './umychart.index.data.wechat.js'
  26. import {
  27. HQ_DATA_TYPE,
  28. ChartData, HistoryData,
  29. SingleData, MinuteData,
  30. } from "./umychart.data.wechat.js";
  31. import
  32. {
  33. g_MinuteCoordinateData,
  34. MARKET_SUFFIX_NAME ,
  35. } from "./umychart.coordinatedata.wechat.js";
  36. var g_JSComplierResource=
  37. {
  38. Domain : "http://127.0.0.1:8080", //API域名
  39. CacheDomain : "http://127.0.0.1:8087", //缓存域名
  40. CustomFunction: //定制函数
  41. {
  42. Data:new Map() //自定义函数 key=函数名, Value:{ID:函数名, Callback: }
  43. },
  44. CustomDataFunction: //自定义数据函数
  45. {
  46. //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息, ArgCount:参数个数 }
  47. Data:new Map(
  48. [
  49. [
  50. "L2_VOLNUM",
  51. {
  52. Name:"L2_VOLNUM",
  53. Description:"单数分档,按: N(0--1):(超大+大)/(中+小),M(0--1):买/卖二类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
  54. ArgCount:2
  55. }
  56. ],
  57. [
  58. "L2_VOL",
  59. {
  60. Name:"L2_VOL",
  61. Description:"成交量分档,按: N(0--3):超大/大/中/小四档处理,M(0--3):买入/卖出/主买/主卖四类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
  62. ArgCount:2
  63. }
  64. ],
  65. [
  66. "L2_AMO",
  67. {
  68. Name:"L2_AMO",
  69. Description:"成交额分档,按: N(0--3):超大/大/中/小四档处理,M(0--3):买入/卖出/主买/主卖四类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
  70. ArgCount:2
  71. }
  72. ]
  73. ])
  74. },
  75. CustomVariant: //自定义变量
  76. {
  77. Data:new Map() //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息 }
  78. },
  79. IsCustomFunction:function(name)
  80. {
  81. if (g_JSComplierResource.CustomFunction.Data.has(name)) return true;
  82. return false;
  83. },
  84. IsCustomDataFunction:function(name)
  85. {
  86. if (g_JSComplierResource.CustomDataFunction.Data.has(name)) return true;
  87. return false;
  88. },
  89. IsCustomVariant:function(name)
  90. {
  91. if (g_JSComplierResource.CustomVariant.Data.has(name)) return true;
  92. return false;
  93. },
  94. GetDrawTextIcon:function(id)
  95. {
  96. //图标对应的字符代码
  97. let mapIcon=new Map(
  98. [
  99. [1,{Symbol:'↑',Color:'rgb(238,44,44)'} ],[2,{Symbol:'↓',Color:'rgb(0,139,69)'} ],
  100. [3,{Symbol:'😧'} ],[4,{Symbol:'😨'} ],[5,{Symbol:'😁'} ],[6,{Symbol:'😱'} ],
  101. [7,{Symbol:'B',Color:'rgb(238,44,44)'} ],[8,{Symbol:'S',Color:'rgb(0,139,69)'} ],
  102. [9,{Symbol:'💰'} ],[10,{Symbol:'📪'} ],[11,{Symbol:'👆'} ],[12,{Symbol:'👇'} ],
  103. [13,{Symbol:'B',Color:'rgb(178,34,34)'}, ],[14,{Symbol:'S',Color:'rgb(0,139,69)'} ],
  104. [36,{Symbol:'Χ',Color:'rgb(238,44,44)'} ],[37,{Symbol:'X',Color:'rgb(0,139,69)'} ],
  105. [38,{Symbol:'▲',Color:'rgb(238,44,44)'} ],[39,{Symbol:'▼',Color:'rgb(0,139,69)'} ],
  106. [40,{Symbol:'◉',Color:'rgb(238,44,44)'}], [41,{Symbol:'◈',Color:'rgb(238,44,44)'}],
  107. [42,{Symbol:'📌'}], [43,{Symbol:'💎'}], [44,{Symbol:'🥇'}],[45,{Symbol:'🥈'}],[46,{Symbol:'🥉'}],[47,{Symbol:'🏅'}]
  108. ]);
  109. var icon=mapIcon.get(id);
  110. return icon;
  111. },
  112. }
  113. var Messages = {
  114. BadGetterArity: 'Getter must not have any formal parameters',
  115. BadSetterArity: 'Setter must have exactly one formal parameter',
  116. BadSetterRestParameter: 'Setter function argument must not be a rest parameter',
  117. ConstructorIsAsync: 'Class constructor may not be an async method',
  118. ConstructorSpecialMethod: 'Class constructor may not be an accessor',
  119. DeclarationMissingInitializer: 'Missing initializer in %0 declaration',
  120. DefaultRestParameter: 'Unexpected token =',
  121. DuplicateBinding: 'Duplicate binding %0',
  122. DuplicateConstructor: 'A class may only have one constructor',
  123. DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
  124. ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer',
  125. GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts',
  126. IllegalBreak: 'Illegal break statement',
  127. IllegalContinue: 'Illegal continue statement',
  128. IllegalExportDeclaration: 'Unexpected token',
  129. IllegalImportDeclaration: 'Unexpected token',
  130. IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list',
  131. IllegalReturn: 'Illegal return statement',
  132. InvalidEscapedReservedWord: 'Keyword must not contain escaped characters',
  133. InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence',
  134. InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
  135. InvalidLHSInForIn: 'Invalid left-hand side in for-in',
  136. InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
  137. InvalidModuleSpecifier: 'Unexpected token',
  138. InvalidRegExp: 'Invalid regular expression',
  139. LetInLexicalBinding: 'let is disallowed as a lexically bound name',
  140. MissingFromClause: 'Unexpected token',
  141. MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
  142. NewlineAfterThrow: 'Illegal newline after throw',
  143. NoAsAfterImportNamespace: 'Unexpected token',
  144. NoCatchOrFinally: 'Missing catch or finally after try',
  145. ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
  146. Redeclaration: '%0 \'%1\' has already been declared',
  147. StaticPrototype: 'Classes may not have static property named prototype',
  148. StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
  149. StrictDelete: 'Delete of an unqualified identifier in strict mode.',
  150. StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block',
  151. StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
  152. StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
  153. StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
  154. StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
  155. StrictModeWith: 'Strict mode code may not include a with statement',
  156. StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
  157. StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
  158. StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
  159. StrictReservedWord: 'Use of future reserved word in strict mode',
  160. StrictVarName: 'Variable name may not be eval or arguments in strict mode',
  161. TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
  162. UnexpectedEOS: 'Unexpected end of input',
  163. UnexpectedIdentifier: 'Unexpected identifier',
  164. UnexpectedNumber: 'Unexpected number',
  165. UnexpectedReserved: 'Unexpected reserved word',
  166. UnexpectedString: 'Unexpected string',
  167. UnexpectedTemplate: 'Unexpected quasi %0',
  168. UnexpectedToken: 'Unexpected token %0',
  169. UnexpectedTokenIllegal: 'Unexpected token ILLEGAL',
  170. UnknownLabel: 'Undefined label \'%0\'',
  171. UnterminatedRegExp: 'Invalid regular expression: missing /'
  172. };
  173. var Regex = {
  174. // Unicode v8.0.0 NonAsciiIdentifierStart:
  175. 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]/,
  176. // Unicode v8.0.0 NonAsciiIdentifierPart:
  177. 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]/
  178. }
  179. var Character =
  180. {
  181. FromCodePoint: function (cp) {
  182. return (cp < 0x10000) ? String.fromCharCode(cp) :
  183. String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
  184. String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
  185. },
  186. //是否是空格 https://tc39.github.io/ecma262/#sec-white-space
  187. IsWhiteSpace:function(cp)
  188. {
  189. return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) ||
  190. (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0);
  191. },
  192. //是否换行 https://tc39.github.io/ecma262/#sec-line-terminators
  193. IsLineTerminator:function(cp)
  194. {
  195. return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029);
  196. },
  197. // https://tc39.github.io/ecma262/#sec-names-and-keywords
  198. IsIdentifierStart:function(cp)
  199. {
  200. return (cp === 0x24) || (cp === 0x5F) ||
  201. (cp >= 0x41 && cp <= 0x5A) ||
  202. (cp >= 0x61 && cp <= 0x7A) ||
  203. (cp === 0x5C) ||
  204. //【】▲▼
  205. (cp===0x3010 || cp===0x3011 || cp===0x25B2 || cp===0x25BC) ||
  206. ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(Character.FromCodePoint(cp)));
  207. },
  208. IsIdentifierPart: function (cp)
  209. {
  210. return (cp === 0x24) || (cp === 0x5F) ||
  211. (cp >= 0x41 && cp <= 0x5A) ||
  212. (cp >= 0x61 && cp <= 0x7A) ||
  213. (cp >= 0x30 && cp <= 0x39) ||
  214. (cp === 0x5C) || (cp===0x23) ||
  215. //【】▲▼
  216. (cp===0x3010 || cp===0x3011 || cp===0x25B2 || cp===0x25BC) ||
  217. ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(Character.FromCodePoint(cp)));
  218. },
  219. // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
  220. IsDecimalDigit: function (cp)
  221. {
  222. return (cp >= 0x30 && cp <= 0x39); // 0..9
  223. },
  224. IsHexDigit: function (cp)
  225. {
  226. return (cp >= 0x30 && cp <= 0x39) || (cp >= 0x41 && cp <= 0x46) || (cp >= 0x61 && cp <= 0x66); // a..f
  227. },
  228. IsOctalDigit: function (cp)
  229. {
  230. return (cp >= 0x30 && cp <= 0x37); // 0..7
  231. }
  232. }
  233. function HexValue(ch)
  234. {
  235. return '0123456789abcdef'.indexOf(ch.toLowerCase());
  236. }
  237. function OctalValue(ch)
  238. {
  239. return '01234567'.indexOf(ch);
  240. }
  241. var TOKEN_NAME={};
  242. TOKEN_NAME[1 /* BooleanLiteral */] = 'Boolean';
  243. TOKEN_NAME[2 /* EOF */] = '<end>';
  244. TOKEN_NAME[3 /* Identifier */] = 'Identifier';
  245. TOKEN_NAME[4 /* Keyword */] = 'Keyword';
  246. TOKEN_NAME[5 /* NullLiteral */] = 'Null';
  247. TOKEN_NAME[6 /* NumericLiteral */] = 'Numeric';
  248. TOKEN_NAME[7 /* Punctuator */] = 'Punctuator';
  249. TOKEN_NAME[8 /* StringLiteral */] = 'String';
  250. TOKEN_NAME[9 /* RegularExpression */] = 'RegularExpression';
  251. TOKEN_NAME[10 /* Template */] = 'Template';
  252. //DYNAINFO() 转换
  253. //["DYNA_NOW",null], //DYNA_NOW 现价 DYNAINFO(7) 即时行情数据 没有现价时(比如在开盘前),返回昨收盘价
  254. //["DYNA_ZAF",null], //DYNA_ZAF 涨幅 DYNAINFO(14) 即时行情数据(沪深京早盘竞价期间使用匹配价的涨幅) 转换成幅度需要乘100
  255. //["DYNA_LB", null], //DYNA_LB DYNAINFO(17) 量比 即时行情数据
  256. //["DYNA_ZAS",null], //DYNA_ZAS DYNAINFO(24) 返回涨速 报价界面行情数据 转换成幅度需要乘100
  257. //["SELLVOL", null], //返回内盘,即DYNAINFO(22) 即时行情数据
  258. //["BUYVOL", null], //返回外盘,即DYNAINFO(21) 即时行情数据
  259. const MAP_DYNAINFO_SHORTCUT=new Map(
  260. [
  261. ['DYNA_NOW', { Name:"DYNA_NOW", ID:7 } ],
  262. ['DYNA_LB', { Name:"DYNA_LB", ID:17 } ],
  263. ['DYNA_ZAS', { Name:"DYNA_ZAS", ID:24 } ],
  264. ['SELLVOL', { Name:"SELLVOL", ID:22 }],
  265. ['BUYVOL', { Name:"BUYVOL", ID:21 } ],
  266. ]
  267. );
  268. //编译异常, 错误类
  269. function ErrorHandler()
  270. {
  271. this.Error=[];
  272. this.IsTolerant=false;
  273. this.RecordError=function(error)
  274. {
  275. this.Error.push(error);
  276. }
  277. this.ConstructError=function(msg,column)
  278. {
  279. let error=new Error(msg);
  280. //通过自己抛异常并自己截获 来获取调用堆栈信息
  281. try
  282. {
  283. throw error;
  284. }
  285. catch(base)
  286. {
  287. if (Object.create && Object.defineProperties)
  288. {
  289. error=Object.create(base);
  290. error.Column=column;
  291. }
  292. }
  293. return error;
  294. }
  295. this.CreateError=function(index, line, col, description)
  296. {
  297. let msg='Line ' + line + ': ' + description;
  298. let error=this.ConstructError(msg,col);
  299. error.Index=index;
  300. error.LineNumber=line;
  301. error.Description=description;
  302. return error;
  303. }
  304. this.ThrowError=function(index, line, col, description)
  305. {
  306. let error=this.CreateError(index,line,col,description);
  307. throw error;
  308. }
  309. this.TolerateError=function(index, line, col, description)
  310. {
  311. const error = this.CreateError(index, line, col, description);
  312. if (this.IsTolerant) this.RecordError(error);
  313. else throw error;
  314. }
  315. }
  316. //扫描类
  317. function Scanner(code, ErrorHandler)
  318. {
  319. this.Source=code;
  320. this.ErrorHandler=ErrorHandler;
  321. this.Length=code.length;
  322. this.Index=0;
  323. this.LineNumber=(code.length>0)?1:0;
  324. this.LineStart=0;
  325. this.CurlyStack=[];
  326. this.SaveState=function() //保存当前扫描状态
  327. {
  328. return { Index:this.Index, LineNumber:this.LineNumber, LineStart:this.LineStart };
  329. }
  330. this.RestoreState=function(state) //还原扫描状态
  331. {
  332. this.Index=state.Index;
  333. this.LineNumber=state.LineNumber;
  334. this.LineStart=state.LineStart;
  335. }
  336. this.IsEOF=function() //否是已经结束
  337. {
  338. return this.Index>=this.Length;
  339. }
  340. this.ThrowUnexpectedToken=function(message=Messages.UnexpectedTokenIllegal)
  341. {
  342. return this.ErrorHandler.ThrowError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message);
  343. }
  344. this.TolerateUnexpectedToken=function(message = Messages.UnexpectedTokenIllegal)
  345. {
  346. this.ErrorHandler.TolerateError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message);
  347. }
  348. this.IsKeyword=function(id)
  349. {
  350. return false;
  351. }
  352. this.CodePointAt = function (i)
  353. {
  354. let cp = this.Source.charCodeAt(i);
  355. if (cp >= 0xD800 && cp <= 0xDBFF)
  356. {
  357. let second = this.Source.charCodeAt(i + 1);
  358. if (second >= 0xDC00 && second <= 0xDFFF) {
  359. var first = cp;
  360. cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
  361. }
  362. }
  363. return cp;
  364. }
  365. //8进制->10进制
  366. this.OctalToDecimal=function(ch)
  367. {
  368. // \0 is not octal escape sequence
  369. let octal = (ch !== '0');
  370. let code = OctalValue(ch);
  371. if (!this.IsEOF() && Character.IsOctalDigit(this.Source.charCodeAt(this.Index)))
  372. {
  373. octal = true;
  374. code = code * 8 + OctalValue(this.Source[this.Index++]);
  375. // 3 digits are only allowed when string starts
  376. // with 0, 1, 2, 3
  377. if ('0123'.indexOf(ch) >= 0 && !this.IsEOF() && Character.IsOctalDigit(this.Source.charCodeAt(this.Index)))
  378. code = code * 8 + OctalValue(this.Source[this.Index++]);
  379. }
  380. return { Code: code, Octal: octal };
  381. }
  382. this.Lex=function()
  383. {
  384. if (this.IsEOF()) return { Type:2/*EOF*/, Value:'', LineNumber:this.LineNumber, LineStart:this.LineStart, Start:this.Index, End:this.Index };
  385. let cp=this.Source.charCodeAt(this.Index);
  386. //变量名 或 关键字
  387. if (Character.IsIdentifierStart(cp)) return this.ScanIdentifier();
  388. //( ) ; 开头 操作符扫描
  389. if (cp === 0x28 || cp === 0x29 || cp === 0x3B) return this.ScanPunctuator();
  390. //' " 开头 字符串扫描
  391. if (cp === 0x27 || cp === 0x22) return this.ScanStringLiteral();
  392. //. 开头 浮点型
  393. if (cp==0x2E)
  394. {
  395. if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index + 1)))
  396. return this.ScanNumericLiteral();
  397. return this.ScanPunctuator();
  398. }
  399. //数字
  400. if (Character.IsDecimalDigit(cp)) return this.ScanNumericLiteral();
  401. if (cp >= 0xD800 && cp < 0xDFFF)
  402. {
  403. if (Character.IsIdentifierStart(this.CodePointAt(this.Index))) return this.ScanIdentifier();
  404. }
  405. return this.ScanPunctuator();
  406. }
  407. //关键字 变量名 https://tc39.github.io/ecma262/#sec-names-and-keywords
  408. this.ScanIdentifier=function()
  409. {
  410. let type;
  411. let start=this.Index;
  412. //0x5C 反斜杠
  413. let id=((this.Source.charCodeAt(start)=== 0x5C) ? this.GetComplexIdentifier() : this.GetIdentifier());
  414. if (id.length) type=3; //Identifier
  415. else if (this.IsKeyword(id)) type=4; //Keyword
  416. else if (id==null) type=5; //NullLiteral
  417. else if (id=='true' || id=='false') type=1; //BooleanLiteral
  418. else type=3; //Identifier
  419. if (type!=3 && (start+id.length!=this.Index))
  420. {
  421. let restore=this.Index;
  422. this.Index=start;
  423. throw Messages.InvalidEscapedReservedWord;
  424. this.Index=restore;
  425. }
  426. if (id=='AND' || id=='OR') type=7 /*Punctuator*/;
  427. return { Type:type, Value:id, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index};
  428. }
  429. this.GetIdentifier=function()
  430. {
  431. let start=this.Index++; //start 保存进来的位置
  432. while(!this.IsEOF())
  433. {
  434. let ch=this.Source.charCodeAt(this.Index);
  435. if (ch==0x5C)
  436. {
  437. this.Index=start;
  438. return this.GetComplexIdentifier();
  439. }
  440. else if (ch >= 0xD800 && ch < 0xDFFF)
  441. {
  442. this.Index=start;
  443. return this.GetComplexIdentifier();
  444. }
  445. if (Character.IsIdentifierPart(ch)) ++this.Index;
  446. else break;
  447. }
  448. return this.Source.slice(start,this.Index);
  449. }
  450. this.GetComplexIdentifier=function()
  451. {
  452. let cp = this.CodePointAt(this.Index);
  453. let id = Character.FromCodePoint(cp);
  454. this.Index += id.length;
  455. // '\u' (U+005C, U+0075) denotes an escaped character.
  456. let ch;
  457. if (cp === 0x5C)
  458. {
  459. if (this.Source.charCodeAt(this.Index) !== 0x75)
  460. this.ThrowUnexpectedToken();
  461. ++this.Index;
  462. if (this.Source[this.Index] === '{')
  463. {
  464. ++this.Index;
  465. ch = this.ScanUnicodeCodePointEscape();
  466. }
  467. else
  468. {
  469. ch = this.ScanHexEscape('u');
  470. if (ch === null || ch === '\\' || !Character.IsIdentifierStart(ch.charCodeAt(0)))
  471. this.ThrowUnexpectedToken();
  472. }
  473. id = ch;
  474. }
  475. while (!this.IsEOF())
  476. {
  477. cp = this.CodePointAt(this.Index);
  478. if (!Character.IsIdentifierPart(cp))
  479. break;
  480. ch = Character.FromCodePoint(cp);
  481. id += ch;
  482. this.Index += ch.length;
  483. // '\u' (U+005C, U+0075) denotes an escaped character.
  484. if (cp === 0x5C)
  485. {
  486. id = id.substring(0, id.length - 1);
  487. if (this.Source.charCodeAt(this.Index) !== 0x75)
  488. this.ThrowUnexpectedToken();
  489. ++this.Index;
  490. if (this.Source[this.Index] === '{')
  491. {
  492. ++this.Index;
  493. ch = this.ScanUnicodeCodePointEscape();
  494. }
  495. else
  496. {
  497. ch = this.ScanHexEscape('u');
  498. if (ch === null || ch === '\\' || !Character.IsIdentifierPart(ch.charCodeAt(0)))
  499. this.ThrowUnexpectedToken();
  500. }
  501. id += ch;
  502. }
  503. }
  504. return id;
  505. }
  506. this.ScanUnicodeCodePointEscape=function()
  507. {
  508. const result = this.TryToScanUnicodeCodePointEscape();
  509. if (result === null)
  510. return this.ThrowUnexpectedToken();
  511. return result;
  512. }
  513. this.TryToScanUnicodeCodePointEscape=function()
  514. {
  515. let ch = this.Source[this.Index];
  516. let code = 0;
  517. // At least, one hex digit is required.
  518. if (ch === '}')
  519. return null;
  520. while (!this.IsEOF())
  521. {
  522. ch = this.Source[this.Index++];
  523. if (!Character.IsHexDigit(ch.charCodeAt(0)))
  524. break;
  525. code = code * 16 + HexValue(ch);
  526. }
  527. if (code > 0x10FFFF || ch !== '}')
  528. return null;
  529. return Character.FromCodePoint(code);
  530. }
  531. this.ScanHexEscape=function(prefix)
  532. {
  533. const len = (prefix === 'u') ? 4 : 2;
  534. let code = 0;
  535. for (let i = 0; i < len; ++i)
  536. {
  537. if (!this.IsEOF() && Character.IsHexDigit(this.Source.charCodeAt(this.Index)))
  538. {
  539. code = code * 16 + HexValue(this.source[this.Index++]);
  540. }
  541. else
  542. {
  543. return null;
  544. }
  545. }
  546. return String.fromCharCode(code);
  547. }
  548. //操作符 https://tc39.github.io/ecma262/#sec-punctuators
  549. this.ScanPunctuator=function()
  550. {
  551. let start=this.Index;
  552. let str=this.Source[this.Index];
  553. switch(str)
  554. {
  555. case '(':
  556. ++this.Index;
  557. break;
  558. case ')':
  559. case ';':
  560. case ',':
  561. ++this.Index;
  562. break;
  563. case '.':
  564. ++this.Index;
  565. /*if (this.Source[this.Index] === '.' && this.Source[this.Index + 1] === '.')
  566. {
  567. //Spread operator: ...
  568. this.Index += 2;
  569. str = '...';
  570. }
  571. */
  572. break;
  573. default:
  574. str=this.Source.substr(this.Index,3);
  575. if (str=='AND')
  576. {
  577. this.Index+=3;
  578. }
  579. else
  580. {
  581. str = this.Source.substr(this.Index, 2);
  582. if (str === '&&' || str === '||' || str === '==' || str === '!=' || str === '<>' || str === '<=' || str === '>=' || str === '=>' || str==':=' || str=='OR')
  583. {
  584. this.Index += 2;
  585. }
  586. else
  587. {
  588. str=this.Source[this.Index];
  589. if ('<>=!+-*%&|^/:'.indexOf(str) >= 0) ++this.Index;
  590. }
  591. }
  592. }
  593. if (this.Index==start)
  594. this.ThrowUnecpectedToken();
  595. return { Type:7/*Punctuator*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index };
  596. }
  597. //字符串 https://tc39.github.io/ecma262/#sec-literals-string-literals
  598. this.ScanStringLiteral=function()
  599. {
  600. let start=this.Index;
  601. let quote=this.Source[this.Index];
  602. ++this.Index;
  603. var octal=false;
  604. let str='';
  605. while(!this.IsEOF())
  606. {
  607. let ch=this.Source[this.Index++];
  608. if (ch==quote)
  609. {
  610. quote='';
  611. break;
  612. }
  613. else if (ch=='\\') //字符串转义
  614. {
  615. ch = this.Source[this.Index++];
  616. if (!ch || !Character.IsLineTerminator(ch.charCodeAt(0)))
  617. {
  618. switch (ch)
  619. {
  620. case 'u':
  621. if (this.Source[this.Index] === '{')
  622. {
  623. ++this.Index;
  624. str += this.ScanUnicodeCodePointEscape();
  625. }
  626. else
  627. {
  628. const unescapedChar = this.ScanHexEscape(ch);
  629. if (unescapedChar === null)
  630. this.ThrowUnexpectedToken();
  631. str += unescapedChar;
  632. }
  633. break;
  634. case 'x': //十六进制 它的转义规则:\x<hex>,\x后跟上2位十六进制数
  635. const unescaped = this.ScanHexEscape(ch);
  636. if (unescaped === null)
  637. this.ThrowUnexpectedToken(Messages.InvalidHexEscapeSequence);
  638. str += unescaped;
  639. break;
  640. case 'n': //换行符
  641. str += '\n';
  642. break;
  643. case 'r': //回车键
  644. str += '\r';
  645. break;
  646. case 't': //制表符
  647. str += '\t';
  648. break;
  649. case 'b': //后退键
  650. str += '\b';
  651. break;
  652. case 'f': //换页符
  653. str += '\f';
  654. break;
  655. case 'v': //垂直制表符
  656. str += '\x0B';
  657. break;
  658. case '8':
  659. case '9':
  660. str += ch;
  661. this.TolerateUnexpectedToken();
  662. break;
  663. default:
  664. if (ch && Character.IsOctalDigit(ch.charCodeAt(0))) //反斜杠后面跟3位八进制数,就代表一个转义字符
  665. {
  666. const octToDec = this.OctalToDecimal(ch);
  667. octal = octToDec.Octal || octal;
  668. str += String.fromCharCode(octToDec.Code);
  669. }
  670. else
  671. {
  672. str += ch;
  673. }
  674. break;
  675. }
  676. }
  677. }
  678. else if (Character.IsLineTerminator(ch.charCodeAt(0)))
  679. {
  680. break;
  681. }
  682. else
  683. {
  684. str+=ch;
  685. }
  686. }
  687. if (quote!='')
  688. {
  689. this.Index=start;
  690. this.ThrowUnecpectedToken();
  691. }
  692. return {Type:8/*StringLiteral*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index};
  693. }
  694. this.ScanNumericLiteral=function()
  695. {
  696. let start=this.Index;
  697. let ch=this.Source[this.Index];
  698. let num='';
  699. if (ch!='.')
  700. {
  701. num=this.Source[this.Index++];
  702. ch=this.Source[this.Index];
  703. // Hex number starts with '0x'. 16进制
  704. if (num=='0')
  705. {
  706. if (ch=='x' || ch=='X')
  707. {
  708. ++this.Index;
  709. return this.ScanHexLiteral(start);
  710. }
  711. }
  712. while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
  713. {
  714. num+=this.Source[this.Index++];
  715. }
  716. ch=this.Source[this.Index];
  717. }
  718. if (ch=='.')
  719. {
  720. num+=this.Source[this.Index++];
  721. while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
  722. {
  723. num+=this.Source[this.Index++];
  724. }
  725. ch=this.Source[this.Index];
  726. }
  727. //科学计数法
  728. if (ch=='e' || ch=='E')
  729. {
  730. num+=this.Source[this.Index++];
  731. ch=this.Source[this.Index];
  732. if (ch=='+' || ch=='-') num+=this.Source[this.Index];
  733. if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
  734. {
  735. while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
  736. {
  737. num+=this.Source[this.Index++];
  738. }
  739. }
  740. else
  741. {
  742. this.ThrowUnecpectedToken();
  743. }
  744. }
  745. if (Character.IsIdentifierStart(this.Source.charCodeAt(this.Index)))
  746. {
  747. this.ThrowUnecpectedToken();
  748. }
  749. return { Type:6/*NumericLiteral*/, Value:parseFloat(num), LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index };
  750. }
  751. //空格 或 注释
  752. this.ScanComments=function()
  753. {
  754. let comments;
  755. let start=(this.Index==0);
  756. while(!this.IsEOF())
  757. {
  758. let ch=this.Source.charCodeAt(this.Index);
  759. if (Character.IsWhiteSpace(ch)) //过滤掉空格
  760. {
  761. ++this.Index;
  762. }
  763. else if (Character.IsLineTerminator(ch))
  764. {
  765. ++this.Index;
  766. if (ch==0x0D && this.Source.charCodeAt(this.Index)==0x0A) ++this.Index; //回车+换行
  767. ++this.LineNumber;
  768. this.LineStart=this.Index;
  769. start=true;
  770. }
  771. else if (ch==0x2F) // //注释
  772. {
  773. ch=this.Source.charCodeAt(this.Index+1);
  774. if (ch==0x2F)
  775. {
  776. this.Index+=2;
  777. let comment=this.SkipSingleLineComment(2);
  778. start=true;
  779. }
  780. else
  781. {
  782. break;
  783. }
  784. }
  785. else if (ch == 0x7B) //{ } 注释
  786. {
  787. this.Index += 1;
  788. let comment = this.SkipMultiLineComment();
  789. }
  790. else
  791. {
  792. break;
  793. }
  794. }
  795. return comments;
  796. }
  797. this.SkipMultiLineComment = function ()
  798. {
  799. var comments = [];
  800. while (!this.IsEOF())
  801. {
  802. var ch = this.Source.charCodeAt(this.Index);
  803. if (Character.IsLineTerminator(ch))
  804. {
  805. ++this.LineNumber;
  806. ++this.Index;
  807. this.LineStart = this.Index;
  808. }
  809. else if (ch == 0x7D)
  810. {
  811. this.Index += 1;
  812. return comments;
  813. }
  814. else
  815. {
  816. ++this.Index;
  817. }
  818. }
  819. return comments;
  820. }
  821. //单行注释 https://tc39.github.io/ecma262/#sec-comments
  822. this.SkipSingleLineComment=function(offset)
  823. {
  824. let comments=[];
  825. while(!this.IsEOF())
  826. {
  827. let ch=this.Source.charCodeAt(this.Index);
  828. ++this.Index;
  829. if (Character.IsLineTerminator(ch))
  830. {
  831. if (ch === 13 && this.Source.charCodeAt(this.Index) === 10)
  832. ++this.Index;
  833. ++this.LineNumber;
  834. this.LineStart=this.Index;
  835. return comments;
  836. }
  837. }
  838. return comments;
  839. }
  840. this.ThrowUnecpectedToken=function(message)
  841. {
  842. if (!message) message = Messages.UnexpectedTokenIllegal;
  843. return this.ErrorHandler.ThrowError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message);
  844. }
  845. }
  846. function Tokenizer(code)
  847. {
  848. this.ErrorHandler=new ErrorHandler(); //错误信息处理类
  849. this.Scanner=new Scanner(code,this.ErrorHandler);
  850. this.Buffer=[];
  851. this.GetNextToken=function()
  852. {
  853. if (this.Buffer.length==0)
  854. {
  855. let comments=this.Scanner.ScanComments();
  856. if (!this.Scanner.IsEOF())
  857. {
  858. let token=this.Scanner.Lex();
  859. let entry={ Type:TOKEN_NAME[token.Type], Value:this.Scanner.Source.slice(token.Start, token.End)};
  860. this.Buffer.push(entry);
  861. }
  862. }
  863. return this.Buffer.shift();
  864. }
  865. }
  866. var Syntax = {
  867. AssignmentExpression: 'AssignmentExpression',
  868. AssignmentPattern: 'AssignmentPattern',
  869. ArrayExpression: 'ArrayExpression',
  870. ArrayPattern: 'ArrayPattern',
  871. ArrowFunctionExpression: 'ArrowFunctionExpression',
  872. AwaitExpression: 'AwaitExpression',
  873. BlockStatement: 'BlockStatement',
  874. BinaryExpression: 'BinaryExpression',
  875. BreakStatement: 'BreakStatement',
  876. CallExpression: 'CallExpression',
  877. CatchClause: 'CatchClause',
  878. ClassBody: 'ClassBody',
  879. ClassDeclaration: 'ClassDeclaration',
  880. ClassExpression: 'ClassExpression',
  881. ConditionalExpression: 'ConditionalExpression',
  882. ContinueStatement: 'ContinueStatement',
  883. DoWhileStatement: 'DoWhileStatement',
  884. DebuggerStatement: 'DebuggerStatement',
  885. EmptyStatement: 'EmptyStatement',
  886. ExportAllDeclaration: 'ExportAllDeclaration',
  887. ExportDefaultDeclaration: 'ExportDefaultDeclaration',
  888. ExportNamedDeclaration: 'ExportNamedDeclaration',
  889. ExportSpecifier: 'ExportSpecifier',
  890. ExpressionStatement: 'ExpressionStatement',
  891. ForStatement: 'ForStatement',
  892. ForOfStatement: 'ForOfStatement',
  893. ForInStatement: 'ForInStatement',
  894. FunctionDeclaration: 'FunctionDeclaration',
  895. FunctionExpression: 'FunctionExpression',
  896. Identifier: 'Identifier',
  897. IfStatement: 'IfStatement',
  898. ImportDeclaration: 'ImportDeclaration',
  899. ImportDefaultSpecifier: 'ImportDefaultSpecifier',
  900. ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
  901. ImportSpecifier: 'ImportSpecifier',
  902. Literal: 'Literal',
  903. LabeledStatement: 'LabeledStatement',
  904. LogicalExpression: 'LogicalExpression',
  905. MemberExpression: 'MemberExpression',
  906. MetaProperty: 'MetaProperty',
  907. MethodDefinition: 'MethodDefinition',
  908. NewExpression: 'NewExpression',
  909. ObjectExpression: 'ObjectExpression',
  910. ObjectPattern: 'ObjectPattern',
  911. Program: 'Program',
  912. Property: 'Property',
  913. RestElement: 'RestElement',
  914. ReturnStatement: 'ReturnStatement',
  915. SequenceExpression: 'SequenceExpression',
  916. SpreadElement: 'SpreadElement',
  917. Super: 'Super',
  918. SwitchCase: 'SwitchCase',
  919. SwitchStatement: 'SwitchStatement',
  920. TaggedTemplateExpression: 'TaggedTemplateExpression',
  921. TemplateElement: 'TemplateElement',
  922. TemplateLiteral: 'TemplateLiteral',
  923. ThisExpression: 'ThisExpression',
  924. ThrowStatement: 'ThrowStatement',
  925. TryStatement: 'TryStatement',
  926. UnaryExpression: 'UnaryExpression',
  927. UpdateExpression: 'UpdateExpression',
  928. VariableDeclaration: 'VariableDeclaration',
  929. VariableDeclarator: 'VariableDeclarator',
  930. WhileStatement: 'WhileStatement',
  931. WithStatement: 'WithStatement',
  932. YieldExpression: 'YieldExpression'
  933. };
  934. function Node()
  935. {
  936. this.IsNeedIndexData=false; //是否需要大盘数据
  937. this.IsNeedLatestData=false; //是否需要最新的个股行情数据
  938. this.IsNeedSymbolData=false; //是否需要下载股票数据
  939. this.IsNeedMarginData = new Set();
  940. this.IsNeedNewsAnalysisData = new Set(); //新闻统计数据
  941. this.IsNeedBlockIncreaseData = new Set(); //是否需要市场涨跌股票数据统计
  942. this.IsNeedSymbolExData = new Set(); //下载股票行情的其他数据
  943. this.FunctionData=[]; //{ID:, Args:, FunctionName: } FINVALUE(ID),FINONE(ID,Y,MMDD), FINANCE(ID)
  944. this.Dynainfo=[]; //{ID:, Args:, FunctionName: } DYNAINFO()
  945. this.IsAPIData = [] //加载API数据
  946. this.ExecuteIndex=[]; //执行调用指标
  947. this.OtherSymbolData=[]; //其他股票数据 key=股票代码(小写)
  948. this.PeriodSymbolData=[]; //跨周期数据 { Period:, VarName: }
  949. this.ErrorHandler=ErrorHandler;
  950. this.GetDataJobList=function() //下载数据任务列表
  951. {
  952. let jobs=[];
  953. if (this.IsNeedSymbolData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA});
  954. if (this.IsNeedIndexData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA});
  955. //最新的个股行情数据
  956. for(var i=0;i<this.Dynainfo.length;++i)
  957. {
  958. var item=this.Dynainfo[i];
  959. jobs.push(item);
  960. }
  961. //涨跌停家数统计
  962. for (var blockSymbol of this.IsNeedBlockIncreaseData)
  963. {
  964. jobs.push({ ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA, Symbol: blockSymbol });
  965. }
  966. //加载融资融券
  967. for (var jobID of this.IsNeedMarginData)
  968. {
  969. jobs.push({ID:jobID});
  970. }
  971. //加载新闻统计
  972. for (var jobID of this.IsNeedNewsAnalysisData)
  973. {
  974. jobs.push({ID:jobID});
  975. }
  976. for (var i in this.IsAPIData)
  977. {
  978. var item = this.IsAPIData[i];
  979. jobs.push(item);
  980. }
  981. for(var i in this.ExecuteIndex)
  982. {
  983. var item=this.ExecuteIndex[i];
  984. jobs.push(item);
  985. }
  986. //行情其他数据
  987. for (var jobID of this.IsNeedSymbolExData)
  988. {
  989. jobs.push({ ID:jobID });
  990. }
  991. for(var i in this.FunctionData)
  992. {
  993. var item=this.FunctionData[i];
  994. jobs.push(item);
  995. }
  996. for(var i in this.OtherSymbolData)
  997. {
  998. var item=this.OtherSymbolData[i];
  999. jobs.push(item);
  1000. }
  1001. return jobs;
  1002. }
  1003. this.VerifySymbolVariable = function (varName, token)
  1004. {
  1005. let setIndexName = new Set(['INDEXA', 'INDEXC', 'INDEXH', 'INDEXL', "INDEXO", "INDEXV", 'INDEXDEC', 'INDEXADV']);
  1006. if (setIndexName.has(varName))
  1007. {
  1008. this.IsNeedIndexData=true;
  1009. return;
  1010. }
  1011. let setSymbolDataName=new Set(['CLOSE','C','VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT']);
  1012. if (setSymbolDataName.has(varName))
  1013. {
  1014. this.IsNeedSymbolData=true;
  1015. return;
  1016. }
  1017. if (varName === 'VOLR')
  1018. {
  1019. if (!this.IsNeedSymbolExData.has(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA))
  1020. this.IsNeedSymbolExData.add(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA);
  1021. return;
  1022. }
  1023. //CAPITAL流通股本(手), EXCHANGE 换手率, TOTALCAPITAL 总股本(手)
  1024. let setVariantName=new Set(
  1025. [
  1026. "CAPITAL","TOTALCAPITAL","EXCHANGE",
  1027. "HYBLOCK","DYBLOCK","GNBLOCK","FGBLOCK","ZSBLOCK","ZHBLOCK","ZDBLOCK","HYZSCODE",
  1028. "GNBLOCKNUM","FGBLOCKNUM","ZSBLOCKNUM","ZHBLOCKNUM","ZDBLOCKNUM",
  1029. "HYSYL","HYSJL","FROMOPEN",
  1030. //资金流向
  1031. "LARGEINTRDVOL","LARGEOUTTRDVOL",
  1032. "TRADENUM","TRADEINNUM","TRADEOUTNUM",
  1033. "LARGETRDINNUM","LARGETRDOUTNUM",
  1034. "CUR_BUYORDER","CUR_SELLORDER",
  1035. "ACTINVOL","ACTOUTVOL",
  1036. "BIDORDERVOL","BIDCANCELVOL","AVGBIDPX",
  1037. "OFFERORDERVOL","OFFERCANCELVOL","AVGOFFERPX",
  1038. ]);
  1039. if (setVariantName.has(varName))
  1040. {
  1041. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT, VariantName:varName };
  1042. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1043. this.FunctionData.push(item);
  1044. return;
  1045. }
  1046. if (MAP_DYNAINFO_SHORTCUT.has(varName))
  1047. {
  1048. var item=MAP_DYNAINFO_SHORTCUT.get(varName);
  1049. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA, Args:[item.ID], FunctionName:varName };
  1050. this.Dynainfo.push(item);
  1051. return;
  1052. }
  1053. if (g_JSComplierResource.IsCustomVariant(varName)) //自定义函数
  1054. {
  1055. var item={ VariantName:varName, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA };
  1056. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1057. this.FunctionData.push(item);
  1058. return;
  1059. }
  1060. }
  1061. this.VerifySymbolFunction = function (callee, args, token)
  1062. {
  1063. //自定义函数 可以覆盖系统内置函数
  1064. if (g_JSComplierResource.IsCustomFunction(callee.Name))
  1065. {
  1066. var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA, Args:args}
  1067. if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
  1068. this.FunctionData.push(item);
  1069. return;
  1070. }
  1071. //自定义数据函数
  1072. if (g_JSComplierResource.IsCustomDataFunction(callee.Name))
  1073. {
  1074. var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_DATA_FUNCTION, Args:args}
  1075. if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
  1076. this.FunctionData.push(item);
  1077. return;
  1078. }
  1079. if (callee.Name=='DYNAINFO')
  1080. {
  1081. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA, Args:args, FunctionName:callee.Name };
  1082. this.Dynainfo.push(item);
  1083. return;
  1084. }
  1085. //财务函数
  1086. if (callee.Name=='FINANCE')
  1087. {
  1088. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:args, FunctionName:callee.Name };
  1089. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1090. this.FunctionData.push(item);
  1091. return;
  1092. }
  1093. if (callee.Name=="FINVALUE")
  1094. {
  1095. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE, Args:args, FunctionName:callee.Name };
  1096. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1097. this.FunctionData.push(item);
  1098. return;
  1099. }
  1100. if (callee.Name=="FINONE")
  1101. {
  1102. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE, Args:args, FunctionName:callee.Name };
  1103. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1104. this.FunctionData.push(item);
  1105. return;
  1106. }
  1107. //专业财务数据
  1108. for(var i=0;i<JS_ARRAY_PROFESSIONAL_FINANCE.length;++i)
  1109. {
  1110. var financeItem=JS_ARRAY_PROFESSIONAL_FINANCE[i];
  1111. if (financeItem.Name==callee.Name)
  1112. {
  1113. var item={ ID:financeItem.JobID, Args:args, FunctionName:callee.Name };
  1114. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1115. this.FunctionData.push(item);
  1116. return;
  1117. }
  1118. }
  1119. if (callee.Name === 'MARGIN')
  1120. {
  1121. let jobID = JS_EXECUTE_JOB_ID.GetMarginJobID(args[0].Value);
  1122. if (jobID && !this.IsNeedMarginData.has(jobID)) this.IsNeedMarginData.add(jobID);
  1123. return;
  1124. }
  1125. if (callee.Name === 'NEWS')
  1126. {
  1127. let jobID = JS_EXECUTE_JOB_ID.GetNewsAnalysisID(args[0].Value);
  1128. if (jobID && !this.IsNeedNewsAnalysisData.has(jobID)) this.IsNeedNewsAnalysisData.add(jobID);
  1129. return;
  1130. }
  1131. if (callee.Name == 'COST' || callee.Name == 'WINNER' || callee.Name=='PWINNER') //筹码都需要换手率
  1132. {
  1133. //下载流通股
  1134. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:[7], FunctionName:"FINANCE", FunctionName2:callee.Name };
  1135. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1136. this.FunctionData.push(item);
  1137. return;
  1138. }
  1139. if (callee.Name=="INBLOCK")
  1140. {
  1141. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT, VariantName:"INBLOCK" }; //下载所有板块
  1142. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1143. this.FunctionData.push(item);
  1144. return;
  1145. }
  1146. if (callee.Name === 'BETA') //beta需要下载上证指数
  1147. {
  1148. this.IsNeedIndexData = true;
  1149. return;
  1150. }
  1151. if (callee.Name == 'UPCOUNT' || callee.Name == 'DOWNCOUNT') //上涨下跌个数
  1152. {
  1153. var blockSymbol = args[0].Value;
  1154. if (!this.IsNeedBlockIncreaseData.has(blockSymbol)) this.IsNeedBlockIncreaseData.add(blockSymbol);
  1155. return;
  1156. }
  1157. if (callee.Name=='STKINDI' || callee.Name=='CALCSTOCKINDEX') //指标调用
  1158. {
  1159. var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Args:args, FunctionName:callee.Name };
  1160. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1161. this.ExecuteIndex.push(item);
  1162. return;
  1163. }
  1164. if (callee.Type==Syntax.Literal) //指标调用 "MA.MA1"(10,5,5)"
  1165. {
  1166. var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Args:args, FunctionName:callee.Value, DynamicName:callee.Value };
  1167. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1168. this.ExecuteIndex.push(item);
  1169. return;
  1170. }
  1171. if (callee.Name == "LOADAPIDATA") //加载API数据
  1172. {
  1173. var item = { Name: callee.Name, ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA, Args: args };
  1174. if (token) item.Token = { Index: token.Start, Line: token.LineNumber };
  1175. this.IsAPIData.push(item);
  1176. return;
  1177. }
  1178. let setStockDataName=new Set(['CLOSE',"C",'VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT','AMO','VOLINSTK']);
  1179. if (setStockDataName.has(callee.Name))
  1180. {
  1181. var item= { Name:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA,Args:args };
  1182. if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
  1183. this.OtherSymbolData.push(item);
  1184. return;
  1185. }
  1186. }
  1187. this.VerifySymbolLiteral=function(value,token)
  1188. {
  1189. if (IFrameSplitOperator.IsString(value))
  1190. {
  1191. if (value.indexOf('$')>0)
  1192. {
  1193. var aryValue=value.split('$');
  1194. if (aryValue.length!=2) return;
  1195. var item= { Literal:value, ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA };
  1196. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1197. this.OtherSymbolData.push(item);
  1198. }
  1199. }
  1200. }
  1201. this.ExpressionStatement=function(expression)
  1202. {
  1203. return { Type:Syntax.ExpressionStatement, Expression:expression };
  1204. }
  1205. this.Script=function(body)
  1206. {
  1207. return {Type:Syntax.Program, Body:body, SourceType:'通达信脚本' };
  1208. }
  1209. this.SequenceExpression=function(expression)
  1210. {
  1211. return {Type:Syntax.SequenceExpression, Expression:expression };
  1212. }
  1213. this.BinaryExpression=function(operator, left, right)
  1214. {
  1215. let logical = (operator === '||' || operator === '&&' || operator=='AND' || operator=='OR');
  1216. let type = logical ? Syntax.LogicalExpression : Syntax.BinaryExpression;
  1217. return { Type:type, Operator:operator, Left:left, Right:right };
  1218. }
  1219. this.Literal=function(value,raw,token)
  1220. {
  1221. this.VerifySymbolLiteral(value, token);
  1222. return { Type:Syntax.Literal, Value:value, Raw:raw };
  1223. }
  1224. this.Identifier = function (name, token)
  1225. {
  1226. this.VerifySymbolVariable(name, token);
  1227. return { Type:Syntax.Identifier, Name:name};
  1228. }
  1229. this.AssignmentExpression=function (operator, left, right)
  1230. {
  1231. return { Type:Syntax.AssignmentExpression, Operator:operator, Left:left, Right:right };
  1232. }
  1233. //成员变量, 不需要检测
  1234. this.MemberIdentifier=function(name, token)
  1235. {
  1236. return { Type:Syntax.Identifier, Name:name};
  1237. }
  1238. this.UnaryExpression=function(operator, argument)
  1239. {
  1240. return { Type:Syntax.UnaryExpression, Operator:operator, Argument:argument, Prefix:true };
  1241. }
  1242. this.EmptyStatement=function()
  1243. {
  1244. return { Type:Syntax.EmptyStatement };
  1245. }
  1246. this.CallExpression = function (callee, args, token)
  1247. {
  1248. this.VerifySymbolFunction(callee, args, token);
  1249. return { Type:Syntax.CallExpression, Callee:callee, Arguments:args };
  1250. }
  1251. this.StaticMemberExpression = function (object, property,token)
  1252. {
  1253. this.VerifyMemberVariable(object,property, token);
  1254. return { Type: Syntax.MemberExpression, Computed: false, Object: object, Property: property };
  1255. }
  1256. this.VerifyMemberVariable=function(object,property,token)
  1257. {
  1258. var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Member:{Object:object, Property:property} };
  1259. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1260. this.ExecuteIndex.push(item);
  1261. return;
  1262. }
  1263. }
  1264. function JSParser(code)
  1265. {
  1266. this.ErrorHandler=new ErrorHandler();
  1267. this.Scanner=new Scanner(code, this.ErrorHandler);
  1268. this.Node=new Node(); //节点创建
  1269. this.LookAhead={Type:2, Value:'', LineNumber:this.Scanner.LineNumber, LineStart:0, Start:0, End:0 };
  1270. this.HasLineTerminator=false;
  1271. this.Context = {
  1272. IsModule: false,
  1273. await: false,
  1274. allowIn: true,
  1275. allowStrictDirective: true,
  1276. allowYield: true,
  1277. FirstCoverInitializedNameError: null,
  1278. IsAssignmentTarget: false,
  1279. IsBindingElement: false,
  1280. InFunctionBody: false,
  1281. inIteration: false,
  1282. inSwitch: false,
  1283. labelSet: {},
  1284. Strict: false
  1285. };
  1286. this.PeratorPrecedence =
  1287. {
  1288. ')': 0,
  1289. ';': 0,
  1290. ',': 0,
  1291. ']': 0,
  1292. '||': 1,
  1293. 'OR':1,
  1294. '&&': 2,
  1295. 'AND':2,
  1296. '|': 3,
  1297. '^': 4,
  1298. '&': 5,
  1299. '=': 6,
  1300. '==': 6,
  1301. '!=': 6,
  1302. '<>': 6,
  1303. '===': 6,
  1304. '!==': 6,
  1305. '<': 7,
  1306. '>': 7,
  1307. '<=': 7,
  1308. '>=': 7,
  1309. '<<': 8,
  1310. '>>': 8,
  1311. '>>>': 8,
  1312. '+': 9,
  1313. '-': 9,
  1314. '*': 11,
  1315. '/': 11,
  1316. '%': 11
  1317. };
  1318. this.StartMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 };
  1319. this.LastMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 };
  1320. this.Initialize=function()
  1321. {
  1322. this.NextToken();
  1323. this.LastMarker={ Index:this.Scanner.Index, Line:this.Scanner.LineNumber, Column:this.Scanner.Index-this.Scanner.LineStart };
  1324. }
  1325. this.CreateNode=function()
  1326. {
  1327. return { Index:this.StartMarker.Index, Line:this.StartMarker.Line, Column:this.StartMarker.Column };
  1328. }
  1329. this.StartNode=function(token, lastLineStart)
  1330. {
  1331. if (lastLineStart==void 0) { lastLineStart=0; }
  1332. let column = token.Start - token.LineStart;
  1333. let line = token.LineNumber;
  1334. if (column < 0)
  1335. {
  1336. column += lastLineStart;
  1337. line--;
  1338. }
  1339. return { Index: token.Start, Line: line, Column: column };
  1340. }
  1341. this.Match=function(value)
  1342. {
  1343. return this.LookAhead.Type==7 /*Punctuator*/ && this.LookAhead.Value==value;
  1344. }
  1345. this.Expect=function(value)
  1346. {
  1347. let token=this.NextToken();
  1348. if (token.Type!=7 /*Punctuator*/ || token.Value!=value)
  1349. this.ThrowUnexpectedToken(token);
  1350. }
  1351. //是否是赋值操作符
  1352. this.MatchAssign=function()
  1353. {
  1354. if (this.LookAhead.Type!=7 /*Punctuator*/) return false;
  1355. let op=this.LookAhead.Value;
  1356. return op==':' || op==':=';
  1357. }
  1358. this.GetTokenRaw=function(token)
  1359. {
  1360. return this.Scanner.Source.slice(token.Start, token.End);
  1361. }
  1362. this.NextToken=function()
  1363. {
  1364. let token=this.LookAhead;
  1365. this.LastMarker.Index=this.Scanner.Index;
  1366. this.LastMarker.Line=this.Scanner.LineNumber;
  1367. this.LastMarker.Column=this.Scanner.Index-this.Scanner.LineStart;
  1368. this.CollectComments(); //过滤注释 空格
  1369. if (this.Scanner.Index !== this.StartMarker.Index)
  1370. {
  1371. this.StartMarker.Index = this.Scanner.Index;
  1372. this.StartMarker.Line = this.Scanner.LineNumber;
  1373. this.StartMarker.Column = this.Scanner.Index - this.Scanner.LineStart;
  1374. }
  1375. let next=this.Scanner.Lex();
  1376. this.HasLineTerminator=(token.LineNumber!=next.LineNumber);
  1377. if (next && this.Context.Strict && next.Type==3/*Identifier */)
  1378. {
  1379. //TODO:
  1380. }
  1381. this.LookAhead=next;
  1382. return token;
  1383. }
  1384. this.CollectComments=function()
  1385. {
  1386. this.Scanner.ScanComments();
  1387. }
  1388. this.ParseScript=function()
  1389. {
  1390. let node=this.CreateNode();
  1391. let body=this.ParseDirectivePrologues();
  1392. while(this.LookAhead.Type!=2 /*EOF*/)
  1393. {
  1394. body.push(this.ParseStatementListItem())
  1395. }
  1396. return this.Finalize(node,this.Node.Script(body));
  1397. }
  1398. //https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive
  1399. this.ParseDirective=function()
  1400. {
  1401. let token=this.LookAhead;
  1402. let node=this.CreateNode();
  1403. let expr=this.ParseExpression();
  1404. }
  1405. this.ParseDirectivePrologues=function()
  1406. {
  1407. let firstRestricted=null;
  1408. let body=[];
  1409. while(true)
  1410. {
  1411. let token=this.LookAhead;
  1412. if (token.Type!=8 /*StringLiteral*/) break;
  1413. let statement=this.ParseDirective();
  1414. body.push(statement);
  1415. }
  1416. return body;
  1417. }
  1418. // https://tc39.github.io/ecma262/#sec-block
  1419. this.ParseStatementListItem=function()
  1420. {
  1421. let statement;
  1422. this.Context.IsAssignmentTarget=true;
  1423. this.Context.IsBindingElement=true;
  1424. if (this.LookAhead.Type==4 /*Keyword*/)
  1425. {
  1426. }
  1427. else
  1428. {
  1429. statement=this.ParseStatement();
  1430. }
  1431. return statement;
  1432. }
  1433. // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations
  1434. this.ParseStatement=function()
  1435. {
  1436. let statement;
  1437. switch(this.LookAhead.Type)
  1438. {
  1439. case 1 /* BooleanLiteral */:
  1440. case 5 /* NullLiteral */:
  1441. case 6 /* NumericLiteral */:
  1442. case 8 /* StringLiteral */:
  1443. case 10 /* Template */:
  1444. case 9 /* RegularExpression */:
  1445. statement = this.ParseExpressionStatement();
  1446. break;
  1447. case 7 /* Punctuator */:
  1448. let value = this.LookAhead.Value;
  1449. if (value === '(') statement = this.ParseExpressionStatement();
  1450. else if (value === ';') statement = this.ParseEmptyStatement();
  1451. else statement = this.ParseExpressionStatement();
  1452. break;
  1453. case 3 /* Identifier */:
  1454. statement = this.ParseLabelledStatement();
  1455. break;
  1456. case 4 /* Keyword */:
  1457. break;
  1458. default:
  1459. statement="error";
  1460. }
  1461. return statement;
  1462. }
  1463. // https://tc39.github.io/ecma262/#sec-empty-statement
  1464. this.ParseEmptyStatement=function()
  1465. {
  1466. let node=this.CreateNode();
  1467. this.Expect(';');
  1468. return this.Finalize(node, this.Node.EmptyStatement());
  1469. }
  1470. //https://tc39.github.io/ecma262/#sec-labelled-statements
  1471. this.ParseLabelledStatement=function()
  1472. {
  1473. let node=this.CreateNode();
  1474. let expr=this.ParseExpression();
  1475. this.ConsumeSemicolon();
  1476. let statement = new this.Node.ExpressionStatement(expr);
  1477. return this.Finalize(node, statement);
  1478. }
  1479. // https://tc39.github.io/ecma262/#sec-comma-operator
  1480. this.ParseExpression=function()
  1481. {
  1482. let startToken=this.LookAhead;
  1483. let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
  1484. if (this.Match(','))
  1485. {
  1486. let expressions=[];
  1487. expressions.push(expr);
  1488. while(this.LookAhead.Type!=2 /*EOF*/)
  1489. {
  1490. if (!this.Match(',')) break;
  1491. this.NextToken();
  1492. expressions.push(this.IsolateCoverGrammar(this.ParseAssignmentExpression));
  1493. }
  1494. expr=this.Finalize(this.StartNode(startToken),this.Node.SequenceExpression(expressions));
  1495. }
  1496. return expr;
  1497. }
  1498. this.ParseAssignmentExpression=function()
  1499. {
  1500. let expr;
  1501. let startToken=this.LookAhead;
  1502. let token=startToken;
  1503. expr=this.ParseConditionalExpression();
  1504. if (this.MatchAssign())
  1505. {
  1506. if (!this.Context.IsAssignmentTarget)
  1507. {
  1508. let marker=expr.Marker;
  1509. this.ThrowUnexpectedError(marker.Index,marker.Line,marker.Column,Messages.InvalidLHSInAssignment);
  1510. }
  1511. if (!this.Match('=') && !this.Match(':'))
  1512. {
  1513. this.Context.IsAssignmentTarget=false;
  1514. this.Context.IsBindingElement=false;
  1515. }
  1516. else
  1517. {
  1518. this.ReinterpretExpressionAsPattern(expr);
  1519. }
  1520. token=this.NextToken();
  1521. let operator=token.Value;
  1522. let right=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
  1523. expr=this.Finalize(this.StartNode(startToken), this.Node.AssignmentExpression(operator, expr, right));
  1524. this.Context.FirstCoverInitializedNameError=null;
  1525. }
  1526. return expr;
  1527. }
  1528. this.ParseConditionalExpression=function()
  1529. {
  1530. let startToken=this.LookAhead;
  1531. let expr=this.InheritCoverGrammar(this.ParseBinaryExpression);
  1532. return expr;
  1533. }
  1534. this.ParseBinaryExpression=function()
  1535. {
  1536. let startToken=this.LookAhead;
  1537. let expr=this.InheritCoverGrammar(this.ParseExponentiationExpression);
  1538. let token=this.LookAhead;
  1539. var prec=this.BinaryPrecedence(token);
  1540. if (prec>0)
  1541. {
  1542. this.NextToken();
  1543. this.Context.IsAssignmentTarget=false;
  1544. this.Context.IsBindingElement=false;
  1545. let markers=[startToken,this.LookAhead];
  1546. let left=expr;
  1547. let right=this.IsolateCoverGrammar(this.ParseExponentiationExpression);
  1548. let stack=[left,token.Value,right];
  1549. let precedences = [prec];
  1550. while(true)
  1551. {
  1552. prec=this.BinaryPrecedence(this.LookAhead);
  1553. if (prec<=0) break;
  1554. while(stack.length>2 && prec<=precedences[precedences.length-1])
  1555. {
  1556. right=stack.pop();
  1557. let operator=stack.pop();
  1558. precedences.pop();
  1559. left=stack.pop();
  1560. markers.pop();
  1561. let node=this.StartNode(markers[markers.length - 1]);
  1562. stack.push(this.Finalize(node, this.Node.BinaryExpression(operator, left, right)));
  1563. }
  1564. //Shift
  1565. stack.push(this.NextToken().Value);
  1566. precedences.push(prec);
  1567. markers.push(this.LookAhead);
  1568. stack.push(this.IsolateCoverGrammar(this.ParseExponentiationExpression));
  1569. }
  1570. let i=stack.length-1;
  1571. expr=stack[i];
  1572. let lastMarker=markers.pop();
  1573. while(i>1)
  1574. {
  1575. let marker=markers.pop();
  1576. let lastLineStart=lastMarker && lastMarker.LineStart;
  1577. let node=this.StartNode(marker, lastLineStart);
  1578. let operator=stack[i-1];
  1579. expr=this.Finalize(node, this.Node.BinaryExpression(operator, stack[i - 2], expr));
  1580. i-=2;
  1581. lastMarker=marker;
  1582. }
  1583. }
  1584. return expr;
  1585. }
  1586. this.ParseExponentiationExpression=function()
  1587. {
  1588. let startToken=this.LookAhead;
  1589. let expr=this.InheritCoverGrammar(this.ParseUnaryExpression);
  1590. return expr;
  1591. }
  1592. this.ParseUnaryExpression=function()
  1593. {
  1594. let expr;
  1595. if (this.Match('+') || this.Match('-'))
  1596. {
  1597. let node=this.StartNode(this.LookAhead);
  1598. let token=this.NextToken();
  1599. expr=this.InheritCoverGrammar(this.ParseUnaryExpression);
  1600. expr=this.Finalize(node, this.Node.UnaryExpression(token.Value, expr));
  1601. this.Context.IsAssignmentTarget=false;
  1602. this.Context.IsBindingElement=false;
  1603. }
  1604. else
  1605. {
  1606. expr=this.ParseUpdateExpression();
  1607. }
  1608. return expr;
  1609. }
  1610. // https://tc39.github.io/ecma262/#sec-update-expressions
  1611. this.ParseUpdateExpression=function()
  1612. {
  1613. let expr;
  1614. let startToken=this.LookAhead;
  1615. expr=this.InheritCoverGrammar(this.ParseLeftHandSideExpressionAllowCall);
  1616. return expr;
  1617. }
  1618. this.ParseLeftHandSideExpressionAllowCall=function()
  1619. {
  1620. let startToken=this.LookAhead;
  1621. let expr;
  1622. expr=this.InheritCoverGrammar(this.ParsePrimaryExpression);
  1623. while(true)
  1624. {
  1625. if (this.Match('.'))
  1626. {
  1627. this.Context.IsBindingElement = false;
  1628. this.Context.IsAssignmentTarget = true;
  1629. this.Expect('.');
  1630. const property = this.ParseMemberIdentifierName();
  1631. expr = this.Finalize(this.StartNode(startToken), this.Node.StaticMemberExpression(expr, property,startToken));
  1632. }
  1633. else if (this.Match('('))
  1634. {
  1635. this.Context.IsBindingElement=false;
  1636. this.Context.IsAssignmentTarget=false;
  1637. var args=this.ParseArguments(); //解析 调用参数
  1638. expr = this.Finalize(this.StartNode(startToken), this.Node.CallExpression(expr, args, startToken));
  1639. }
  1640. else
  1641. {
  1642. break;
  1643. }
  1644. }
  1645. return expr;
  1646. }
  1647. /*
  1648. BooleanLiteral = 1,
  1649. EOF=2,
  1650. Identifier=3,
  1651. Keyword=4,
  1652. NullLiteral=5,
  1653. NumericLiteral=6,
  1654. Punctuator=7,
  1655. StringLiteral=9,
  1656. RegularExpression=9,
  1657. Template=10
  1658. */
  1659. this.IsIdentifierName = function (token)
  1660. {
  1661. return token.Type === 3 //Identifier
  1662. || token.Type === 4 //Keyword
  1663. || token.Type === 1 //BooleanLiteral
  1664. || token.Type === 5;//NullLiteral;
  1665. }
  1666. this.ParseIdentifierName = function ()
  1667. {
  1668. const node = this.CreateNode();
  1669. const token = this.NextToken();
  1670. if (!this.IsIdentifierName(token))
  1671. {
  1672. this.ThrowUnexpectedToken(token);
  1673. }
  1674. return this.Finalize(node, this.Node.Identifier(token.Value, token));
  1675. }
  1676. this.ParseMemberIdentifierName=function()
  1677. {
  1678. const node = this.CreateNode();
  1679. const token = this.NextToken();
  1680. if (!this.IsIdentifierName(token))
  1681. {
  1682. this.ThrowUnexpectedToken(token);
  1683. }
  1684. return this.Finalize(node, this.Node.MemberIdentifier(token.Value, token));
  1685. }
  1686. // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions
  1687. this.ParseArguments=function()
  1688. {
  1689. this.Expect('(');
  1690. var args=[];
  1691. if (!this.Match(')'))
  1692. {
  1693. while(true)
  1694. {
  1695. let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
  1696. args.push(expr);
  1697. if (this.Match(')')) break;
  1698. this.ExpectCommaSeparator();
  1699. if (this.Match(')')) break;
  1700. }
  1701. }
  1702. this.Expect(')');
  1703. return args;
  1704. }
  1705. // Quietly expect a comma when in tolerant mode, otherwise delegates to expect().
  1706. this.ExpectCommaSeparator=function()
  1707. {
  1708. this.Expect(',');
  1709. }
  1710. // https://tc39.github.io/ecma262/#sec-primary-expression
  1711. this.ParsePrimaryExpression=function()
  1712. {
  1713. let node=this.CreateNode();
  1714. let expr;
  1715. var token, raw;
  1716. switch(this.LookAhead.Type)
  1717. {
  1718. case 3:/* Identifier */
  1719. token = this.NextToken();
  1720. expr = this.Finalize(node, this.Node.Identifier(token.Value, token));
  1721. break;
  1722. case 6:/* NumericLiteral */
  1723. case 8:/* StringLiteral */
  1724. this.Context.IsAssignmentTarget=false;
  1725. this.Context.IsBindingElement=false;
  1726. token=this.NextToken();
  1727. raw=this.GetTokenRaw(token);
  1728. expr=this.Finalize(node, this.Node.Literal(token.Value,raw,token));
  1729. break;
  1730. case 7:/* Punctuator */
  1731. switch(this.LookAhead.Value)
  1732. {
  1733. case '(':
  1734. this.Context.IsBindingElement=false;
  1735. expr=this.InheritCoverGrammar(this.ParseGroupExpression);
  1736. break;
  1737. default:
  1738. expr=this.ThrowUnexpectedToken(this.NextToken())
  1739. }
  1740. break;
  1741. default:
  1742. expr = this.ThrowUnexpectedToken(this.NextToken());
  1743. }
  1744. return expr;
  1745. }
  1746. this.ParseGroupExpression=function()
  1747. {
  1748. let expr;
  1749. this.Expect('(');
  1750. if (this.Match(')'))
  1751. {
  1752. this.NextToken();
  1753. }
  1754. else
  1755. {
  1756. let startToken=this.LookAhead;
  1757. let params=[];
  1758. let arrow=false;
  1759. this.Context.IsBindingElement=true;
  1760. expr=this.InheritCoverGrammar(this.ParseAssignmentExpression);
  1761. if (this.Match(','))
  1762. {
  1763. let expressions=[];
  1764. this.Context.IsAssignmentTarget=false;
  1765. expressions.push(expr);
  1766. while(this.LookAhead.Type!=2 /* EOF */)
  1767. {
  1768. if (!this.Match(',')) break;
  1769. this.NextToken();
  1770. if (this.Match(')'))
  1771. {
  1772. }
  1773. }
  1774. }
  1775. if (!arrow)
  1776. {
  1777. this.Expect(')');
  1778. this.Context.IsBindingElement=false;
  1779. }
  1780. }
  1781. return expr;
  1782. }
  1783. // https://tc39.github.io/ecma262/#sec-expression-statement
  1784. this.ParseExpressionStatement=function()
  1785. {
  1786. let node=this.CreateNode();
  1787. let expr=this.ParseExpression();
  1788. this.ConsumeSemicolon();
  1789. return this.Finalize(node,this.Node.ExpressionStatement(expr));
  1790. }
  1791. this.ConsumeSemicolon=function()
  1792. {
  1793. if (this.Match(';'))
  1794. {
  1795. this.NextToken();
  1796. }
  1797. else if (!this.HasLineTerminator)
  1798. {
  1799. //if (this.LookAhead.Type!=2/*EOF*/ && !this.Match('}'))
  1800. this.LastMarker.Index=this.StartMarker.Index;
  1801. this.LastMarker.Line=this.StartMarker.Line;
  1802. this.LastMarker.Column=this.StartMarker.Column;
  1803. }
  1804. }
  1805. this.ReinterpretExpressionAsPattern=function(expr)
  1806. {
  1807. switch(expr.Type)
  1808. {
  1809. case Syntax.Identifier:
  1810. case Syntax.MemberExpression:
  1811. case Syntax.AssignmentExpression:
  1812. break;
  1813. default:
  1814. break;
  1815. }
  1816. }
  1817. this.Finalize=function(marker,node)
  1818. {
  1819. node.Marker={ Line:marker.Line, Column:marker.Column, Index:marker.Index };
  1820. return node;
  1821. }
  1822. this.BinaryPrecedence = function (token)
  1823. {
  1824. let op = token.Value;
  1825. let precedence;
  1826. if (token.Type === 7 /* Punctuator */) precedence = this.PeratorPrecedence[op] || 0;
  1827. else precedence = 0;
  1828. return precedence;
  1829. };
  1830. this.IsolateCoverGrammar=function(parseFunction)
  1831. {
  1832. let previousIsBindingElement=this.Context.IsBindingElement;
  1833. let previousIsAssignmentTarget=this.Context.IsAssignmentTarget;
  1834. let previousFirstCoverInitializedNameError=this.Context.FirstCoverInitializedNameError;
  1835. this.Context.IsBindingElement=true;
  1836. this.Context.IsAssignmentTarget=true;
  1837. this.Context.FirstCoverInitializedNameError=null;
  1838. let result=parseFunction.call(this);
  1839. if (this.Context.FirstCoverInitializedNameError!=null)
  1840. {
  1841. //错误 this.throwUnexpectedToken(this.context.firstCoverInitializedNameError);
  1842. }
  1843. this.Context.IsBindingElement=previousIsBindingElement;
  1844. this.Context.IsAssignmentTarget=previousIsAssignmentTarget;
  1845. this.Context.FirstCoverInitializedNameError=previousFirstCoverInitializedNameError;
  1846. return result;
  1847. }
  1848. this.InheritCoverGrammar = function (parseFunction)
  1849. {
  1850. let previousIsBindingElement = this.Context.IsBindingElement;
  1851. let previousIsAssignmentTarget = this.Context.IsAssignmentTarget;
  1852. let previousFirstCoverInitializedNameError = this.Context.FirstCoverInitializedNameError;
  1853. this.Context.IsBindingElement = true;
  1854. this.Context.IsAssignmentTarget = true;
  1855. this.Context.FirstCoverInitializedNameError = null;
  1856. let result = parseFunction.call(this);
  1857. this.Context.IsBindingElement = this.Context.IsBindingElement && previousIsBindingElement;
  1858. this.Context.IsAssignmentTarget = this.Context.IsAssignmentTarget && previousIsAssignmentTarget;
  1859. this.Context.FirstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.Context.FirstCoverInitializedNameError;
  1860. return result;
  1861. };
  1862. this.ThrowUnexpectedToken=function(token,message)
  1863. {
  1864. throw this.UnexpectedTokenError(token,message);
  1865. }
  1866. this.ThrowUnexpectedError=function(index,line,column,message)
  1867. {
  1868. let msg=message || "执行异常";
  1869. return this.ErrorHandler.ThrowError(index,line,column,msg);
  1870. }
  1871. this.UnexpectedTokenError=function(token,message)
  1872. {
  1873. let msg=message || Messages.UnexpectedToken;
  1874. let value='ILLEGAL';
  1875. if (token)
  1876. {
  1877. if (!message)
  1878. {
  1879. }
  1880. value=token.Value;
  1881. }
  1882. msg=msg.replace("%0",value);
  1883. if (token && typeof(token.LineNumber)=='number')
  1884. {
  1885. let index=token.Start;
  1886. let line=token.LineNumber;
  1887. let lastMarkerLineStart=this.LastMarker.Index-this.LastMarker.Column;
  1888. let column=token.Start-lastMarkerLineStart+1;
  1889. return this.ErrorHandler.CreateError(index,line,column,msg);
  1890. }
  1891. else
  1892. {
  1893. let index=this.LastMarker.Index;
  1894. let line=this.LastMarker.Line;
  1895. let column=this.LastMarker.Column+1;
  1896. return this.ErrorHandler.CreateError(index,line,column,msg);
  1897. }
  1898. }
  1899. }
  1900. /*
  1901. 算法类
  1902. */
  1903. function JSAlgorithm(errorHandler, symbolData)
  1904. {
  1905. this.ErrorHandler=errorHandler;
  1906. this.SymbolData = symbolData; //股票数据
  1907. //相加
  1908. this.Add=function(data,data2)
  1909. {
  1910. let isNumber=typeof(data)=='number';
  1911. let isNumber2=typeof(data2)=='number';
  1912. //单数值相加
  1913. if (isNumber && isNumber2) return data+data2;
  1914. //都是数组相加
  1915. let result=[];
  1916. if (!isNumber && !isNumber2)
  1917. {
  1918. let count=Math.max(data.length, data2.length);
  1919. for(let i=0;i<count;++i)
  1920. {
  1921. result[i]=null; //初始化
  1922. if (i<data.length && i<data2.length)
  1923. {
  1924. if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]+data2[i];
  1925. }
  1926. }
  1927. return result;
  1928. }
  1929. //单数据和数组相加
  1930. let value;
  1931. let aryData;
  1932. if (isNumber)
  1933. {
  1934. value=data;
  1935. aryData=data2;
  1936. }
  1937. else
  1938. {
  1939. value=data2;
  1940. aryData=data;
  1941. }
  1942. for(let i in aryData)
  1943. {
  1944. result[i]=null;
  1945. if (this.IsNumber(aryData[i]) && this.IsNumber(value)) result[i]=value+aryData[i];
  1946. }
  1947. return result;
  1948. }
  1949. //相减
  1950. this.Subtract=function(data,data2)
  1951. {
  1952. let isNumber=typeof(data)=='number';
  1953. let isNumber2=typeof(data2)=='number';
  1954. //单数值相减
  1955. if (isNumber && isNumber2) return data-data2;
  1956. //都是数组相减
  1957. let result=[];
  1958. if (!isNumber && !isNumber2)
  1959. {
  1960. let count=Math.max(data.length, data2.length);
  1961. for(let i=0;i<count;++i)
  1962. {
  1963. result[i]=null; //初始化
  1964. if (i<data.length && i<data2.length)
  1965. {
  1966. if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]-data2[i];
  1967. }
  1968. }
  1969. return result;
  1970. }
  1971. if (isNumber) //单数据-数组
  1972. {
  1973. for(let i in data2)
  1974. {
  1975. result[i]=null;
  1976. if (this.IsNumber(data) && this.IsNumber(data2[i])) result[i]=data-data2[i];
  1977. }
  1978. }
  1979. else //数组-单数据
  1980. {
  1981. for(let i in data)
  1982. {
  1983. result[i]=null;
  1984. if (this.IsNumber(data[i]) && this.IsNumber(data2)) result[i]=data[i]-data2;
  1985. }
  1986. }
  1987. return result;
  1988. }
  1989. //相乘
  1990. this.Multiply=function(data,data2)
  1991. {
  1992. let isNumber=typeof(data)=='number';
  1993. let isNumber2=typeof(data2)=='number';
  1994. //单数值相乘
  1995. if (isNumber && isNumber2) return data*data2;
  1996. //都是数组相乘
  1997. let result=[];
  1998. if (!isNumber && !isNumber2)
  1999. {
  2000. let count=Math.max(data.length, data2.length);
  2001. for(let i=0;i<count;++i)
  2002. {
  2003. result[i]=null; //初始化
  2004. if (i<data.length && i<data2.length)
  2005. {
  2006. if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]*data2[i];
  2007. }
  2008. }
  2009. return result;
  2010. }
  2011. //单数据和数组相乘
  2012. let value;
  2013. let aryData;
  2014. if (isNumber)
  2015. {
  2016. value=data;
  2017. aryData=data2;
  2018. }
  2019. else
  2020. {
  2021. value=data2;
  2022. aryData=data;
  2023. }
  2024. for(let i in aryData)
  2025. {
  2026. result[i]=null;
  2027. if (this.IsNumber(aryData[i]) && this.IsNumber(value)) result[i]=value*aryData[i];
  2028. }
  2029. return result;
  2030. }
  2031. //相除
  2032. this.Divide=function(data,data2)
  2033. {
  2034. let isNumber=typeof(data)=='number';
  2035. let isNumber2=typeof(data2)=='number';
  2036. //单数值相除
  2037. if (isNumber && isNumber2)
  2038. {
  2039. if (data2==0) return null; //除0判断
  2040. return data/data2;
  2041. }
  2042. //都是数组相除
  2043. let result=[];
  2044. if (!isNumber && !isNumber2)
  2045. {
  2046. let count=Math.max(data.length, data2.length);
  2047. for(let i=0;i<count;++i)
  2048. {
  2049. result[i]=null; //初始化
  2050. if (i<data.length && i<data2.length)
  2051. {
  2052. if ( this.IsNumber(data[i]) && this.IsDivideNumber(data2[i]) ) result[i]=data[i]/data2[i];
  2053. }
  2054. }
  2055. return result;
  2056. }
  2057. if (isNumber) //单数据-数组
  2058. {
  2059. for(let i in data2)
  2060. {
  2061. result[i]=null;
  2062. if ( this.IsNumber(data) && this.IsDivideNumber(data2[i]) ) result[i]=data/data2[i];
  2063. }
  2064. }
  2065. else //数组-单数据
  2066. {
  2067. for(let i in data)
  2068. {
  2069. result[i]=null;
  2070. if ( this.IsNumber(data[i]) && this.IsDivideNumber(data2) ) result[i]=data[i]/data2;
  2071. }
  2072. }
  2073. return result;
  2074. }
  2075. //大于
  2076. this.GT=function(data,data2)
  2077. {
  2078. let isNumber=IFrameSplitOperator.IsNumber(data);
  2079. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  2080. //单数值比较
  2081. if (isNumber && isNumber2) return (data>data2 ? 1 : 0);
  2082. //都是数组比较
  2083. let result=[];
  2084. if (Array.isArray(data) && Array.isArray(data2))
  2085. {
  2086. let count=Math.max(data.length, data2.length);
  2087. for(let i=0;i<count;++i)
  2088. {
  2089. result[i]=null; //初始化
  2090. if (i<data.length && i<data2.length)
  2091. {
  2092. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2093. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2094. result[i]=(data[i]>data2[i] ? 1:0);
  2095. }
  2096. }
  2097. return result;
  2098. }
  2099. if (isNumber) //单数据-数组
  2100. {
  2101. for(let i in data2)
  2102. {
  2103. result[i]=null;
  2104. if (!IFrameSplitOperator.IsVaild(data)) continue;
  2105. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2106. result[i]=(data>data2[i] ? 1 : 0);
  2107. }
  2108. }
  2109. else //数组-单数据
  2110. {
  2111. for(let i in data)
  2112. {
  2113. result[i]=null;
  2114. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2115. if (!IFrameSplitOperator.IsVaild(data2)) continue;
  2116. result[i]=(data[i]>data2 ? 1 : 0);
  2117. }
  2118. }
  2119. return result;
  2120. }
  2121. //大于等于
  2122. this.GTE=function(data,data2)
  2123. {
  2124. let isNumber=IFrameSplitOperator.IsNumber(data);
  2125. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  2126. //单数值比较
  2127. if (isNumber && isNumber2) return (data>=data2 ? 1 : 0);
  2128. //都是数组比较
  2129. let result=[];
  2130. if (Array.isArray(data) && Array.isArray(data2))
  2131. {
  2132. let count=Math.max(data.length, data2.length);
  2133. for(let i=0;i<count;++i)
  2134. {
  2135. result[i]=null; //初始化
  2136. if (i<data.length && i<data2.length)
  2137. {
  2138. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2139. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2140. result[i]=(data[i]>=data2[i] ? 1:0);
  2141. }
  2142. }
  2143. return result;
  2144. }
  2145. if (isNumber) //单数据-数组
  2146. {
  2147. for(let i in data2)
  2148. {
  2149. result[i]=null;
  2150. if (!IFrameSplitOperator.IsVaild(data)) continue;
  2151. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2152. result[i]=(data>=data2[i] ? 1 : 0);
  2153. }
  2154. }
  2155. else //数组-单数据
  2156. {
  2157. for(let i in data)
  2158. {
  2159. result[i]=null;
  2160. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2161. if (!IFrameSplitOperator.IsVaild(data2)) continue;
  2162. result[i]=(data[i]>=data2 ? 1 : 0);
  2163. }
  2164. }
  2165. return result;
  2166. }
  2167. //小于
  2168. this.LT=function(data,data2)
  2169. {
  2170. let isNumber=IFrameSplitOperator.IsNumber(data);
  2171. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  2172. //单数值比较
  2173. if (isNumber && isNumber2) return (data<data2 ? 1 : 0);
  2174. //都是数组比较
  2175. let result=[];
  2176. if (Array.isArray(data) && Array.isArray(data2))
  2177. {
  2178. let count=Math.max(data.length, data2.length);
  2179. for(let i=0;i<count;++i)
  2180. {
  2181. result[i]=null; //初始化
  2182. if (i<data.length && i<data2.length)
  2183. {
  2184. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2185. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2186. result[i]=(data[i]<data2[i] ? 1:0);
  2187. }
  2188. }
  2189. return result;
  2190. }
  2191. if (isNumber) //单数据-数组
  2192. {
  2193. for(let i in data2)
  2194. {
  2195. result[i]=null;
  2196. if (!IFrameSplitOperator.IsVaild(data)) continue;
  2197. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2198. if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data<data2[i] ? 1 : 0);
  2199. }
  2200. }
  2201. else //数组-单数据
  2202. {
  2203. for(let i in data)
  2204. {
  2205. result[i]=null;
  2206. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2207. if (!IFrameSplitOperator.IsVaild(data2)) continue;
  2208. result[i]=(data[i]<data2 ? 1 : 0);
  2209. }
  2210. }
  2211. return result;
  2212. }
  2213. //小于等于
  2214. this.LTE=function(data,data2)
  2215. {
  2216. let isNumber=IFrameSplitOperator.IsNumber(data);
  2217. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  2218. //单数值比较
  2219. if (isNumber && isNumber2) return (data>=data2 ? 1 : 0);
  2220. //都是数组比较
  2221. let result=[];
  2222. if (Array.isArray(data) && Array.isArray(data2))
  2223. {
  2224. let count=Math.max(data.length, data2.length);
  2225. for(let i=0;i<count;++i)
  2226. {
  2227. result[i]=null; //初始化
  2228. if (i<data.length && i<data2.length)
  2229. {
  2230. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2231. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2232. result[i]=(data[i]<=data2[i] ? 1:0);
  2233. }
  2234. }
  2235. return result;
  2236. }
  2237. if (isNumber) //单数据-数组
  2238. {
  2239. for(let i in data2)
  2240. {
  2241. result[i]=null;
  2242. if (!IFrameSplitOperator.IsVaild(data)) continue;
  2243. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2244. result[i]=(data<=data2[i] ? 1 : 0);
  2245. }
  2246. }
  2247. else //数组-单数据
  2248. {
  2249. for(let i in data)
  2250. {
  2251. result[i]=null;
  2252. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2253. if (!IFrameSplitOperator.IsVaild(data2)) continue;
  2254. result[i]=(data[i]<=data2 ? 1 : 0);
  2255. }
  2256. }
  2257. return result;
  2258. }
  2259. //等于
  2260. this.EQ=function(data,data2)
  2261. {
  2262. let isNumber=IFrameSplitOperator.IsNumber(data);
  2263. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  2264. //单数值比较
  2265. if (isNumber && isNumber2) return (data==data2 ? 1 : 0);
  2266. //都是数组比较
  2267. let result=[];
  2268. if (Array.isArray(data) && Array.isArray(data2))
  2269. {
  2270. let count=Math.max(data.length, data2.length);
  2271. for(let i=0;i<count;++i)
  2272. {
  2273. result[i]=null; //初始化
  2274. if (i<data.length && i<data2.length)
  2275. {
  2276. if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i]==data2[i] ? 1:0);
  2277. }
  2278. }
  2279. return result;
  2280. }
  2281. if (isNumber) //单数据-数组
  2282. {
  2283. for(let i in data2)
  2284. {
  2285. result[i]=null;
  2286. if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data==data2[i] ? 1 : 0);
  2287. }
  2288. }
  2289. else //数组-单数据
  2290. {
  2291. for(let i in data)
  2292. {
  2293. result[i]=null;
  2294. if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i]==data2 ? 1 : 0);
  2295. }
  2296. }
  2297. return result;
  2298. }
  2299. //不等于
  2300. this.NEQ = function (data, data2)
  2301. {
  2302. let isNumber=IFrameSplitOperator.IsNumber(data);
  2303. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  2304. //单数值比较
  2305. if (isNumber && isNumber2) return (data != data2 ? 1 : 0);
  2306. //都是数组比较
  2307. let result = [];
  2308. if (Array.isArray(data) && Array.isArray(data2))
  2309. {
  2310. let count = Math.max(data.length, data2.length);
  2311. for (let i = 0; i < count; ++i)
  2312. {
  2313. result[i] = null; //初始化
  2314. if (i < data.length && i < data2.length)
  2315. {
  2316. if (!isNaN(data[i]) && !isNaN(data2[i])) result[i] = (data[i] != data2[i] ? 1 : 0);
  2317. }
  2318. }
  2319. return result;
  2320. }
  2321. if (isNumber) //单数据-数组
  2322. {
  2323. for (let i in data2)
  2324. {
  2325. result[i] = null;
  2326. if (!isNaN(data) && !isNaN(data2[i])) result[i] = (data != data2[i] ? 1 : 0);
  2327. }
  2328. }
  2329. else //数组-单数据
  2330. {
  2331. for (let i in data)
  2332. {
  2333. result[i] = null;
  2334. if (!isNaN(data[i]) && !isNaN(data2)) result[i] = (data[i] != data2 ? 1 : 0);
  2335. }
  2336. }
  2337. return result;
  2338. }
  2339. //AND &&
  2340. this.And=function(data,data2)
  2341. {
  2342. let isNumber=typeof(data)=='number';
  2343. let isNumber2=typeof(data2)=='number';
  2344. //单数值 &&
  2345. if (isNumber && isNumber2) return (data && data2 ? 1 : 0);
  2346. //都是数组 &&
  2347. let result=[];
  2348. if (!isNumber && !isNumber2)
  2349. {
  2350. let count=Math.max(data.length, data2.length);
  2351. for(let i=0;i<count;++i)
  2352. {
  2353. result[i]=null; //初始化
  2354. if (i<data.length && i<data2.length)
  2355. {
  2356. if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i] && data2[i] ? 1:0);
  2357. }
  2358. }
  2359. return result;
  2360. }
  2361. if (isNumber) //单数据-数组
  2362. {
  2363. for(let i in data2)
  2364. {
  2365. result[i]=null;
  2366. if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data && data2[i] ? 1 : 0);
  2367. }
  2368. }
  2369. else //数组-单数据
  2370. {
  2371. for(let i in data)
  2372. {
  2373. result[i]=null;
  2374. if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i] && data2 ? 1 : 0);
  2375. }
  2376. }
  2377. return result;
  2378. }
  2379. //OR ||
  2380. this.Or=function(data,data2)
  2381. {
  2382. let isNumber=typeof(data)=='number';
  2383. let isNumber2=typeof(data2)=='number';
  2384. //单数值 &&
  2385. if (isNumber && isNumber2) return (data || data2 ? 1 : 0);
  2386. //都是数组 &&
  2387. let result=[];
  2388. if (!isNumber && !isNumber2)
  2389. {
  2390. let count=Math.max(data.length, data2.length);
  2391. for(let i=0;i<count;++i)
  2392. {
  2393. result[i]=null; //初始化
  2394. if (i<data.length && i<data2.length)
  2395. {
  2396. if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i] || data2[i] ? 1:0);
  2397. }
  2398. }
  2399. return result;
  2400. }
  2401. if (isNumber) //单数据-数组
  2402. {
  2403. for(let i in data2)
  2404. {
  2405. result[i]=null;
  2406. if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data || data2[i] ? 1 : 0);
  2407. }
  2408. }
  2409. else //数组-单数据
  2410. {
  2411. for(let i in data)
  2412. {
  2413. result[i]=null;
  2414. if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i] || data2 ? 1 : 0);
  2415. }
  2416. }
  2417. return result;
  2418. }
  2419. this.IF=function(data,trueData,falseData)
  2420. {
  2421. let isNumber=this.IsNumber(data);
  2422. let isNumber2=this.IsNumber(trueData);
  2423. let isNumber3=this.IsNumber(falseData);
  2424. var isArray2=Array.isArray(trueData);
  2425. var isArray3=Array.isArray(falseData);
  2426. //单数值
  2427. if (isNumber)
  2428. {
  2429. if (isNumber2 && isNumber3) return data?trueData:falseData;
  2430. return data? trueData:falseData;
  2431. }
  2432. //都是数组
  2433. let result=[];
  2434. for(let i in data)
  2435. {
  2436. if (data[i])
  2437. {
  2438. if (isNumber2) result[i]=trueData;
  2439. else if (isArray2) result[i]=trueData[i];
  2440. else result[i]=null;
  2441. }
  2442. else
  2443. {
  2444. if (isNumber3) result[i]=falseData;
  2445. else if (isArray3) result[i]=falseData[i];
  2446. else result[i]=null;
  2447. }
  2448. }
  2449. return result;
  2450. }
  2451. /*
  2452. 根据条件求不同的值,同IF判断相反.
  2453. 用法: IFN(X,A,B)若X不为0则返回B,否则返回A
  2454. 例如: IFN(CLOSE>OPEN,HIGH,LOW)表示该周期收阴则返回最高值,否则返回最低值
  2455. */
  2456. this.IFN=function(data,trueData,falseData)
  2457. {
  2458. return this.IF(data,falseData,trueData);
  2459. }
  2460. //指标函数 函数名全部大写
  2461. this.REF=function(data,n)
  2462. {
  2463. let result=[];
  2464. if (typeof(n)=='number')
  2465. {
  2466. if (IFrameSplitOperator.IsNumber(data)) //单数值
  2467. {
  2468. if (n<0) return result;
  2469. var kData=this.SymbolData.Data.Data;
  2470. if (!kData || kData.length<=0) return result;
  2471. var count=kData.length;
  2472. for(var i=n;i<count;++i)
  2473. {
  2474. result[i]=data;
  2475. }
  2476. }
  2477. else
  2478. {
  2479. if (data.length<=0) return result;
  2480. if (n>=data.length) return result;
  2481. result=data.slice(0,data.length-n);
  2482. for(let i=0;i<n;++i)
  2483. result.unshift(null);
  2484. }
  2485. }
  2486. else //n 为数组的情况
  2487. {
  2488. for(let i=0;i<data.length;++i)
  2489. {
  2490. result[i]=null;
  2491. if (i>=n.length) continue;
  2492. var value=n[i];
  2493. if (value>0 && value<=i) result[i]=data[i-value];
  2494. else if (i) result[i]=result[i-1];
  2495. else result[i]=data[i];
  2496. }
  2497. }
  2498. return result;
  2499. }
  2500. //引用若干周期前的数据(未作平滑处理).
  2501. //用法: REFV(X,A),引用A周期前的X值.A可以是变量.
  2502. //平滑处理:当引用不到数据时进行的操作.
  2503. //例如: REFV(CLOSE,BARSCOUNT(C)-1)表示第二根K线的收盘价.
  2504. this.REFV=function(data,n)
  2505. {
  2506. let result=[];
  2507. if (typeof(n)=='number')
  2508. {
  2509. if (data.length<=0) return result;
  2510. if (n>=data.length) return result;
  2511. result=data.slice(0,data.length-n);
  2512. for(let i=0;i<n;++i) //不作平滑处理
  2513. result.unshift(null);
  2514. }
  2515. else //n 为数组的情况
  2516. {
  2517. for(let i=0;i<data.length;++i)
  2518. {
  2519. result[i]=null;
  2520. if (i>=n.length) continue;
  2521. var value=n[i];
  2522. if (value>=0 && value<=i) result[i]=data[i-value];
  2523. }
  2524. }
  2525. return result;
  2526. }
  2527. //属于未来函数,引用若干周期后的数据(平滑处理).
  2528. //用法: REFX(X,A),引用A周期后的X值.A可以是变量.
  2529. //平滑处理:当引用不到数据时进行的操作.此函数中,平滑时使用上一个周期的引用值.
  2530. //例如: TT:=IF(C>O,1,2);
  2531. // REFX(CLOSE,TT);表示阳线引用下一周期的收盘价,阴线引用日后第二周期的收盘价.
  2532. this.REFX=function(data,n)
  2533. {
  2534. let result=[];
  2535. if (typeof(n)=='number')
  2536. {
  2537. if (data.length<=0) return result;
  2538. if (n>=data.length) return result;
  2539. result=data.slice(n,data.length);
  2540. //平滑处理
  2541. var lastData=data[data.length-1];
  2542. for(let i=0;i<n;++i)
  2543. result.push(lastData);
  2544. }
  2545. else //n 为数组的情况
  2546. {
  2547. var dataCount=data.length;
  2548. for(let i=0;i<data.length;++i)
  2549. {
  2550. result[i]=null;
  2551. if (i>=n.length) continue;
  2552. var value=n[i];
  2553. if (value>=0 && value+i<dataCount) result[i]=data[i+value];
  2554. else if (i) result[i]=result[i-1];
  2555. else result[i]=data[i];
  2556. }
  2557. }
  2558. return result;
  2559. }
  2560. //属于未来函数,引用若干周期后的数据(未作平滑处理).
  2561. //用法:REFXV(X,A),引用A周期后的X值.A可以是变量.
  2562. //平滑处理:当引用不到数据时进行的操作.
  2563. //例如: REFXV(CLOSE,1)表示下一周期的收盘价,在日线上就是明天收盘价
  2564. this.REFXV=function(data,n)
  2565. {
  2566. let result=[];
  2567. if (typeof(n)=='number')
  2568. {
  2569. if (data.length<=0) return result;
  2570. if (n>=data.length) return result;
  2571. result=data.slice(n,data.length);
  2572. //平滑处理
  2573. for(let i=0;i<n;++i)
  2574. result.push(null);
  2575. }
  2576. else //n 为数组的情况
  2577. {
  2578. var dataCount=data.length;
  2579. for(let i=0;i<data.length;++i)
  2580. {
  2581. result[i]=null;
  2582. if (i>=n.length) continue;
  2583. var value=n[i];
  2584. if (value>=0 && value+i<dataCount) result[i]=data[i+value];
  2585. }
  2586. }
  2587. return result;
  2588. }
  2589. //求最大值.
  2590. //用法:MAX(A,B,C,D ..... ) 返回A,B,C,D ..... 中的较大值
  2591. //例如: MAX(CLOSE-OPEN,0)表示若收盘价大于开盘价返回它们的差值,否则返回0
  2592. this.MAX=function(args, node)
  2593. {
  2594. if (args.length==0) this.ThrowUnexpectedNode(node,'MAX() Error: 参数个数不能为0');
  2595. if (args.length==1) return args[0];
  2596. var aryData=[], aryNumber=[];
  2597. for(var i in args)
  2598. {
  2599. var item=args[i];
  2600. if (IFrameSplitOperator.IsNumber(item)) aryNumber.push(item);
  2601. else if (Array.isArray(item)) aryData.push(item);
  2602. }
  2603. var maxNumber=null;
  2604. if (aryNumber.length>0)
  2605. {
  2606. maxNumber=aryNumber[0];
  2607. for(var i=1; i<aryNumber.length; ++i)
  2608. {
  2609. maxNumber=Math.max(maxNumber,aryNumber[i]);
  2610. }
  2611. }
  2612. var maxAryData=null;
  2613. if (aryData.length>0)
  2614. {
  2615. maxAryData=aryData[0].slice(0);
  2616. for(var i=1;i<aryData.length;++i)
  2617. {
  2618. var dataItem=aryData[i];
  2619. for(var j in dataItem)
  2620. {
  2621. var maxItem=maxAryData[j];
  2622. var item=dataItem[j];
  2623. if (!IFrameSplitOperator.IsNumber(maxItem)) continue;
  2624. if (!IFrameSplitOperator.IsNumber(item))
  2625. {
  2626. maxAryData[j]=null;
  2627. continue;
  2628. }
  2629. maxAryData[j]=Math.max(maxItem,item);
  2630. }
  2631. }
  2632. }
  2633. if (maxAryData==null && maxNumber!=null) return maxNumber;
  2634. if (maxAryData && maxNumber==null) return maxAryData;
  2635. for(var i in maxAryData)
  2636. {
  2637. if (!IFrameSplitOperator.IsNumber(maxAryData[i])) continue;
  2638. maxAryData[i]=Math.max(maxAryData[i],maxNumber);
  2639. }
  2640. return maxAryData;
  2641. }
  2642. //求最小值.
  2643. //用法:MIN(A,B, C, D .....)返回A,B, C ,D ......中的较小值
  2644. //例如:MIN(CLOSE,OPEN)返回开盘价和收盘价中的较小值
  2645. this.MIN=function(args, node)
  2646. {
  2647. if (args.length==0) this.ThrowUnexpectedNode(node,'MIN() Error: 参数个数不能为0');
  2648. if (args.length==1) return args[0];
  2649. var aryData=[], aryNumber=[];
  2650. for(var i in args)
  2651. {
  2652. var item=args[i];
  2653. if (IFrameSplitOperator.IsNumber(item)) aryNumber.push(item);
  2654. else if (Array.isArray(item)) aryData.push(item);
  2655. }
  2656. var minNumber=null;
  2657. if (aryNumber.length>0)
  2658. {
  2659. minNumber=aryNumber[0];
  2660. for(var i=1; i<aryNumber.length; ++i)
  2661. {
  2662. minNumber=Math.min(minNumber,aryNumber[i]);
  2663. }
  2664. }
  2665. var minAryData=null;
  2666. if (aryData.length>0)
  2667. {
  2668. minAryData=aryData[0].slice(0);
  2669. for(var i=1;i<aryData.length;++i)
  2670. {
  2671. var dataItem=aryData[i];
  2672. for(var j in dataItem)
  2673. {
  2674. var minItem=minAryData[j];
  2675. var item=dataItem[j];
  2676. if (!IFrameSplitOperator.IsNumber(minItem)) continue;
  2677. if (!IFrameSplitOperator.IsNumber(item))
  2678. {
  2679. minAryData[j]=null;
  2680. continue;
  2681. }
  2682. minAryData[j]=Math.min(minItem,item);
  2683. }
  2684. }
  2685. }
  2686. if (minAryData==null && minNumber!=null) return minNumber;
  2687. if (minAryData && minNumber==null) return minAryData;
  2688. for(var i in minAryData)
  2689. {
  2690. if (!IFrameSplitOperator.IsNumber(minAryData[i])) continue;
  2691. minAryData[i]=Math.min(minAryData[i],minNumber);
  2692. }
  2693. return minAryData;
  2694. }
  2695. //取正数
  2696. this.ABS=function(data)
  2697. {
  2698. let result=[];
  2699. for(let i in data)
  2700. {
  2701. result[i]=null;
  2702. if (!isNaN(data[i])) result[i]=Math.abs(data[i]);
  2703. }
  2704. return result;
  2705. }
  2706. this.MA=function(data,dayCount)
  2707. {
  2708. let result=[];
  2709. if (dayCount<=0) return result;
  2710. if (!Array.isArray(dayCount))
  2711. {
  2712. dayCount=parseInt(dayCount);
  2713. if (dayCount<=0) dayCount=1;
  2714. if (!data || !data.length) return result;
  2715. for(var i=0;i<data.length;++i)
  2716. {
  2717. result[i]=null;
  2718. if (this.IsNumber(data[i])) break;
  2719. }
  2720. var data=data.slice(0); //复制一份数据出来
  2721. for(var days=0;i<data.length;++i,++days)
  2722. {
  2723. if (days<dayCount-1)
  2724. {
  2725. result[i]=null;
  2726. continue;
  2727. }
  2728. let preValue=data[i-(dayCount-1)];
  2729. let sum=0;
  2730. for(let j=dayCount-1;j>=0;--j)
  2731. {
  2732. var value=data[i-j];
  2733. if (!this.IsNumber(value))
  2734. {
  2735. value=preValue; //空数据就取上一个数据
  2736. data[i-j]=value;
  2737. }
  2738. else
  2739. {
  2740. preValue=value;
  2741. }
  2742. sum+=value;
  2743. }
  2744. result[i]=sum/dayCount;
  2745. }
  2746. }
  2747. else
  2748. {
  2749. for(var i=0;i<data.length;++i)
  2750. {
  2751. result[i]=null;
  2752. if (i>=dayCount.length) continue;
  2753. var sumCount=dayCount[i];
  2754. if (!this.IsNumber(sumCount)) continue;
  2755. if (sumCount<=0) continue;
  2756. var sum=0;
  2757. var count=0;
  2758. for(var j=i, k=0;j>=0 && k<sumCount;--j,++k)
  2759. {
  2760. sum+=data[j];
  2761. ++count;
  2762. }
  2763. if (count>0) result[i]=sum/count;
  2764. }
  2765. }
  2766. return result;
  2767. }
  2768. //指数平均数指标 EMA(close,10)
  2769. //N 支持周期数组
  2770. this.EMA=function(data,dayCount)
  2771. {
  2772. var result = [];
  2773. if (data.length<=0) return result;
  2774. if (Array.isArray(dayCount))
  2775. {
  2776. for(var i=0;i<dayCount.length;++i)
  2777. {
  2778. var period=dayCount[i];
  2779. if (!this.IsNumber(period)) continue;
  2780. period=parseInt(period); //周期用整数
  2781. if (period<=0) continue;
  2782. if (period>i+1) period=i+1;
  2783. //EMA(N) = 2/(N+1)*C + (N-1)/(N+1)*EMA', EMA'为前一天的ema
  2784. var EMAFactor=[ 2/ (period + 1), (period - 1) / (period + 1)];
  2785. var ema=null;
  2786. var lastEMA=null;
  2787. for(var j=0;j<period;++j)
  2788. {
  2789. var index=i-(period-j-1);
  2790. var value=data[index];
  2791. if (!this.IsNumber(value)) coninue;
  2792. if (lastEMA==null)
  2793. {
  2794. ema=value; //第一个EMA为第一个数据的价格
  2795. lastEMA=ema;
  2796. }
  2797. else
  2798. {
  2799. ema = EMAFactor[0] * value + EMAFactor[1] * lastEMA;
  2800. lastEMA=ema;
  2801. }
  2802. }
  2803. result[i]=ema;
  2804. }
  2805. }
  2806. else
  2807. {
  2808. dayCount=parseInt(dayCount);
  2809. if (dayCount<=0) return result;
  2810. var offset=0;
  2811. //取首个有效数据
  2812. for(;offset<data.length;++offset)
  2813. {
  2814. if (data[offset]!=null && !isNaN(data[offset]))
  2815. break;
  2816. }
  2817. var p1Index=offset;
  2818. var p2Index=offset+1;
  2819. result[p1Index]=data[p1Index];
  2820. for(var i=offset+1;i<data.length;++i,++p1Index,++p2Index)
  2821. {
  2822. result[p2Index]=((2*data[p2Index]+(dayCount-1)*result[p1Index]))/(dayCount+1);
  2823. }
  2824. }
  2825. return result;
  2826. }
  2827. this.XMA = function (data, n)
  2828. {
  2829. var result = [];
  2830. var offset = 0;
  2831. for (; offset < data.length; ++offset)
  2832. {
  2833. if (this.IsNumber(data[offset])) break;
  2834. }
  2835. var p = parseInt((n - 2) / 2);
  2836. var sum = 0;
  2837. var count = 0, start = 0, end = 0;
  2838. for (var i = offset, j=0; i < data.length; ++i)
  2839. {
  2840. start = i - p - 1;
  2841. end = i + (n - p) - 1;
  2842. for (j = start; j < end; ++j)
  2843. {
  2844. if (j >= 0 && j < data.length)
  2845. {
  2846. if (this.IsNumber(data[j]))
  2847. {
  2848. sum += data[j];
  2849. ++count;
  2850. }
  2851. }
  2852. }
  2853. if (count != 0) result[i] = (sum / count);
  2854. else result[i] = null;
  2855. sum = 0;
  2856. count = 0;
  2857. }
  2858. return result;
  2859. }
  2860. /*
  2861. SMA 移动平均
  2862. 返回移动平均。
  2863. 用法: SMA(X,N,M) X的M日移动平均,M为权重,如Y=(X*M+Y'*(N-M))/N
  2864. */
  2865. this.SMA=function(data,n,m)
  2866. {
  2867. var result = [];
  2868. if (Array.isArray(n))
  2869. {
  2870. for( var i=0;i<n.length;++i)
  2871. {
  2872. var period=n[i];
  2873. if (!this.IsNumber(period)) continue;
  2874. period=parseInt(period);
  2875. if (period<=0) continue;
  2876. if (period>i+1) period=i+1;
  2877. var lastSMA=null;
  2878. var sma=null;
  2879. for(var j=0;j<period;++j)
  2880. {
  2881. var index=i-(period-j-1);
  2882. var item=data[index];
  2883. if (!this.IsNumber(item)) continue;
  2884. if (lastSMA==null)
  2885. {
  2886. lastSMA=item;
  2887. sma=item;
  2888. }
  2889. else
  2890. {
  2891. sma=(m*item+(period-m)*lastSMA)/period;
  2892. lastSMA=sma;
  2893. }
  2894. }
  2895. result[i]=sma;
  2896. }
  2897. }
  2898. else
  2899. {
  2900. var i=n;
  2901. var lastData=null;
  2902. for(;i<data.length; ++i)
  2903. {
  2904. if (data[i]==null || isNaN(data[i])) continue;
  2905. lastData=data[i];
  2906. result[i]=lastData; //第一天的数据
  2907. break;
  2908. }
  2909. for(++i;i<data.length;++i)
  2910. {
  2911. result[i]=(m*data[i]+(n-m)*lastData)/n;
  2912. lastData=result[i];
  2913. }
  2914. }
  2915. return result;
  2916. }
  2917. /*
  2918. 求动态移动平均.
  2919. 用法: DMA(X,A),求X的动态移动平均.
  2920. 算法: 若Y=DMA(X,A)则 Y=A*X+(1-A)*Y',其中Y'表示上一周期Y值,A必须小于1.
  2921. 例如:DMA(CLOSE,VOL/CAPITAL)表示求以换手率作平滑因子的平均价
  2922. */
  2923. this.DMA=function(data,data2)
  2924. {
  2925. var result = [];
  2926. if (data.length<0 || data.length!=data2.length) return result;
  2927. var index=0;
  2928. for(;index<data.length;++index)
  2929. {
  2930. if (data[index]!=null && !isNaN(data[index]) && data2[index]!=null && !isNaN(data2[index]))
  2931. {
  2932. result[index]=data[index];
  2933. break;
  2934. }
  2935. }
  2936. for(index=index+1;index<data.length;++index)
  2937. {
  2938. if (data[index]==null || data2[index]==null)
  2939. result[index]=null;
  2940. else
  2941. {
  2942. if (data[index]<1)
  2943. result[index]=(data2[index]*data[index])+(1-data2[index])*result[index-1];
  2944. else
  2945. result[index]= data[index];
  2946. }
  2947. }
  2948. return result;
  2949. }
  2950. /*
  2951. 返回加权移动平均
  2952. 用法:WMA(X,N):X的N日加权移动平均.
  2953. 算法:Yn=(1*X1+2*X2+...+n*Xn)/(1+2+...+n)
  2954. */
  2955. this.WMA = function (data, dayCount)
  2956. {
  2957. let result = [];
  2958. if (!data || !data.length) return result;
  2959. if (dayCount < 1) dayCount = 1;
  2960. var i = 0;
  2961. for (i = 0; i < data.length && !this.IsNumber(data[i]); ++i)
  2962. {
  2963. result[i] = null;
  2964. }
  2965. var data = data.slice(0);
  2966. for (var days = 0; i < data.length; ++i, ++days)
  2967. {
  2968. if (days < dayCount - 1)
  2969. {
  2970. result[i] = null;
  2971. continue;
  2972. }
  2973. var preValue = data[i - (dayCount - 1)];
  2974. var sum = 0;
  2975. var count = 0;
  2976. for (var j = dayCount - 1; j >= 0; --j)
  2977. {
  2978. var value = data[i - j];
  2979. if (!this.IsNumber(value))
  2980. {
  2981. value = preValue;
  2982. data[i - j] = value;
  2983. }
  2984. else
  2985. preValue = value;
  2986. count += dayCount - j;
  2987. sum += value * (dayCount - j);
  2988. }
  2989. result[i] = sum / count;
  2990. }
  2991. return result;
  2992. }
  2993. /*
  2994. 返回平滑移动平均
  2995. 用法:MEMA(X,N):X的N日平滑移动平均,如Y=(X+Y'*(N-1))/N
  2996. MEMA(X,N)相当于SMA(X,N,1)
  2997. */
  2998. this.MEMA = function (data, dayCount)
  2999. {
  3000. let result = [];
  3001. if (!data || !data.length) return result;
  3002. var i = 0, j = 0;
  3003. for (j = 0; j < data.length && !this.IsNumber(data[j]); ++j)
  3004. {
  3005. result[j] = null;
  3006. }
  3007. i = j;
  3008. if (dayCount < 1 || i + dayCount >= data.length) return result;
  3009. var sum = 0;
  3010. var data = data.slice(0);
  3011. for (; i < j + dayCount; ++i)
  3012. {
  3013. result[i] = null;
  3014. if (!this.IsNumber(data[i]) && i - 1 >= 0)
  3015. data[i] = data[i - 1];
  3016. sum += data[i];
  3017. }
  3018. result[i - 1] = sum / dayCount;
  3019. for (; i < data.length; ++i)
  3020. {
  3021. if (this.IsNumber(result[i - 1]) && this.IsNumber(data[i]))
  3022. result[i] = (data[i] + result[i - 1] * (dayCount - 1)) / dayCount;
  3023. else if (i - 1 > -1 && this.IsNumber(result[i - 1]))
  3024. result[i] = result[i - 1];
  3025. else
  3026. result[i] = null;
  3027. }
  3028. return result;
  3029. }
  3030. /*
  3031. 加权移动平均
  3032. 返回加权移动平均
  3033. 用法:EXPMA(X,M):X的M日加权移动平均
  3034. EXPMA[i]=buffer[i]*para+(1-para)*EXPMA[i-1] para=2/(1+__para)
  3035. */
  3036. this.EXPMA=function(data,dayCount)
  3037. {
  3038. let result=[];
  3039. if (dayCount>=data.length) return result;
  3040. let i=dayCount;
  3041. for(;i<data.length;++i) //获取第1个有效数据
  3042. {
  3043. if (data[i]!=null)
  3044. {
  3045. result[i]=data[i];
  3046. break;
  3047. }
  3048. }
  3049. for (i=i+1; i < data.length; ++i)
  3050. {
  3051. if (result[i-1]!=null && data[i]!=null)
  3052. result[i]=(2*data[i]+(dayCount-1)*result[i-1])/(dayCount+1);
  3053. else if (result[i-1]!=null)
  3054. result[i]=result[i-1];
  3055. }
  3056. return result;
  3057. }
  3058. //加权平滑平均,MEMA[i]=SMA[i]*para+(1-para)*SMA[i-1] para=2/(1+__para)
  3059. this.EXPMEMA=function(data,dayCount)
  3060. {
  3061. var result=[];
  3062. if (dayCount>=data.length) return result;
  3063. var index=0;
  3064. for(;index<data.length;++index)
  3065. {
  3066. if (data[index] && !isNaN(data[index])) break;
  3067. }
  3068. var sum=0;
  3069. for(var i=0; index<data.length && i<dayCount;++i, ++index)
  3070. {
  3071. if (data[index] && !isNaN(data[index]))
  3072. sum+=data[index];
  3073. else
  3074. sum+=data[index-1];
  3075. }
  3076. result[index-1]=sum/dayCount;
  3077. for(;index<data.length;++index)
  3078. {
  3079. if(result[index-1]!=null && data[index]!=null)
  3080. result[index]=(2*data[index]+(dayCount-1)*result[index-1])/(dayCount+1);
  3081. else if(result[index-1]!=null)
  3082. result[index] = result[index-1];
  3083. }
  3084. return result;
  3085. }
  3086. /*
  3087. 向前累加到指定值到现在的周期数.
  3088. 用法:SUMBARS(X,A):将X向前累加直到大于等于A,返回这个区间的周期数
  3089. 例如:SUMBARS(VOL,CAPITAL)求完全换手到现在的周期数
  3090. */
  3091. this.SUMBARS = function (data, data2)
  3092. {
  3093. var result = [];
  3094. if (!data || !data.length || !data2 || !data2.length) return result;
  3095. var start = 0, i = 0, j = 0;
  3096. for (; start < data.length && !this.IsNumber(data[start]); ++start)
  3097. {
  3098. result[start] = null;
  3099. }
  3100. var total = 0;
  3101. for (i = data.length - 1; i >= start; --i)
  3102. {
  3103. for (j = i, total = 0; j >= start && total < data2[i]; --j)
  3104. total += data[j];
  3105. if (j < start) result[i] = null;
  3106. else result[i] = i - j;
  3107. }
  3108. for (i = start + 1; i < data.length; ++i)
  3109. {
  3110. if (result[i] == null)
  3111. result[i] = result[i - 1];
  3112. }
  3113. return result;
  3114. }
  3115. /*
  3116. 求相反数.
  3117. 用法:REVERSE(X)返回-X.
  3118. 例如:REVERSE(CLOSE)返回-CLOSE
  3119. */
  3120. this.REVERSE = function (data)
  3121. {
  3122. if (this.IsNumber(data))
  3123. {
  3124. return 0-data;
  3125. }
  3126. var result = [];
  3127. var i = 0;
  3128. for (; i < data.length && !this.IsNumber(data[i]); ++i)
  3129. {
  3130. result[i] = null;
  3131. }
  3132. for (; i < data.length; ++i)
  3133. {
  3134. if (!this.IsNumber(data[i]))
  3135. result[i] = null;
  3136. else
  3137. result[i] = 0 - data[i];
  3138. }
  3139. return result;
  3140. }
  3141. this.COUNT=function(data,n)
  3142. {
  3143. if (Array.isArray(n))
  3144. {
  3145. var start=null;
  3146. var dataCount=data.length;
  3147. for(var i=0;i<dataCount;++i)
  3148. {
  3149. if (this.IsNumber(data[i]))
  3150. {
  3151. start=i;
  3152. break;
  3153. }
  3154. }
  3155. if (start==null) return [];
  3156. var result=[];
  3157. var count=0;
  3158. for(var i=0;i<n.length;++i)
  3159. {
  3160. var period=n[i];
  3161. if (period==0)
  3162. {
  3163. result[i]=0;
  3164. continue;
  3165. }
  3166. if (!IFrameSplitOperator.IsNumber(period) ) period=i+1; //无效周期 第一个有效值开始.
  3167. else if (period<0) period=i+1;
  3168. count=0;
  3169. for(var j=i, k=0 ;j>=0 && k<period ;--j,++k) //当前往前period天 统计
  3170. {
  3171. if (data[j]) ++count;
  3172. }
  3173. result[i]=count;
  3174. }
  3175. return result;
  3176. }
  3177. else
  3178. {
  3179. var period=n;
  3180. var dataCount=data.length;
  3181. var period=period<1?dataCount:period;
  3182. var i=0,j=0;
  3183. for(;i<dataCount;++i) // 取第1个有效数据
  3184. {
  3185. if (this.IsNumber(data[i])) break;
  3186. }
  3187. var result=[];
  3188. var days=0;
  3189. for(;i<dataCount && j<period; ++i,++j)
  3190. {
  3191. days=data[i]?days+1:days;
  3192. result[i]=days;
  3193. }
  3194. for(;i<dataCount;++i)
  3195. {
  3196. if (data[i-period] && days) days--;
  3197. days=data[i] ? days+1 : days;
  3198. result[i]=days;
  3199. }
  3200. return result;
  3201. }
  3202. }
  3203. /*
  3204. HHV 最高值
  3205. 求最高值。
  3206. 用法: HHV(X,N) 求N周期内X最高值,N=0则从第一个有效值开始。
  3207. 例如: HHV(HIGH,30) 表示求30日最高价。
  3208. */
  3209. this.HHV=function(data,n)
  3210. {
  3211. let result = [];
  3212. if (Array.isArray(n))
  3213. {
  3214. var max = null;
  3215. for (var i = 0, j = 0; i < data.length; ++i)
  3216. {
  3217. result[i] = null;
  3218. if (i >= n.length) continue;
  3219. max = null;
  3220. var count = n[i];
  3221. if (count > 0 && count <= i)
  3222. {
  3223. for (j = i - count; j <= i; ++j)
  3224. {
  3225. if (max == null || max < data[j]) max = data[j];
  3226. }
  3227. }
  3228. else
  3229. {
  3230. count = i;
  3231. for (j = 0; j <= i; ++j)
  3232. {
  3233. if (max == null || max < data[j]) max = data[j];
  3234. }
  3235. }
  3236. result[i] = max;
  3237. }
  3238. }
  3239. else
  3240. {
  3241. if (!IFrameSplitOperator.IsNonEmptyArray(data)) return result;
  3242. n=parseInt(n);
  3243. if (n<=0) n=data.length;
  3244. else if (n>data.length) n=data.length;
  3245. var nStart=this.GetFirstVaildIndex(data);
  3246. if (nStart>=data.length) return result;
  3247. var nMax = nStart;
  3248. if (nMax < data.length) result[nMax] = data[nMax];
  3249. for (var i = nMax + 1, j = 2; i < data.length && j < n; ++i, ++j)
  3250. {
  3251. if (data[i] >= data[nMax]) nMax = i;
  3252. result[i] = data[nMax];
  3253. }
  3254. for (; i < data.length; ++i)
  3255. {
  3256. if (i - nMax < n)
  3257. {
  3258. nMax = data[i] < data[nMax] ? nMax : i;
  3259. }
  3260. else
  3261. {
  3262. for (j = nMax = (i - n + 1); j <= i; ++j)
  3263. {
  3264. nMax = data[j] < data[nMax] ? nMax : j;
  3265. }
  3266. }
  3267. result[i] = data[nMax];
  3268. }
  3269. }
  3270. return result;
  3271. }
  3272. /*
  3273. HV(X,N):求X在N个周期内(不包含当前k线)的最高值。
  3274. 注:
  3275. 1、若N为0则从第一个有效值开始算起(不包含当前K线);
  3276. 2、当N为有效值,但当前的k线数不足N根,按照实际的根数计算,第一根k线返回空值;
  3277. 3、N为空值时,返回空值。
  3278. 4、N可以是变量。
  3279. 例1:
  3280. HH:HV(H,10);//求前10根k线的最高点。
  3281. 例2:
  3282. N:=BARSLAST(DATE<>REF(DATE,1))+1;
  3283. ZH:VALUEWHEN(DATE<>REF(DATE,1),HV(H,N));//在分钟周期上,求昨天最高价。
  3284. 例3:
  3285. HV(H,5) 和 REF(HHV(H,5),1) 的结果是一样的,用HV编写更加方便。
  3286. */
  3287. this.HV=function(data,n)
  3288. {
  3289. var result=this.HHV(data,n);
  3290. return this.REF(result,1);
  3291. }
  3292. /*
  3293. LLV 最低值
  3294. 求最低值。
  3295. 用法: LLV(X,N) 求N周期内X最低值,N=0则从第一个有效值开始。
  3296. 例如: LLV(LOW,0) 表示求历史最低价。
  3297. */
  3298. this.LLV=function(data,n)
  3299. {
  3300. var result = [];
  3301. if (Array.isArray(n))
  3302. {
  3303. for (var i = 0; i < data.length; ++i)
  3304. {
  3305. result[i] = null;
  3306. if (i >= n.length) continue;
  3307. var min = null;
  3308. var count = n[i];
  3309. if (count > 0 && count <= i)
  3310. {
  3311. for (var j = i - count; j <= i; ++j)
  3312. {
  3313. if (min == null || min > data[j]) min = data[j];
  3314. }
  3315. }
  3316. else
  3317. {
  3318. count = i;
  3319. for (var j = 0; j <= i; ++j)
  3320. {
  3321. if (min == null || min > data[j]) min = data[j];
  3322. }
  3323. }
  3324. result[i] = min;
  3325. }
  3326. }
  3327. else
  3328. {
  3329. if (!IFrameSplitOperator.IsNonEmptyArray(data)) return result;
  3330. n=parseInt(n);
  3331. if (n<=0) n=data.length;
  3332. else if (n>data.length) n=data.length;
  3333. var nStart=this.GetFirstVaildIndex(data);
  3334. if (nStart>=data.length) return result;
  3335. var nMin=nStart;
  3336. if (nMin<data.length) result[nMin]=data[nMin];
  3337. for(var i=nMin+1,j=2;i<data.length && j<n;++i,++j)
  3338. {
  3339. if (data[i]<=data[nMin]) nMin=i;
  3340. result[i]=data[nMin];
  3341. }
  3342. for(;i<data.length;++i)
  3343. {
  3344. if (i-nMin<n)
  3345. {
  3346. nMin=data[i]>data[nMin]?nMin:i;
  3347. }
  3348. else
  3349. {
  3350. for(j=nMin=(i-n+1);j<=i;++j)
  3351. {
  3352. nMin=data[j]>data[nMin]?nMin:j;
  3353. }
  3354. }
  3355. result[i]=data[nMin];
  3356. }
  3357. }
  3358. return result;
  3359. }
  3360. /*
  3361. LV(X,N) 求X在N个周期内的最小值(不包含当前k线)
  3362. 注:
  3363. 1、若N为0则从第一个有效值开始算起;
  3364. 2、当N为有效值,但当前的k线数不足N根,按照实际的根数计算;
  3365. 3、N为空值时,返回空值。
  3366. 4、N可以是变量。
  3367. 例1:
  3368. LL:LV(L,10);//求前面10根k线的最低点。(不包含当前k线)
  3369. 例2:
  3370. N:=BARSLAST(DATE<>REF(DATE,1))+1;//分钟周期,日内k线根数
  3371. ZL:VALUEWHEN(DATE<>REF(DATE,1),LV(L,N));//在分钟周期上,求昨天最低价。
  3372. 例3:
  3373. LV(L,5) 和 REF(LLV(L,5),1) 的结果是一样的,用LV编写更加方便。
  3374. */
  3375. this.LV=function(data,n)
  3376. {
  3377. var result=this.LLV(data,n);
  3378. return this.REF(result,1);
  3379. }
  3380. this.STD=function(data,n)
  3381. {
  3382. var result=[];
  3383. var nStart=this.GetFirstVaildIndex(data);
  3384. if (!IFrameSplitOperator.IsNumber(n)) return result;
  3385. if(nStart+n>data.length || n<1) return result;
  3386. var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
  3387. for(i+=n-1;i<data.length;++i)
  3388. {
  3389. dTotal = 0;
  3390. if(bFirst)
  3391. {
  3392. bFirst = false;
  3393. for(j=i-n+1;j<=i;++j)
  3394. {
  3395. dAvg += data[j];
  3396. }
  3397. dAvg /= n;
  3398. }
  3399. else
  3400. {
  3401. dAvg += (data[i]-data[i-n])/n;
  3402. }
  3403. for(j=i-n+1;j<=i;++j)
  3404. {
  3405. dTotal += (data[j]-dAvg)*(data[j]-dAvg);
  3406. }
  3407. result[i] = Math.sqrt(dTotal/(n-1));
  3408. }
  3409. return result;
  3410. }
  3411. //STDDEV(X,N) 返回标准偏差
  3412. //将标准差除以样本大小N的平方根即可得出标准误差。标准误差 = σ/sqrt(n)
  3413. this.STDDEV=function(data,n)
  3414. {
  3415. var result=[];
  3416. if (!Array.isArray(data)) return result;
  3417. var nStart=this.GetFirstVaildIndex(data);
  3418. if (!IFrameSplitOperator.IsNumber(n)) return result;
  3419. if(nStart+n>data.length || n<1) return result;
  3420. var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
  3421. for(i+=n-1;i<data.length;++i)
  3422. {
  3423. dTotal = 0;
  3424. if(bFirst)
  3425. {
  3426. bFirst = false;
  3427. for(j=i-n+1;j<=i;++j)
  3428. {
  3429. dAvg += data[j];
  3430. }
  3431. dAvg /= n;
  3432. }
  3433. else
  3434. {
  3435. dAvg += (data[i]-data[i-n])/n;
  3436. }
  3437. for(j=i-n+1;j<=i;++j)
  3438. {
  3439. dTotal += (data[j]-dAvg)*(data[j]-dAvg);
  3440. }
  3441. result[i] = Math.sqrt(dTotal/(n-1))/Math.sqrt(n);
  3442. }
  3443. return result;
  3444. }
  3445. //平均绝对方差
  3446. this.AVEDEV=function(data,n)
  3447. {
  3448. var result=[];
  3449. var total=0;
  3450. var averageData=[]; //平均值
  3451. for(var i=n-1;i<data.length;++i)
  3452. {
  3453. total=0;
  3454. for(var j=0;j<n;++j)
  3455. {
  3456. total+=data[i-j];
  3457. }
  3458. averageData[i]=total/n;
  3459. }
  3460. for(var i=n-1;i<data.length;++i)
  3461. {
  3462. total=0;
  3463. for(var j=0;j<n;++j)
  3464. {
  3465. total+=Math.abs(data[i-j]-averageData[i]);
  3466. }
  3467. result[i]=total/n;
  3468. }
  3469. return result;
  3470. }
  3471. //上穿
  3472. this.CROSS=function(data,data2)
  3473. {
  3474. var result = [];
  3475. if (Array.isArray(data) && Array.isArray(data2))
  3476. {
  3477. if (data.length != data2.length) return result = [];
  3478. var index = 0;
  3479. for (; index < data.length; ++index)
  3480. {
  3481. if (this.IsNumber(data[index]) && this.IsNumber(data2[index]))
  3482. break;
  3483. }
  3484. for (++index; index < data.length; ++index)
  3485. {
  3486. result[index] = (data[index] > data2[index] && data[index - 1] < data2[index - 1]) ? 1 : 0;
  3487. }
  3488. }
  3489. else if (Array.isArray(data) && typeof (data2) == 'number')
  3490. {
  3491. var index = 0;
  3492. for (; index < data.length; ++index)
  3493. {
  3494. if (this.IsNumber(data[index])) break;
  3495. }
  3496. for (++index; index < data.length; ++index)
  3497. {
  3498. result[index] = (data[index] > data2 && data[index - 1] < data2) ? 1 : 0;
  3499. }
  3500. }
  3501. else if (typeof (data) == 'number' && Array.isArray(data2))
  3502. {
  3503. var index = 0;
  3504. for (; index < data2.length; ++index)
  3505. {
  3506. if (this.IsNumber(data2[index])) break;
  3507. }
  3508. for (++index; index < data2.length; ++index)
  3509. {
  3510. result[index] = (data2[index] < data && data2[index - 1] > data) ? 1 : 0;
  3511. }
  3512. }
  3513. return result;
  3514. }
  3515. /*
  3516. CROSSDOWN(A,B):表示当A从上方向下穿B,成立返回1(Yes),否则返回0(No)
  3517. 注:1、CROSSDOWN(A,B)等同于CROSS(B,A),CROSSDOWN(A,B)编写更利于理解
  3518. 例1:
  3519. MA5:=MA(C,5);
  3520. MA10:=MA(C,10);
  3521. CROSSDOWN(MA5,MA10)//MA5下穿MA10
  3522. */
  3523. this.CROSSDOWN=function(data,data2)
  3524. {
  3525. return this.CROSS(data2,data);
  3526. }
  3527. //累乘
  3528. this.MULAR=function(data,n)
  3529. {
  3530. var result=[];
  3531. if(data.length<n) return result;
  3532. var index=n;
  3533. for(;index<data.length;++index)
  3534. {
  3535. if (data[index]!=null && !isNaN(data[index]))
  3536. {
  3537. result[index]=data[index];
  3538. break;
  3539. }
  3540. }
  3541. for(++index;index<data.length;++index)
  3542. {
  3543. result[index]=result[index-1]*data[index];
  3544. }
  3545. return result;
  3546. }
  3547. this.SUM=function(data,n)
  3548. {
  3549. var result=[];
  3550. if (!Array.isArray(n))
  3551. {
  3552. if (n==0)
  3553. {
  3554. var start=-1;
  3555. for(var i=0; i<data.length; ++i) //取第1个有效数
  3556. {
  3557. if (IFrameSplitOperator.IsNumber(data[i]))
  3558. {
  3559. start=i;
  3560. break;
  3561. }
  3562. }
  3563. if (start<0) return result;
  3564. result[start]=data[start];
  3565. for (var i=start+1; i<data.length; ++i)
  3566. {
  3567. result[i] = result[i-1]+data[i];
  3568. }
  3569. }
  3570. else
  3571. {
  3572. result[0]=data[0];
  3573. for(var i=1;i<n && i<data.length;++i) //前面小于N周期的累加
  3574. {
  3575. result[i] = result[i-1]+data[i];
  3576. }
  3577. for(var i=n-1,j=0;i<data.length;++i,++j)
  3578. {
  3579. for(var k=0;k<n;++k)
  3580. {
  3581. if (k==0) result[i]=data[k+j];
  3582. else result[i]+=data[k+j];
  3583. }
  3584. }
  3585. }
  3586. }
  3587. else
  3588. {
  3589. for(var i=0;i<data.length;++i)
  3590. {
  3591. result[i]=null;
  3592. var totalCount=n[i];
  3593. if (!(totalCount>0)) continue;
  3594. for(var j=i, k=0 ;j>=0 && k<totalCount ;--j,++k)
  3595. {
  3596. if (k==0) result[i]=data[j];
  3597. else result[i]+=data[j];
  3598. }
  3599. }
  3600. }
  3601. return result;
  3602. }
  3603. /*
  3604. BARSCOUNT 有效数据周期数
  3605. 求总的周期数。
  3606. 用法: BARSCOUNT(X) 第一个有效数据到当前的天数。
  3607. 例如: BARSCOUNT(CLOSE) 对于日线数据取得上市以来总交易日数,对于分笔成交取得当日成交笔数,对于1分钟线取得当日交易分钟数。
  3608. */
  3609. this.BARSCOUNT=function(data)
  3610. {
  3611. let result=[];
  3612. let days=null;
  3613. for(let i in data)
  3614. {
  3615. result[i]=0;
  3616. if (days==null)
  3617. {
  3618. if (!this.IsNumber(data[i])) contnue;
  3619. days=0;
  3620. }
  3621. result[i]=days;
  3622. ++days;
  3623. }
  3624. return result;
  3625. }
  3626. //DEVSQ 数据偏差平方和
  3627. //DEVSQ(X,N)  返回数据偏差平方和。
  3628. this.DEVSQ=function(data,n)
  3629. {
  3630. if (this.IsNumber(data) && this.IsNumber(n))
  3631. return 0;
  3632. var result=[];
  3633. if (Array.isArray(data))
  3634. {
  3635. var num = null;
  3636. if (Array.isArray(n)) //取最后一个有效数
  3637. {
  3638. for(var i=n.length-1;i>=0;--i)
  3639. {
  3640. if (this.IsNumber(n[i]))
  3641. {
  3642. num = parseInt(n[i]);
  3643. break;
  3644. }
  3645. }
  3646. }
  3647. else
  3648. {
  3649. num = parseInt(n);
  3650. }
  3651. if (!this.IsNumber(num)) return result;
  3652. var datanum = data.length;
  3653. var i = 0, j = 0, k = 0;
  3654. var E = 0, DEV = 0;
  3655. for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
  3656. {
  3657. result[i] = null;
  3658. }
  3659. if (num < 1 || i+num>datanum) return result;
  3660. for(E=0; i < datanum && j < num; ++i,++j)
  3661. E += data[i]/num;
  3662. if (j == num)
  3663. {
  3664. DEV = 0;
  3665. for(i--; k < num; k++)
  3666. DEV += (data[i-k]-E) * (data[i-k]-E);
  3667. result[i] = DEV;
  3668. i++;
  3669. }
  3670. for(; i < datanum; ++i)
  3671. {
  3672. E += (data[i] - data[i-num]) / num;
  3673. for(DEV=0, k = 0; k < num; ++k)
  3674. DEV += (data[i-k]-E) * (data[i-k]-E);
  3675. result[i] = DEV;
  3676. }
  3677. }
  3678. return result;
  3679. }
  3680. //NOT 取反
  3681. //求逻辑非。
  3682. //用法: NOT(X) 返回非X,即当X=0时返回1,否则返回0。
  3683. //例如: NOT(ISUP) 表示平盘或收阴。
  3684. this.NOT=function(data)
  3685. {
  3686. let isNumber=typeof(data)=='number';
  3687. if (isNumber) return data? 0:1;
  3688. let result=[];
  3689. for(let i in data)
  3690. {
  3691. result[i]=null;
  3692. if (this.IsNumber(data[i])) result[i]=data[i]?0:1;
  3693. }
  3694. return result;
  3695. }
  3696. //FORCAST 线性回归预测值
  3697. //FORCAST(X,N)  返回线性回归预测值。
  3698. this.FORCAST=function(data,n)
  3699. {
  3700. var result=[];
  3701. if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
  3702. var num = n;
  3703. var datanum = data.length;
  3704. if (num < 1 || num >= datanum)
  3705. return result;
  3706. var Ex = 0, Ey = 0, Sxy = 0, Sxx = 0, Const, Slope;
  3707. var i, j,x;
  3708. for(j = 0; j < datanum && !this.IsNumber(data[j]); ++j)
  3709. {
  3710. result[j] = null;
  3711. }
  3712. for(i = j+num-1; i < datanum; ++i)
  3713. {
  3714. Ex = Ey = Sxy = Sxx = 0;
  3715. for (j = 0, x = num; j < num && j <= i; ++j,--x)
  3716. {
  3717. Ex +=x;
  3718. Ey += data[i - j];
  3719. }
  3720. Ex /= num;
  3721. Ey /= num;
  3722. for (j = 0, x = num; j < num && j <= i; ++j, --x)
  3723. {
  3724. Sxy += (x-Ex)*(data[i-j]-Ey);
  3725. Sxx += (x-Ex)*(x-Ex);
  3726. }
  3727. Slope = Sxy / Sxx;
  3728. Const = Ey - Ex*Slope;
  3729. result[i] = Slope * num + Const;
  3730. }
  3731. return result;
  3732. }
  3733. //SLOPE 线性回归斜率
  3734. //SLOPE(X,N)  返回线性回归斜率。
  3735. this.SLOPE=function(data,n)
  3736. {
  3737. let result=[];
  3738. if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
  3739. if (n<1 || !data.length) return result;
  3740. if (n>=data.length) return result;
  3741. let start=0;
  3742. for(let i=0;i<data.length;++i,++start)
  3743. {
  3744. result[i]=null;
  3745. if (this.IsNumber(data[i])) break;
  3746. }
  3747. let x,y,xy,xx;
  3748. for(let i=start+n-1;i<data.length;++i)
  3749. {
  3750. result[i]=null;
  3751. x=y=xy=xx=0;
  3752. for(var j=0;j<n && j<=i; ++j)
  3753. {
  3754. x+=(i-j); //数据索引相加
  3755. y+=data[i-j]; //数据相加
  3756. }
  3757. x=x/n; y=y/n;
  3758. for(j=0;j<n && j<=i; ++j)
  3759. {
  3760. xy+=(i-j-x)*(data[i-j]-y);
  3761. xx+=(i-j-x)*(i-j-x);
  3762. }
  3763. if (xx) result[i]= xy/xx;
  3764. else if (i) result[i]=result[i-1];
  3765. }
  3766. return result;
  3767. }
  3768. //STDP 总体标准差
  3769. //STDP(X,N)  返回总体标准差。
  3770. this.STDP=function(data,n)
  3771. {
  3772. var result=[];
  3773. var nStart=this.GetFirstVaildIndex(data);
  3774. if (!IFrameSplitOperator.IsNumber(n)) return result;
  3775. if(nStart+n>data.length || n<1) return result;
  3776. var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
  3777. for(i+=n-1;i<data.length;++i)
  3778. {
  3779. dTotal = 0;
  3780. if(bFirst)
  3781. {
  3782. bFirst = false;
  3783. for(j=i-n+1;j<=i;++j)
  3784. {
  3785. dAvg += data[j];
  3786. }
  3787. dAvg /= n;
  3788. }
  3789. else
  3790. {
  3791. dAvg += (data[i]-data[i-n])/n;
  3792. }
  3793. for(j=i-n+1;j<=i;++j)
  3794. {
  3795. dTotal += (data[j]-dAvg)*(data[j]-dAvg);
  3796. }
  3797. result[i] = Math.sqrt(dTotal/n);
  3798. }
  3799. return result;
  3800. }
  3801. //VAR 估算样本方差
  3802. //VAR(X,N)  返回估算样本方差。
  3803. this.VAR=function(data,n)
  3804. {
  3805. if (this.IsNumber(data) && this.IsNumber(n)) return 0;
  3806. var result=[];
  3807. if (Array.isArray(data) && this.IsNumber(n))
  3808. {
  3809. var num = parseInt(n);
  3810. var datanum = data.length;
  3811. if (num <= 0 || num >= datanum) return result;
  3812. var i, j;
  3813. for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
  3814. {
  3815. result[i] = null;
  3816. }
  3817. var SigmaPowerX, SigmaX;
  3818. for (j = 0, i = i+num-1; i < datanum; ++i)
  3819. {
  3820. SigmaPowerX = SigmaX = 0;
  3821. for(j=0; j < num && j <= i; ++j)
  3822. {
  3823. SigmaPowerX += data[i-j] * data[i-j];
  3824. SigmaX += data[i-j];
  3825. }
  3826. result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1);
  3827. }
  3828. }
  3829. else if (Array.isArray(data) && Array.isArray(n))
  3830. {
  3831. var start=this.GetFirstVaildIndex(data);
  3832. for(var i=start; i<data.length; ++i)
  3833. {
  3834. var SigmaPowerX = SigmaX = 0;
  3835. if (!this.IsNumber(n[i])) continue;
  3836. var num=parseInt(n[i]);
  3837. if (num <= 0 || i-(num-1)<0) continue;
  3838. for (var j = 0; j<num; ++j)
  3839. {
  3840. SigmaPowerX += data[i-j] * data[i-j];
  3841. SigmaX += data[i-j];
  3842. }
  3843. result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1);
  3844. }
  3845. }
  3846. return result;
  3847. }
  3848. //VARP 总体样本方差
  3849. //VARP(X,N)  返回总体样本方差 。
  3850. this.VARP=function(data,n)
  3851. {
  3852. var result=[];
  3853. if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
  3854. var num = n;
  3855. var datanum = data.length;
  3856. if (num < 1 || num >= datanum)
  3857. return result;
  3858. var i = 0, j = 0;
  3859. for (i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
  3860. {
  3861. result[i] = null;
  3862. }
  3863. var SigmaPowerX = 0, SigmaX = 0;
  3864. for (; i < datanum && j < num; ++i, ++j)
  3865. {
  3866. SigmaPowerX += data[i] * data[i];
  3867. SigmaX += data[i];
  3868. }
  3869. if (j == num)
  3870. result[i-1] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num);
  3871. for(; i < datanum; ++i)
  3872. {
  3873. SigmaPowerX += data[i]*data[i] - data[i-num]*data[i-num];
  3874. SigmaX += data[i] - data[i-num];
  3875. result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num);
  3876. }
  3877. return result;
  3878. }
  3879. //RANGE(A,B,C)表示A>B AND A<C;
  3880. this.RANGE=function(data,range,range2)
  3881. {
  3882. let isNumber=typeof(data)=='number';
  3883. let isNumber2=typeof(range)=='number';
  3884. let isNumber3=typeof(range2)=='number';
  3885. if (isNumber && isNumber2 && isNumber3)
  3886. {
  3887. if (data>Math.min(range,range2) && data<Math.max(range,range2)) return 1;
  3888. else return 0;
  3889. }
  3890. let result=[];
  3891. let value, rangeValue,rangValue2;
  3892. for(let i=0; i<data.length; ++i)
  3893. {
  3894. result[i]=null;
  3895. value=data[i];
  3896. if (!this.IsNumber(value)) continue;
  3897. if (!isNumber2)
  3898. {
  3899. if (i>=range.length) continue;
  3900. rangeValue=range[i];
  3901. }
  3902. else
  3903. {
  3904. rangeValue=range;
  3905. }
  3906. if (!this.IsNumber(rangeValue)) continue;
  3907. if (!isNumber3)
  3908. {
  3909. if (i>=range2.length) continue;
  3910. rangeValue2=range2[i];
  3911. }
  3912. else
  3913. {
  3914. rangeValue2=range2;
  3915. }
  3916. if (!this.IsNumber(rangeValue2)) continue;
  3917. result[i]= (value>Math.min(rangeValue,rangeValue2) && value<Math.max(rangeValue,rangeValue2)) ? 1:0;
  3918. }
  3919. return result;
  3920. }
  3921. this.EXIST=function(data,n)
  3922. {
  3923. n=parseInt(n);
  3924. if (typeof(data)=='number') return 0;
  3925. var latestID; //最新满足条件的数据索引
  3926. var result=[];
  3927. var value;
  3928. for(let i=0;i<data.length;++i)
  3929. {
  3930. result[i]=null;
  3931. value=data[i];
  3932. if (this.IsNumber(value) && value>0) latestID==i;
  3933. if (i-latestID<n) result[i]=1;
  3934. else result[i]=0;
  3935. }
  3936. return result;
  3937. }
  3938. //用法:BETWEEN(A,B,C)表示A处于B和C之间时返回1,否则返回0
  3939. //例如:BETWEEN(CLOSE,MA(CLOSE,20),MA(CLOSE,10))表示收盘价介于10日均线和20日均线之间
  3940. this.BETWEEN=function(condition, data, data2)
  3941. {
  3942. var result=[];
  3943. var isNumber=typeof(condition)=='number';
  3944. var isNumber2=typeof(data)=='number';
  3945. var isNumber3=typeof(data2)=='number';
  3946. if (isNumber && isNumber2 && isNumber3) //单数值
  3947. {
  3948. return (condition>=data && condition<=data2) ? 1 : 0;
  3949. }
  3950. for(var i in condition)
  3951. {
  3952. result[i]=0;
  3953. var item=condition[i];
  3954. var left=null, right=null;
  3955. if (isNumber2) left=data;
  3956. else if (i<data.length-1) left=data[i];
  3957. if (isNumber3) right=data2;
  3958. else if (i<data2.length-1) right=data2[i];
  3959. if (left==null || right==null) continue;
  3960. if (left>right)
  3961. {
  3962. if (item>=right && item<=left)
  3963. result[i]=1;
  3964. }
  3965. else
  3966. {
  3967. if (item<=right && item>=left)
  3968. result[i]=1;
  3969. }
  3970. }
  3971. return result;
  3972. }
  3973. /*
  3974. 过滤连续出现的信号.
  3975. 用法:TFILTER(买入条件,卖出条件,N);过滤掉买入(卖出)信号发出后,下一个反向信号发出前的所有买入(卖出)信号.
  3976. N=1表示仅对买入信号过滤;
  3977. N=2表示仅对卖出信号过滤;
  3978. N=0表示对买入和卖出信号都过滤,返回1,2表示买入或卖出条件成立;
  3979. 同一K线上只能有一个信号;
  3980. 例如:
  3981. ENTERLONG:TFILTER(买入,卖出,1);
  3982. EXITLONG:TFILTER(买入,卖出,2);
  3983. TFILTER(D,K,1) 等价于 D AND COUNT(D, BARSLAST(K)) == 1
  3984. TFILTER(D,K,2) 等价于 K AND COUNT(K, BARSLAST(D)) == 1
  3985. TFILTER(D,K,0) 需要做个判断,如果满足 D AND COUNT(D, BARSLAST(K)) == 1 则返回1,如果满足 K AND COUNT(K, BARSLAST(D)) == 1 则返回2
  3986. */
  3987. this.TFILTER=function(data,data2,n)
  3988. {
  3989. if (!this.IsNumber(n)) return [];
  3990. if (n==1)
  3991. {
  3992. return this.And(data,this.EQ(this.COUNT(data,this.BARSLAST(data2)),1));
  3993. }
  3994. else if (n==2)
  3995. {
  3996. return this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
  3997. }
  3998. else if (n==0)
  3999. {
  4000. var result=this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
  4001. var value=this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
  4002. for(var i=0; i<result.length; ++i)
  4003. {
  4004. var item=value[i];
  4005. if (item>0) result[i]=2;
  4006. }
  4007. return result;
  4008. }
  4009. return [];
  4010. }
  4011. /*
  4012. 过滤连续出现的信号.
  4013. 用法:FILTER(X,N):X满足条件后,将其后N周期内的数据置为0,N为常量.
  4014. 例如:
  4015. FILTER(CLOSE>OPEN,5)查找阳线,5天内再次出现的阳线不被记录在内
  4016. */
  4017. this.FILTER = function (data, n)
  4018. {
  4019. var result = [];
  4020. for (let i = 0, j = 0; i < data.length; ++i)
  4021. {
  4022. if (data[i])
  4023. {
  4024. result[i] = 1;
  4025. for (j = 0; j < n && j + i + 1 < data.length; ++j)
  4026. {
  4027. result[j + i + 1] = 0;
  4028. }
  4029. i += n;
  4030. }
  4031. else
  4032. {
  4033. result[i] = 0;
  4034. }
  4035. }
  4036. return result;
  4037. }
  4038. //反向过滤连续出现的信号.
  4039. //用法:FILTERX(X,N):X满足条件后,将其前N周期内的数据置为0,N为常量.
  4040. //例如:FILTERX(CLOSE>OPEN,5)查找阳线,前5天内出现过的阳线不被记录在内
  4041. this.FILTERX=function(data, n, node)
  4042. {
  4043. var result=[];
  4044. if (IFrameSplitOperator.IsNumber(n))
  4045. {
  4046. for(var i=data.length-1, j=0; i>=0; --i)
  4047. {
  4048. if (data[i])
  4049. {
  4050. result[i]=1;
  4051. for(j=0;j<n && i-j-1>=0;++j)
  4052. {
  4053. result[i-j-1]=0;
  4054. }
  4055. i-=n;
  4056. }
  4057. else
  4058. {
  4059. result[i]=0;
  4060. }
  4061. }
  4062. }
  4063. else if (Array.isArray(n))
  4064. {
  4065. for(var i=data.length-1, j=0; i>=0; --i)
  4066. {
  4067. if (data[i])
  4068. {
  4069. result[i]=1;
  4070. if (!IFrameSplitOperator.IsNumber(n[i])) continue;
  4071. var period=parseInt(n[i]);
  4072. if (period<=0) continue;
  4073. for(j=0;j<period && i-j-1>=0;++j)
  4074. {
  4075. result[i-j-1]=0;
  4076. }
  4077. i-=period;
  4078. }
  4079. else
  4080. {
  4081. result[i]=0;
  4082. }
  4083. }
  4084. }
  4085. return result;
  4086. }
  4087. this.BARSLAST=function(data)
  4088. {
  4089. var result=[];
  4090. if (!data) return result;
  4091. let day=null;
  4092. for(let i=0;i<data.length;++i)
  4093. {
  4094. result[i]=null;
  4095. if (data[i]>0) day=0;
  4096. else if (day!=null) ++day;
  4097. if (day!=null) result[i]=day;
  4098. }
  4099. return result;
  4100. }
  4101. /*
  4102. N周期内第一个条件成立到当前的周期数.
  4103. 用法:
  4104. BARSSINCEN(X,N):N周期内第一次X不为0到现在的天数,N为常量
  4105. 例如:
  4106. BARSSINCEN(HIGH>10,10)表示10个周期内股价超过10元时到当前的周期数
  4107. */
  4108. this.BARSSINCEN = function (data, n)
  4109. {
  4110. var result=[];
  4111. if (this.IsNumber(n) && Array.isArray(data))
  4112. {
  4113. var nPeriod=n;
  4114. if (nPeriod<1) nPeriod=data.length;
  4115. var i=this.GetFirstVaildIndex(data);
  4116. if (i>=data.length) return result;
  4117. var j=0;
  4118. if (i <= nPeriod - 1) j = nPeriod - 1;
  4119. else j = i;
  4120. result[j] = j - i;
  4121. for (; j < data.length; ++j)
  4122. {
  4123. if (this.IsNumber(result[j - 1]))
  4124. {
  4125. if (result[j - 1] + 1 < nPeriod)
  4126. {
  4127. result[j] = result[j - 1] + 1;
  4128. }
  4129. else
  4130. {
  4131. for (var k = j - nPeriod+1; k <= j; ++k)
  4132. {
  4133. if (!(Math.abs(data[k]) < 0.000001))
  4134. {
  4135. result[j] = j - k;
  4136. break;
  4137. }
  4138. }
  4139. }
  4140. }
  4141. else
  4142. {
  4143. if (!(Math.abs(data[j]) < 0.000001))
  4144. result[j] = 0;
  4145. }
  4146. }
  4147. }
  4148. return result;
  4149. }
  4150. /*
  4151. 第一个条件成立到当前的周期数.
  4152. 用法:
  4153. BARSSINCE(X):第一次X不为0到现在的天数
  4154. 例如:
  4155. BARSSINCE(HIGH>10)表示股价超过10元时到当前的周期数
  4156. */
  4157. this.BARSSINCE = function (data)
  4158. {
  4159. var result = [];
  4160. var day = null;
  4161. for (let i = 0; i < data.length; ++i)
  4162. {
  4163. result[i] = null;
  4164. if (day == null)
  4165. {
  4166. if (data[i]) day = 0;
  4167. }
  4168. else
  4169. {
  4170. ++day;
  4171. }
  4172. if (day) result[i] = day;
  4173. }
  4174. return result;
  4175. }
  4176. /*三角函数调用 func 三角函数
  4177. 反正切值. 用法: ATAN(X)返回X的反正切值
  4178. 余弦值. 用法: COS(X)返回X的余弦值
  4179. 正弦值. 用法: SIN(X)返回X的正弦值
  4180. 正切值. 用法: TAN(X)返回X的正切值
  4181. 求自然对数. 用法: LN(X)以e为底的对数 例如: LN(CLOSE)求收盘价的对数
  4182. 求10为底的对数. 用法: LOG(X)取得X的对数 例如: LOG(100)等于2
  4183. 指数. 用法: EXP(X)为e的X次幂 例如: EXP(CLOSE)返回e的CLOSE次幂
  4184. 开平方. 用法: SQRT(X)为X的平方根 例如: SQRT(CLOSE)收盘价的平方根
  4185. */
  4186. this.Trigonometric = function (data, func)
  4187. {
  4188. if (!Array.isArray(data))
  4189. {
  4190. if (this.IsNumber(data)) return func(data);
  4191. return null;
  4192. }
  4193. else
  4194. {
  4195. var result = [];
  4196. for (let i in data)
  4197. {
  4198. var item = data[i];
  4199. if (this.IsNumber(item)) result[i] = func(item);
  4200. else result[i] = null;
  4201. }
  4202. return result;
  4203. }
  4204. }
  4205. //反正弦值. 用法: ASIN(X)返回X的反正弦值
  4206. this.ASIN = function (data)
  4207. {
  4208. if (!Array.isArray(data))
  4209. {
  4210. if (this.IsNumber(data)) return Math.acos(data);
  4211. return null;
  4212. }
  4213. else
  4214. {
  4215. var result = [];
  4216. for (let i in data)
  4217. {
  4218. var item = data[i];
  4219. result[i] = null;
  4220. if (this.IsNumber(item))
  4221. {
  4222. if (item >= -1 && item <= 1)
  4223. {
  4224. result[i] = Math.asin(item);
  4225. }
  4226. else if (i - 1 >= 0)
  4227. {
  4228. var preItem = result[i - 1];
  4229. if (this.IsNumber(preItem)) result[i] = preItem;
  4230. }
  4231. }
  4232. }
  4233. return result;
  4234. }
  4235. }
  4236. //反余弦值. 用法: ACOS(X)返回X的反余弦值
  4237. this.ACOS = function (data)
  4238. {
  4239. if (!Array.isArray(data))
  4240. {
  4241. if (this.IsNumber(data)) return Math.acos(data);
  4242. return null;
  4243. }
  4244. else
  4245. {
  4246. var result = [];
  4247. for (let i in data)
  4248. {
  4249. var item = data[i];
  4250. result[i] = null;
  4251. if (this.IsNumber(item))
  4252. {
  4253. if (item >= -1 && item <= 1)
  4254. {
  4255. result[i] = Math.acos(item);
  4256. }
  4257. else if (i - 1 >= 0) //超出范围使用上一个数值
  4258. {
  4259. var preItem = result[i - 1];
  4260. if (this.IsNumber(preItem)) result[i] = preItem;
  4261. }
  4262. }
  4263. }
  4264. return result;
  4265. }
  4266. }
  4267. /*
  4268. LAST(X,A,B):持续存在.
  4269. 用法:
  4270. LAST(CLOSE>OPEN,10,5)
  4271. 表示从前10日到前5日内一直阳线
  4272. 若A为0,表示从第一天开始,B为0,表示到最后日止
  4273. */
  4274. this.LAST = function (data, n, n2)
  4275. {
  4276. var result = [];
  4277. if (n2 <= 0) n2 = data.length - 1;
  4278. if (n2 > n) return result;
  4279. var day = 0;
  4280. for (let i = 0, j = 0; i < data.length; ++i) {
  4281. result[i] = 0;
  4282. day = 0;
  4283. var start = i - n;
  4284. var end = i - n2;
  4285. if (start < 0 || end < 0) continue;
  4286. for (j = start; j < data.length && j <= end; ++j, ++day) {
  4287. if (!data[j]) break;
  4288. }
  4289. if (day == end - start + 1) //[start,end]
  4290. result[i] = 1;
  4291. }
  4292. return result;
  4293. }
  4294. /*
  4295. 属于未来函数,之字转向.
  4296. 用法: ZIG(K,N),当价格变化量超过N%时转向,K表示0:开盘价,1:最高价,2:最低价,3:收盘价,其余:数组信息
  4297. 例如: ZIG(3,5)表示收盘价的5%的ZIG转向
  4298. */
  4299. this.ZIG=function(data,n)
  4300. {
  4301. var hisData=this.SymbolData.Data;
  4302. var result=[];
  4303. if (typeof(data)=='number')
  4304. {
  4305. switch(data)
  4306. {
  4307. case 0:
  4308. data=hisData.GetOpen();
  4309. break;
  4310. case 1:
  4311. data=hisData.GetHigh();
  4312. break;
  4313. case 2:
  4314. data=hisData.GetLow();
  4315. break;
  4316. case 3:
  4317. data=hisData.GetClose();
  4318. break;
  4319. default:
  4320. return result;
  4321. }
  4322. }
  4323. return this.ZIG_Calculate(data,n);
  4324. }
  4325. this.ZIG_Calculate=function(data,dRate)
  4326. {
  4327. var dest=[];
  4328. var nDataCount=data.length;
  4329. var m=this.GetFirstVaildIndex(data);
  4330. var i = 0, lLastPos = 0, lState = 0, j = 0;
  4331. var dif = 0;
  4332. for (i = m + 1, lLastPos = lState = m; i<nDataCount - 1 && lState == m; ++i)
  4333. {
  4334. lState = Math.abs(data[i] - data[m]) * 100 >= dRate*data[m] ? (data[i]>data[m] ? i : -i) : m;
  4335. }
  4336. for (; i<nDataCount - 1; ++i)
  4337. {
  4338. if (data[i] >= data[i - 1] && data[i] >= data[i + 1])
  4339. {
  4340. if (lState<0)
  4341. {
  4342. if ((data[i] - data[-lState]) * 100<dRate*data[-lState]) continue;
  4343. else
  4344. {
  4345. dif = (data[lLastPos] - data[j = -lState]) / (-lState - lLastPos);
  4346. dest[j--]=data[-lState];
  4347. for (; j >= lLastPos; j--)
  4348. dest[j]=data[-lState] + (-lState - j)*dif;
  4349. lLastPos = -lState;
  4350. lState = i;
  4351. }
  4352. }
  4353. else if (data[i]>data[lState]) lState = i;
  4354. }
  4355. else if (data[i] <= data[i - 1] && data[i] <= data[i + 1])
  4356. {
  4357. if (lState>0)
  4358. {
  4359. if ((data[lState] - data[i]) * 100<dRate*data[lState]) continue;
  4360. else
  4361. {
  4362. dif = (data[lState] - data[j = lLastPos]) / (lState - lLastPos);
  4363. dest[j++]=data[lLastPos];
  4364. for (; j <= lState; ++j)
  4365. dest[j]=data[lLastPos] + (j - lLastPos)*dif;
  4366. lLastPos = lState;
  4367. lState = -i;
  4368. }
  4369. }
  4370. else if (data[i]<data[-lState]) lState = -i;
  4371. }
  4372. }
  4373. if (Math.abs(lState) >= nDataCount - 2)
  4374. {
  4375. if (lState>0 && data[nDataCount - 1] >= data[lState]) lState = nDataCount - 1;
  4376. if (lState<0 && data[nDataCount - 1] <= data[-lState]) lState = 1 - nDataCount;
  4377. }
  4378. if (lState>0)
  4379. {
  4380. dif = (data[lState] - data[j = lLastPos]) / (lState - lLastPos );
  4381. dest[j++]=data[lLastPos];
  4382. for (; j <= lState; ++j)
  4383. dest[j]=data[lLastPos] + (j - lLastPos)*dif;
  4384. }
  4385. else
  4386. {
  4387. dif = (data[lLastPos] - data[j = -lState]) / (-lState - lLastPos);
  4388. dest[j--]=data[-lState];
  4389. for (; j >= lLastPos; j--)
  4390. dest[j]=(data[-lState] + (-lState - j)*dif);
  4391. }
  4392. if ((lState = Math.abs(lState))<nDataCount - 1)
  4393. {
  4394. if (data[nDataCount - 1] >= data[lState])
  4395. {
  4396. dif = (data[nDataCount - 1] - data[j = lState]) / (nDataCount - lState);
  4397. dest[j++]=(data[lState]);
  4398. for (; j<nDataCount; ++j)
  4399. dest[j]=(data[lState] + (j - lState)*dif);
  4400. }
  4401. else
  4402. {
  4403. dif = (data[lState] - data[j = nDataCount - 1]) / (nDataCount - lState);
  4404. dest[j--]=(data[nDataCount - 1]);
  4405. for (; j >= lState; j--)
  4406. dest[j]=(data[nDataCount - 1] + (nDataCount - j)*dif);
  4407. }
  4408. }
  4409. return dest;
  4410. }
  4411. this.GetFirstVaildIndex=function(data)
  4412. {
  4413. for (var i = 0; i <data.length; ++i)
  4414. {
  4415. if (this.IsNumber(data[i]))
  4416. return i;
  4417. }
  4418. return data.length;
  4419. }
  4420. this.JSDraw = null;
  4421. this.CalculateZIGLine = function (firstData, secondData, thridData, data, result)
  4422. {
  4423. if (this.JSDraw == null) this.JSDraw = new JSDraw(this.ErrorHandler);
  4424. var isUp = secondData.Up;
  4425. var findData = firstData;
  4426. if (isUp)
  4427. {
  4428. for (var i = firstData.ID + 1; i < thridData.ID; ++i) //查找最高点
  4429. {
  4430. var subItem = data[i];
  4431. if (!this.IsNumber(subItem)) continue;
  4432. if (findData.Value < subItem) findData = { ID: i, Value: subItem };
  4433. }
  4434. }
  4435. else
  4436. {
  4437. for (var i = firstData.ID + 1; i < thridData.ID; ++i) //查找最低点
  4438. {
  4439. var subItem = data[i];
  4440. if (!this.IsNumber(subItem)) continue;
  4441. if (findData.Value > subItem) findData = { ID: i, Value: subItem };
  4442. }
  4443. }
  4444. secondData.Value = findData.Value;
  4445. secondData.ID = findData.ID;
  4446. var lineCache = { Start: { ID: firstData.ID, Value: firstData.Value }, End: { ID: secondData.ID, Value: secondData.Value } };
  4447. var lineData = this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值
  4448. for (var i in lineData)
  4449. {
  4450. var lineItem = lineData[i];
  4451. result[lineItem.ID] = lineItem.Value;
  4452. }
  4453. if (thridData.ID == data.length - 1) //最后一组数据
  4454. {
  4455. //最后2个点的数据连成线
  4456. lineCache = { Start: { ID: secondData.ID, Value: secondData.Value }, End: { ID: thridData.ID, Value: thridData.Value } };
  4457. lineData = this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值
  4458. for (var i in lineData)
  4459. {
  4460. var lineItem = lineData[i];
  4461. result[lineItem.ID] = lineItem.Value;
  4462. }
  4463. }
  4464. else
  4465. {
  4466. firstData.ID = secondData.ID;
  4467. firstData.Value = secondData.Value;
  4468. secondData.ID = thridData.ID;
  4469. secondData.Value = thridData.Value;
  4470. secondData.Up = firstData.Value < secondData.Value;
  4471. }
  4472. }
  4473. /*
  4474. 属于未来函数,前M个ZIG转向波谷到当前距离.
  4475. 用法:
  4476. TROUGHBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波谷到当前的周期数,M必须大于等于1
  4477. 例如:
  4478. TROUGHBARS(2,5,2)表示%5最低价ZIG转向的前2个波谷到当前的周期数
  4479. */
  4480. this.TROUGHBARS=function(data,n,n2)
  4481. {
  4482. var zigData=this.ZIG(data,n); //计算ZIG
  4483. var dest=[];
  4484. var lEnd =n2;
  4485. if (lEnd<1) return dest;
  4486. var nDataCount = zigData.length;
  4487. var trough = [];
  4488. for(var i=0;i<lEnd;++i) trough[i]=0;
  4489. var lFlag = 0;
  4490. var i = this.GetFirstVaildIndex(zigData) + 1;
  4491. for (lEnd--; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
  4492. for (; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
  4493. for (trough[0] = --i; i<nDataCount - 1; ++i)
  4494. {
  4495. if (zigData[i]<zigData[i + 1])
  4496. {
  4497. if (lFlag)
  4498. {
  4499. if (lEnd)
  4500. {
  4501. var tempTrough=trough.slice(0);
  4502. for(var j=0;j<lEnd;++j)
  4503. {
  4504. trough[j+1]=tempTrough[j];
  4505. }
  4506. }
  4507. trough[lFlag = 0] = i;
  4508. }
  4509. }
  4510. else lFlag = 1;
  4511. if (trough[lEnd]) dest[i]=(i - trough[lEnd]);
  4512. }
  4513. if (trough[lEnd]) dest[i]=(i - trough[lEnd]);
  4514. return dest;
  4515. }
  4516. this.TROUGH=function(data,n,n2)
  4517. {
  4518. var zigData=this.ZIG(data,n); //计算ZIG
  4519. var dest=[];
  4520. var End=n2;
  4521. if(End<1) return dest;
  4522. var nDataCount = zigData.length;
  4523. var trough=[];
  4524. for(var i=0;i<End;++i) trough[i]=0;
  4525. var i=1,Flag=0;
  4526. var i = this.GetFirstVaildIndex(zigData) + 1;
  4527. for(End--; i<nDataCount && zigData[i]>zigData[i-1]; ++i);
  4528. for(; i<nDataCount && zigData[i]<zigData[i-1]; ++i);
  4529. for(trough[0]=--i;i<nDataCount-1;++i)
  4530. {
  4531. if(zigData[i]<zigData[i+1])
  4532. {
  4533. if(Flag)
  4534. {
  4535. if(End)
  4536. {
  4537. var tempTrough=trough.slice(0);
  4538. for(var j=0;j<End;++j)
  4539. {
  4540. trough[j+1]=tempTrough[j];
  4541. }
  4542. }
  4543. trough[Flag=0]=i;
  4544. }
  4545. }
  4546. else Flag=1;
  4547. if(trough[End]) dest[i]=zigData[trough[End]];
  4548. }
  4549. if(trough[End]) dest[i]=zigData[trough[End]];
  4550. return dest;
  4551. }
  4552. /*
  4553. 属于未来函数,前M个ZIG转向波峰到当前距离.
  4554. 用法:
  4555. PEAKBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波峰到当前的周期数,M必须大于等于1
  4556. 例如:
  4557. PEAKBARS(0,5,1)表示%5开盘价ZIG转向的上一个波峰到当前的周期数
  4558. */
  4559. this.PEAKBARS=function(data,n,n2)
  4560. {
  4561. var zigData=this.ZIG(data,n); //计算ZIG
  4562. var dest=[];
  4563. var nDataCount = zigData.length;
  4564. var lEnd = n2;
  4565. if (lEnd < 1) return dest;
  4566. var peak = [];
  4567. for(var i=0;i<lEnd;++i) peak[i]=0;
  4568. var lFlag = 0;
  4569. var i = this.GetFirstVaildIndex(zigData) + 1;
  4570. for (lEnd--; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
  4571. for (; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
  4572. for (peak[0] = --i; i<nDataCount - 1; ++i)
  4573. {
  4574. if (zigData[i]>zigData[i + 1])
  4575. {
  4576. if (lFlag)
  4577. {
  4578. if (lEnd)
  4579. {
  4580. var tempPeak=peak.slice(0);
  4581. for(var j=0;j<lEnd;++j)
  4582. {
  4583. peak[j+1]=tempPeak[j];
  4584. }
  4585. }
  4586. peak[lFlag = 0] = i;
  4587. }
  4588. }
  4589. else lFlag = 1;
  4590. if (peak[lEnd]) dest[i]=(i - peak[lEnd]);
  4591. }
  4592. if (peak[lEnd])dest[i]=(i - peak[lEnd]);
  4593. return dest;
  4594. }
  4595. this.PEAK=function(data,n,n2)
  4596. {
  4597. var zigData=this.ZIG(data,n); //计算ZIG
  4598. var dest=[];
  4599. var nDataCount = zigData.length;
  4600. var lEnd = n2;
  4601. if (lEnd < 1) return dest;
  4602. var lFlag = 0;
  4603. var peak = [];
  4604. for(var i=0;i<lEnd;++i) peak[i]=0;
  4605. var i = this.GetFirstVaildIndex(zigData) + 1;
  4606. for (lEnd--; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
  4607. for (; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
  4608. for (peak[0] = --i; i<nDataCount - 1; ++i)
  4609. {
  4610. if (zigData[i]>zigData[i + 1])
  4611. {
  4612. if (lFlag)
  4613. {
  4614. if (lEnd)
  4615. {
  4616. var tempPeak=peak.slice(0);
  4617. for(var j=0;j<lEnd;++j)
  4618. {
  4619. peak[j+1]=tempPeak[j];
  4620. }
  4621. }
  4622. peak[lFlag = 0] = i;
  4623. }
  4624. }
  4625. else lFlag = 1;
  4626. if (peak[lEnd]) dest[i]=(zigData[peak[lEnd]]);
  4627. }
  4628. if (peak[lEnd]) dest[i]=(zigData[peak[lEnd]]);
  4629. return dest;
  4630. }
  4631. /*
  4632. 一直存在.
  4633. 例如:
  4634. EVERY(CLOSE>OPEN,N)
  4635. 表示N日内一直阳线(N应大于0,小于总周期数,N支持变量)
  4636. */
  4637. this.EVERY = function (data, n)
  4638. {
  4639. var result=[];
  4640. if (n<1) return result;
  4641. if (IFrameSplitOperator.IsNumber(n))
  4642. {
  4643. n=parseInt(n);
  4644. var i=0;
  4645. for(;i<data.length;++i)
  4646. {
  4647. result[i]=null;
  4648. if (this.IsNumber(data[i])) break;
  4649. }
  4650. var flag=0;
  4651. for(;i<data.length;++i)
  4652. {
  4653. if (data[i]) flag+=1;
  4654. else flag=0;
  4655. if (flag==n)
  4656. {
  4657. result[i]=1;
  4658. --flag;
  4659. }
  4660. else
  4661. {
  4662. result[i]=0;
  4663. }
  4664. }
  4665. }
  4666. else if (Array.isArray(n))
  4667. {
  4668. for(var i=0;i<n.length;++i)
  4669. {
  4670. var value=n[i];
  4671. result[i]=null;
  4672. if (!IFrameSplitOperator.IsPlusNumber(value)) continue;
  4673. value=parseInt(value);
  4674. var flag=0;
  4675. for(var j=i, k=0; j>=0 && k<value; --j, ++k)
  4676. {
  4677. if (data[j]) ++flag;
  4678. }
  4679. result[i]=(flag==value?1:0);
  4680. }
  4681. }
  4682. return result;
  4683. }
  4684. /*
  4685. 成本分布情况.
  4686. 用法:
  4687. COST(10),表示10%获利盘的价格是多少,即有10%的持仓量在该价格以下,其余90%在该价格以上,为套牢盘
  4688. 该函数仅对日线分析周期有效
  4689. */
  4690. this.COST = function (data, node)
  4691. {
  4692. var result=[];
  4693. var rate=data/100;
  4694. if(rate<0.000001 || rate>1) return result;
  4695. var kData=this.SymbolData.Data.Data;
  4696. if (!kData || kData.length<=0) return result;
  4697. var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本
  4698. var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low;
  4699. for(var i=0;i<kData.length;++i)
  4700. {
  4701. var item=kData[i];
  4702. dMinPrice = Math.min(dMinPrice,item.Low);
  4703. dMaxPrice = Math.max(dMaxPrice,item.High);
  4704. }
  4705. if (dMinPrice > 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0)
  4706. this.ThrowUnexpectedNode(node,'COST() 历史K线最大最小值错误, 超出(0,5000)范围');
  4707. var lMaxPrice = parseInt(dMaxPrice * 100 + 1);
  4708. var lMinPrice = parseInt(dMinPrice * 100 - 1);
  4709. var lLow = 0, lHigh = 0, lClose = 0;
  4710. //去掉小数
  4711. dMaxPrice = lMaxPrice / 100.0;
  4712. dMinPrice = lMinPrice / 100.0;
  4713. var lSpeed = lMaxPrice - lMinPrice + 1;
  4714. if (lSpeed < 1) return result;
  4715. var aryVolPrice=[],aryPerVol=[];
  4716. for(var i=0;i<lSpeed;++i)
  4717. {
  4718. aryVolPrice[i]=0;
  4719. aryPerVol[i]=0;
  4720. }
  4721. var dHSL = 0, dTotalVol = 0, dVol = 0, dCost=0;
  4722. for(var i=0;i<kData.length;++i)
  4723. {
  4724. if (i >= aryCapital.length) continue;
  4725. if (aryCapital[i]>1)
  4726. {
  4727. var kItem=kData[i]
  4728. dHSL = kItem.Vol/aryCapital[i];
  4729. for( var j=0;j<lSpeed;j++)
  4730. aryVolPrice[j]*=(1-dHSL);
  4731. lLow=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Low *100)))-lMinPrice;
  4732. lHigh=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.High*100)))-lMinPrice;
  4733. lClose=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Close*100)))-lMinPrice;
  4734. for(var j=0;j<lSpeed;++j) aryPerVol[j]=0;
  4735. var lHalf =parseInt((lLow + lHigh + 2 * lClose) / 4);
  4736. if (lHalf == lHigh || lHalf == lLow)
  4737. {
  4738. aryPerVol[lHalf] += kItem.Vol;
  4739. }
  4740. else
  4741. {
  4742. var dVH = kItem.Vol / (lHalf - lLow);
  4743. for (var k = lLow; k<lHalf; ++k)
  4744. {
  4745. aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow));
  4746. }
  4747. for (k; k <= lHigh; ++k)
  4748. {
  4749. aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh));
  4750. }
  4751. }
  4752. var dTotalVol = 0;
  4753. for (var j = lLow; j <= lHigh; j++)
  4754. {
  4755. aryVolPrice[j] += aryPerVol[j];
  4756. }
  4757. for (var j = 0; j < lSpeed; j++)
  4758. {
  4759. dTotalVol += aryVolPrice[j];
  4760. }
  4761. for(j=0,dCost=dVol=0;j<lSpeed;++j)
  4762. {
  4763. dVol+=aryVolPrice[j];
  4764. if(dVol>=dTotalVol*rate)
  4765. {
  4766. dCost=(dMaxPrice-dMinPrice)*j/lSpeed+dMinPrice;
  4767. break;
  4768. }
  4769. }
  4770. }
  4771. result[i]=dCost;
  4772. }
  4773. return result;
  4774. }
  4775. /*
  4776. 获利盘比例.
  4777. 用法:
  4778. WINNER(CLOSE),表示以当前收市价卖出的获利盘比例,例如返回0.1表示10%获利盘;WINNER(10.5)表示10.5元价格的获利盘比例
  4779. 该函数仅对日线分析周期有效
  4780. !!!!计算比较耗时间
  4781. */
  4782. this.WINNER = function (data,node)
  4783. {
  4784. var result=[];
  4785. var kData=this.SymbolData.Data.Data;
  4786. if (!kData || kData.length<=0) return result;
  4787. var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本
  4788. var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low;
  4789. for(var i=0;i<kData.length;++i)
  4790. {
  4791. var item=kData[i];
  4792. dMinPrice = Math.min(dMinPrice,item.Low);
  4793. dMaxPrice = Math.max(dMaxPrice,item.High);
  4794. }
  4795. if (dMinPrice > 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0)
  4796. this.ThrowUnexpectedNode(node,'WINNER() 历史K线最大最小值错误, 超出(0,5000)范围');
  4797. var lMaxPrice = parseInt(dMaxPrice * 100 + 1);
  4798. var lMinPrice = parseInt(dMinPrice * 100 - 1);
  4799. var lLow = 0, lHigh = 0, lClose = 0;
  4800. //去掉小数
  4801. dMaxPrice = lMaxPrice / 100.0;
  4802. dMinPrice = lMinPrice / 100.0;
  4803. var lSpeed = lMaxPrice - lMinPrice + 1;
  4804. if (lSpeed < 1) return result;
  4805. var aryVolPrice=[],aryPerVol=[];
  4806. for(var i=0;i<lSpeed;++i)
  4807. {
  4808. aryVolPrice[i]=0;
  4809. aryPerVol[i]=0;
  4810. }
  4811. var dHSL = 0, dTotalVol = 0, dVol = 0;
  4812. for(var i=0;i<kData.length;++i)
  4813. {
  4814. if (i >= aryCapital.length) continue;
  4815. if (!(aryCapital[i]>1)) continue;
  4816. var kItem=kData[i]
  4817. dHSL = kItem.Vol/aryCapital[i];
  4818. for( var j=0;j<lSpeed;j++)
  4819. aryVolPrice[j]*=(1-dHSL);
  4820. lLow=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Low *100)))-lMinPrice;
  4821. lHigh=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.High*100)))-lMinPrice;
  4822. lClose=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Close*100)))-lMinPrice;
  4823. for(var j=0;j<lSpeed;++j) aryPerVol[j]=0;
  4824. var lHalf =parseInt((lLow + lHigh + 2 * lClose) / 4);
  4825. if (lHalf == lHigh || lHalf == lLow)
  4826. {
  4827. aryPerVol[lHalf] += kItem.Vol;
  4828. }
  4829. else
  4830. {
  4831. var dVH = kItem.Vol / (lHalf - lLow);
  4832. for (var k = lLow; k<lHalf; ++k)
  4833. {
  4834. aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow));
  4835. }
  4836. for (k; k <= lHigh; ++k)
  4837. {
  4838. aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh));
  4839. }
  4840. }
  4841. var dTotalVol = 0;
  4842. for (var j = lLow; j <= lHigh; j++)
  4843. {
  4844. aryVolPrice[j] += aryPerVol[j];
  4845. }
  4846. for (var j = 0; j < lSpeed; j++)
  4847. {
  4848. dTotalVol += aryVolPrice[j];
  4849. }
  4850. if (Array.isArray(data))
  4851. lHigh = parseInt(Math.min((data[i] * 100) - lMinPrice, lSpeed - 1));
  4852. else
  4853. lHigh = parseInt(Math.min((data * 100) - lMinPrice, lSpeed - 1));
  4854. for (var j = 0, dVol = 0; j <= lHigh; j++)
  4855. {
  4856. dVol += aryVolPrice[j];
  4857. }
  4858. if (dTotalVol > 0) result[i]=dVol / dTotalVol;
  4859. else if (i - 1 >= 0) result[i] = result[i - 1];
  4860. }
  4861. return result;
  4862. }
  4863. //计算截至到某一天的历史所有筹码
  4864. this.CalculateChip = function (index, exchangeData, hisData, dRate)
  4865. {
  4866. var result = { Min: null, Max: null, Data: [] };
  4867. var seed = 1;//筹码历史衰减换手系数
  4868. var max = null, min = null;
  4869. for (let i = index; i >= 0; --i)
  4870. {
  4871. let item = {}; //Vol:量 High:最高 Low:最低
  4872. var kData = hisData[i];
  4873. if (i == index) item.Vol = kData.Vol * exchangeData[i];
  4874. else item.Vol = kData.Vol * seed;
  4875. item.Date = kData.Date;
  4876. item.High = kData.High;
  4877. item.Low = kData.Low;
  4878. if (max == null) max = item.High;
  4879. else if (max < item.High) max = item.High;
  4880. if (min == null) min = item.Low;
  4881. else if (min < item.Low) min = item.Low;
  4882. result.Data[i] = item;
  4883. seed *= (1 - (exchangeData[i] / 100) * dRate); //换手率累乘
  4884. }
  4885. result.Max = max;
  4886. result.Min = min;
  4887. return result;
  4888. }
  4889. /*
  4890. 返回是否连涨周期数.
  4891. 用法:
  4892. UPNDAY(CLOSE,M)
  4893. 表示连涨M个周期,M为常量
  4894. */
  4895. this.UPNDAY = function (data, n)
  4896. {
  4897. var result = [];
  4898. if (n < 1) return result;
  4899. if (data == null || n > data.length) return result;
  4900. var days = 0;
  4901. for (let i = 0; i < data.length; ++i)
  4902. {
  4903. result[i] = 0;
  4904. if (i - 1 < 0) continue;
  4905. if (!this.IsNumber(data[i]) || !this.IsNumber(data[i - 1])) //无效数都不算连涨
  4906. {
  4907. days = 0;
  4908. continue;
  4909. }
  4910. if (data[i] > data[i - 1])++days;
  4911. else days = 0;
  4912. if (days == n)
  4913. {
  4914. result[i] = 1;
  4915. --days;
  4916. }
  4917. }
  4918. return result;
  4919. }
  4920. /*
  4921. 返回是否连跌周期.
  4922. 用法:
  4923. DOWNNDAY(CLOSE,M)
  4924. 表示连跌M个周期,M为常量
  4925. */
  4926. this.DOWNNDAY = function (data, n)
  4927. {
  4928. var result = [];
  4929. if (n < 1) return result;
  4930. if (data == null || n > data.length) return result;
  4931. var days = 0;
  4932. for (let i = 0; i < data.length; ++i)
  4933. {
  4934. result[i] = 0;
  4935. if (i - 1 < 0) continue;
  4936. if (!this.IsNumber(data[i]) || !this.IsNumber(data[i - 1])) //无效数都不算连涨
  4937. {
  4938. days = 0;
  4939. continue;
  4940. }
  4941. if (data[i] < data[i - 1])++days;
  4942. else days = 0;
  4943. if (days == n)
  4944. {
  4945. result[i] = 1;
  4946. --days;
  4947. }
  4948. }
  4949. return result;
  4950. }
  4951. /*
  4952. 返回是否持续存在X>Y
  4953. 用法:
  4954. NDAY(CLOSE,OPEN,3)
  4955. 表示连续3日收阳线
  4956. */
  4957. this.NDAY = function (data, data2, n)
  4958. {
  4959. var result = [];
  4960. if (n < 1) return result;
  4961. if (!Array.isArray(data) && !Array.isArray(data2)) return result;
  4962. if (data == null || data2 == null) return result;
  4963. if (Array.isArray(data) && Array.isArray(data2))
  4964. {
  4965. if (n >= data.length || n >= data2.length) return result;
  4966. var count = Math.max(data.length, data2.length);
  4967. var days = 0;
  4968. for (let i = 0; i < count; ++i)
  4969. {
  4970. result[i] = 0;
  4971. if (i >= data.length || i >= data2.length) continue;
  4972. if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]))
  4973. {
  4974. days = 0;
  4975. continue;
  4976. }
  4977. if (data[i] > data2[i])++days;
  4978. else days = 0;
  4979. if (days == n)
  4980. {
  4981. result[i] = 1;
  4982. --days;
  4983. }
  4984. }
  4985. }
  4986. else if (Array.isArray(data) && !Array.isArray(data2))
  4987. {
  4988. if (n >= data.length || !this.IsNumber(data2)) return;
  4989. var days = 0;
  4990. for (let i in data)
  4991. {
  4992. result[i] = 0;
  4993. if (!this.IsNumber(data[i]))
  4994. {
  4995. days = 0;
  4996. continue;
  4997. }
  4998. if (data[i] > data2)++days;
  4999. else days = 0;
  5000. if (days == n)
  5001. {
  5002. result[i] = 1;
  5003. --days;
  5004. }
  5005. }
  5006. }
  5007. else if (!Array.isArray(data) && Array.isArray(data2))
  5008. {
  5009. if (n >= data2.length || !this.IsNumber(data)) return;
  5010. var days = 0;
  5011. for (let i in data2)
  5012. {
  5013. result[i] = 0;
  5014. if (!this.IsNumber(data2[i]))
  5015. {
  5016. days = 0;
  5017. continue;
  5018. }
  5019. if (data > data2[i])++days;
  5020. else days = 0;
  5021. if (days == n)
  5022. {
  5023. result[i] = 1;
  5024. --days;
  5025. }
  5026. }
  5027. }
  5028. return result;
  5029. }
  5030. /*
  5031. 两条线维持一定周期后交叉.
  5032. 用法:LONGCROSS(A,B,N)表示A在N周期内都小于B,本周期从下方向上穿过B时返回1,否则返回0
  5033. */
  5034. this.LONGCROSS = function (data, data2, n)
  5035. {
  5036. var result = [];
  5037. var count = Math.max(data.length, data2.length);
  5038. for (let i = 0; i < count; ++i)
  5039. {
  5040. result[i] = 0;
  5041. if (i - 1 < 0) continue;
  5042. if (i >= data.length || i >= data2.length) continue;
  5043. if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]) || !this.IsNumber(data[i - 1]) || !this.IsNumber(data2[i - 1])) continue;
  5044. if (data[i] > data2[i] && data[i - 1] < data2[i - 1]) result[i] = 1;
  5045. }
  5046. for (let i = 0, j = 0; i < count; ++i)
  5047. {
  5048. if (!result[i]) continue;
  5049. for (j = 1; j <= n && i - j >= 0; ++j)
  5050. {
  5051. if (data[i - j] >= data2[i - j])
  5052. {
  5053. result[i] = 0;
  5054. break;
  5055. }
  5056. }
  5057. }
  5058. return result;
  5059. }
  5060. this.ISVALID=function(data)
  5061. {
  5062. if (Array.isArray(data))
  5063. {
  5064. var result=[];
  5065. for(var i=0;i<data.length;++i)
  5066. {
  5067. var item=data[i];
  5068. if (item) result[i]=1;
  5069. else result[i]=0;
  5070. }
  5071. return result;
  5072. }
  5073. else
  5074. {
  5075. if (data) return 1;
  5076. else return 0;
  5077. }
  5078. }
  5079. /*
  5080. EXISTR(X,A,B):是否存在(前几日到前几日间).
  5081. 例如: EXISTR(CLOSE>OPEN,10,5)
  5082. 表示从前10日内到前5日内存在着阳线
  5083. 若A为0,表示从第一天开始,B为0,表示到最后日止
  5084. */
  5085. this.EXISTR = function (data, n, n2)
  5086. {
  5087. var result = [];
  5088. if (!Array.isArray(data)) return result;
  5089. n = parseInt(n);
  5090. n2 = parseInt(n2);
  5091. if (n <= 0) n = data.length;
  5092. if (n2 <= 0) n2 = 1;
  5093. if (n2 > n) return result;
  5094. var result = [];
  5095. var value;
  5096. for (let i = 0, j = 0; i < data.length; ++i)
  5097. {
  5098. result[i] = null;
  5099. if (i - n < 0 || i - n2 < 0) continue;
  5100. result[i] = 0;
  5101. for (j = n; j >= n2; --j)
  5102. {
  5103. var value = data[i - j];
  5104. if (this.IsNumber(value) && value)
  5105. {
  5106. result[i] = 1;
  5107. break;
  5108. }
  5109. }
  5110. }
  5111. return result;
  5112. }
  5113. /*
  5114. RELATE(X,Y,N) 返回X和Y的N周期的相关系数
  5115. RELATE(X,Y,N)=(∑[(Xi-Avg(X))(Yi-Avg(y))])/N ÷ √((∑(Xi-Avg(X))^2)/N * (∑(Yi-Avg(Y))^2)/N)
  5116. 其中 avg(x)表示x的N周期均值: avg(X) = (∑Xi)/N
  5117. √(...)表示开平方
  5118. */
  5119. this.RELATE = function (data, data2, n)
  5120. {
  5121. var result = [];
  5122. if (n < 1) n = 1;
  5123. if (!Array.isArray(data) || !Array.isArray(data2)) return result;
  5124. var dataAverage = this.CalculateAverage(data, n);
  5125. var data2Average = this.CalculateAverage(data2, n);
  5126. var count = Math.max(data.length, data2.length);
  5127. for (let i = 0, j = 0; i < count; ++i)
  5128. {
  5129. result[i] = null;
  5130. if (i >= data.length || i >= data2.length || i >= dataAverage.length || i >= data2Average.length) continue;
  5131. var average = dataAverage[i];
  5132. var average2 = data2Average[i];
  5133. var total = 0, total2 = 0, total3 = 0;
  5134. for (j = i - n + 1; j <= i; ++j)
  5135. {
  5136. total += (data[j] - average) * (data2[j] - average2); //∑[(Xi-Avg(X))(Yi-Avg(y))])
  5137. total2 += Math.pow(data[j] - average, 2); //∑(Xi-Avg(X))^2
  5138. total3 += Math.pow(data2[j] - average2, 2); //∑(Yi-Avg(Y))^2)
  5139. }
  5140. result[i] = (total / n) / (Math.sqrt(total2 / n) * Math.sqrt(total3 / n));
  5141. }
  5142. return result;
  5143. }
  5144. //计算数组n周期内的均值
  5145. this.CalculateAverage = function (data, n)
  5146. {
  5147. var result = [];
  5148. if (n < 1) return result;
  5149. var total = 0;
  5150. for (var i = 0; i < data.length; ++i) //去掉开始的无效数
  5151. {
  5152. if (this.IsNumber(data[i])) break;
  5153. }
  5154. for (; i < data.length && i < n; ++i) //计算第1个周期的数据
  5155. {
  5156. result[i] = null;
  5157. var value = data[i];
  5158. if (!this.IsNumber(value)) continue;
  5159. total += value;
  5160. }
  5161. result[i - 1] = total / n;
  5162. for (; i < data.length; ++i) //计算后面的周期数据
  5163. {
  5164. var value = data[i];
  5165. var preValue = data[i - n]; //上一个周期的第1个数据
  5166. if (!this.IsNumber(value)) value = 0;
  5167. if (!this.IsNumber(preValue)) preValue = 0;
  5168. total = total - preValue + value; //当前周期的数据 等于上一个周期数据 去掉上一个周期的第1个数据 加上这个周期的最后1个数据
  5169. result[i] = total / n;
  5170. }
  5171. return result;
  5172. }
  5173. /*
  5174. COVAR(X,Y,N) 返回X和Y的N周期的协方差
  5175. */
  5176. this.COVAR = function (data, data2, n)
  5177. {
  5178. if (this.IsNumber(data) || this.IsNumber(data2)) return 0;
  5179. var result = [];
  5180. if (n < 1) n = 1;
  5181. if (!Array.isArray(data) || !Array.isArray(data2)) return result;
  5182. var dataAverage = this.CalculateAverage(data, n);
  5183. var data2Average = this.CalculateAverage(data2, n);
  5184. var count = Math.max(data.length, data2.length);
  5185. var count = Math.max(data.length, data2.length);
  5186. for (let i = 0, j = 0; i < count; ++i)
  5187. {
  5188. result[i] = null;
  5189. if (i >= data.length || i >= data2.length || i >= dataAverage.length || i >= data2Average.length) continue;
  5190. var average = dataAverage[i];
  5191. var average2 = data2Average[i];
  5192. var total = 0;
  5193. for (j = i - n + 1; j <= i; ++j)
  5194. {
  5195. total += (data[j] - average) * (data2[j] - average2);
  5196. }
  5197. result[i] = (total / n);
  5198. }
  5199. return result;
  5200. }
  5201. /*
  5202. 求上一高点到当前的周期数.
  5203. 用法:
  5204. HHVBARS(X,N):求N周期内X最高值到当前周期数,N=0表示从第一个有效值开始统计
  5205. 例如:
  5206. HHVBARS(HIGH,0)求得历史新高到到当前的周期数
  5207. */
  5208. this.HHVBARS = function (data, n)
  5209. {
  5210. var result = [];
  5211. if (!Array.isArray(data)) return result;
  5212. if (Array.isArray(n))
  5213. {
  5214. for(var i=0;i<n.length;++i)
  5215. {
  5216. result[i]=null;
  5217. var period=n[i];
  5218. if (!this.IsNumber(period)) continue;
  5219. var start=i-period;
  5220. if (start<0) start=0;
  5221. var nMax=null;
  5222. var j=start;
  5223. for(; j<data.length;++j)
  5224. {
  5225. if (this.IsNumber(data[j]))
  5226. {
  5227. nMax=j;
  5228. break;
  5229. }
  5230. }
  5231. for(var k=0; j<data.length && k<period;++k, ++j)
  5232. {
  5233. if (data[j]>=data[nMax]) nMax=j;
  5234. }
  5235. if (nMax!=null)
  5236. result[i]=(i-nMax);
  5237. }
  5238. }
  5239. else
  5240. {
  5241. if (n < 1) n = data.length;
  5242. var nMax = null; //最大值索引
  5243. for (var i = 0; i < data.length; ++i)
  5244. {
  5245. result[i] = null;
  5246. if (this.IsNumber(data[i])) {
  5247. nMax = i;
  5248. break;
  5249. }
  5250. }
  5251. var j = 0;
  5252. for (i = nMax + 1; i < data.length && j < n; ++i, ++j) //求第1个最大值
  5253. {
  5254. if (data[i] >= data[nMax]) nMax = i;
  5255. if (n == data.length) result[i] = (i - nMax);
  5256. }
  5257. for (; i < data.length; ++i)
  5258. {
  5259. if (i - nMax < n)
  5260. {
  5261. if (data[i] >= data[nMax]) nMax = i;
  5262. }
  5263. else
  5264. {
  5265. nMax = i - n + 1;
  5266. for (j = nMax; j <= i; ++j) //计算区间最大值
  5267. {
  5268. if (data[j] >= data[nMax]) nMax = j;
  5269. }
  5270. }
  5271. result[i] = i - nMax;
  5272. }
  5273. }
  5274. return result;
  5275. }
  5276. /*
  5277. 求上一低点到当前的周期数.
  5278. 用法: LLVBARS(X,N):求N周期内X最低值到当前周期数,N=0表示从第一个有效值开始统计
  5279. 例如: LLVBARS(HIGH,20)求得20日最低点到当前的周期数
  5280. */
  5281. this.LLVBARS = function (data, n)
  5282. {
  5283. var result = [];
  5284. if (!Array.isArray(data)) return result;
  5285. if (Array.isArray(n))
  5286. {
  5287. for(var i=0;i<n.length;++i)
  5288. {
  5289. result[i]=null;
  5290. var period=n[i];
  5291. if (!this.IsNumber(period)) continue;
  5292. var start=i-period;
  5293. if (start<0) start=0;
  5294. var nMin=null;
  5295. var j=start;
  5296. for(; j<data.length;++j)
  5297. {
  5298. if (this.IsNumber(data[j]))
  5299. {
  5300. nMin=j;
  5301. break;
  5302. }
  5303. }
  5304. for(var k=0; j<data.length && k<period;++k, ++j)
  5305. {
  5306. if (data[j]<=data[nMin]) nMin=j;
  5307. }
  5308. if (nMin!=null)
  5309. result[i]=(i-nMin);
  5310. }
  5311. }
  5312. else
  5313. {
  5314. if (n < 1) n = data.length;
  5315. var nMin = null; //最小值索引
  5316. for (var i = 0; i < data.length; ++i)
  5317. {
  5318. result[i] = null;
  5319. if (this.IsNumber(data[i]))
  5320. {
  5321. nMin = i;
  5322. break;
  5323. }
  5324. }
  5325. var j = 0;
  5326. for (i = nMin + 1; i < data.length && j < n; ++i, ++j) //求第1个最大值
  5327. {
  5328. if (data[i] <= data[nMin]) nMin = i;
  5329. if (n == data.length) result[i] = (i - nMin);
  5330. }
  5331. for (; i < data.length; ++i)
  5332. {
  5333. if (i - nMin < n)
  5334. {
  5335. if (data[i] <= data[nMin]) nMin = i;
  5336. }
  5337. else
  5338. {
  5339. nMin = i - n + 1;
  5340. for (j = nMin; j <= i; ++j) //计算区间最小值
  5341. {
  5342. if (data[j] <= data[nMin]) nMin = j;
  5343. }
  5344. }
  5345. result[i] = i - nMin;
  5346. }
  5347. }
  5348. return result;
  5349. }
  5350. /*
  5351. β(Beta)系数
  5352. BETA(N) 返回当前证券N周期收益与对应大盘指数收益相比的贝塔系数
  5353. 需要下载上证指数历史数据
  5354. 涨幅(X)=(现价-上一个交易日收盘价)/上一个交易日收盘价
  5355. 公式=股票和指数协方差/股票方差
  5356. */
  5357. this.BETA = function (n)
  5358. {
  5359. var result = [];
  5360. var stockData = this.SymbolData.Data;
  5361. var indexData = this.SymbolData.IndexData;
  5362. if (n <= 0) n = 1;
  5363. var stockProfit = []; //股票涨幅
  5364. var indexProfit = []; //指数涨幅
  5365. for (let i = 0; i < stockData.Data.length; ++i)
  5366. {
  5367. stockProfit[i] = 0;
  5368. indexProfit[i] = 0;
  5369. var stockItem = stockData.Data[i];
  5370. var indexItem = indexData.Data[i];
  5371. if (stockItem.Close > 0 && stockItem.YClose > 0) stockProfit[i] = (stockItem.Close - stockItem.YClose) / stockItem.YClose;
  5372. if (indexItem.Close > 0 && indexItem.YClose > 0) indexProfit[i] = (indexItem.Close - indexItem.YClose) / indexItem.YClose;
  5373. }
  5374. //计算均值数组
  5375. var averageStockProfit = this.CalculateAverage(stockProfit, n);
  5376. var averageIndexProfit = this.CalculateAverage(indexProfit, n);
  5377. for (var i = 0, j = 0; i < stockData.Data.length; ++i)
  5378. {
  5379. result[i] = null;
  5380. if (i >= stockProfit.length || i >= indexProfit.length || i >= averageStockProfit.length || i >= averageIndexProfit.length) continue;
  5381. var averageStock = averageStockProfit[i];
  5382. var averageIndex = averageIndexProfit[i];
  5383. var covariance = 0; //协方差
  5384. var variance = 0; //方差
  5385. for (j = i - n + 1; j <= i; ++j)
  5386. {
  5387. var value = (indexProfit[j] - averageIndex);
  5388. var value2 = (stockProfit[j] - averageStock);
  5389. covariance += value * value2;
  5390. variance += value * value;
  5391. }
  5392. if (this.IsDivideNumber(variance) && this.IsNumber(covariance))
  5393. result[i] = covariance / variance; //(covariance/n)/(variance/n)=covariance/variance;
  5394. }
  5395. return result;
  5396. }
  5397. /*
  5398. 用法:BETA2(X,Y,N)为X与Y的N周期相关放大系数,表示Y变化1%,则X将变化N%
  5399. 例如:BETA2(CLOSE,INDEXC,10)表示收盘价与大盘指数之间的10周期相关放大率
  5400. */
  5401. this.BETA2 = function (x, y, n)
  5402. {
  5403. var result = [];
  5404. if (n <= 0) n = 1;
  5405. var xProfit = [null]; //x数据的涨幅
  5406. var yProfit = [null]; //y数据的涨幅
  5407. var count = Math.max(x.length, y.length);
  5408. var lastItem = { X: x[0], Y: y[0] };
  5409. for (var i = 1; i < count; ++i)
  5410. {
  5411. xProfit[i] = 0;
  5412. yProfit[i] = 0;
  5413. var xItem = x[i];
  5414. var yItem = y[i];
  5415. if (lastItem.X > 0) xProfit[i] = (xItem - lastItem.X) / lastItem.X;
  5416. if (lastItem.Y > 0) yProfit[i] = (yItem - lastItem.Y) / lastItem.Y;
  5417. lastItem = { X: xItem, Y: yItem };
  5418. }
  5419. //计算均值数组
  5420. var averageXProfit = this.CalculateAverage(xProfit, n);
  5421. var averageYProfit = this.CalculateAverage(yProfit, n);
  5422. for (var i = 0, j = 0; i < count; ++i)
  5423. {
  5424. result[i] = null;
  5425. if (i >= xProfit.length || i >= yProfit.length || i >= averageXProfit.length || i >= averageYProfit.length) continue;
  5426. var averageX = averageXProfit[i];
  5427. var averageY = averageYProfit[i];
  5428. var covariance = 0; //协方差
  5429. var variance = 0; //方差
  5430. for (j = i - n + 1; j <= i; ++j)
  5431. {
  5432. var value = (xProfit[j] - averageX);
  5433. var value2 = (yProfit[j] - averageY);
  5434. covariance += value * value2;
  5435. variance += value * value;
  5436. }
  5437. if (this.IsDivideNumber(variance) && this.IsNumber(covariance))
  5438. result[i] = covariance / variance; //(covariance/n)/(variance/n)=covariance/variance;
  5439. }
  5440. return result;
  5441. }
  5442. /*
  5443. 抛物转向.
  5444. 用法:
  5445. SAR(N,S,M),N为计算周期,S为步长,M为极值
  5446. 例如:
  5447. SAR(10,2,20)表示计算10日抛物转向,步长为2%,极限值为20%
  5448. */
  5449. this.SAR = function (n, step, exValue)
  5450. {
  5451. var result = [];
  5452. var stockData = this.SymbolData.Data;
  5453. if (n >= stockData.Data.length) return result;
  5454. var high = null, low = null;
  5455. for (var i = 0; i < n; ++i)
  5456. {
  5457. var item = stockData.Data[i];
  5458. if (high == null) high = item.High;
  5459. else if (high < item.High) high = item = high;
  5460. if (low == null) low = item.Low;
  5461. else if (low > item.Low) low = item.Low;
  5462. }
  5463. const SAR_LONG = 0, SAR_SHORT = 1;
  5464. var position = SAR_LONG;
  5465. result[n - 1] = low;
  5466. var nextSar = low, sip = stockData.Data[0].High, af = exValue / 100;
  5467. for (var i = n; i < stockData.Data.length; ++i)
  5468. {
  5469. var ysip = sip;
  5470. var item = stockData.Data[i];
  5471. var yitem = stockData.Data[i - 1];
  5472. if (position == SAR_LONG)
  5473. {
  5474. if (item.Low < result[i - 1])
  5475. {
  5476. position = SAR_SHORT;
  5477. sip = item.Low;
  5478. af = step / 100;
  5479. nextSar = Math.max(item.High, yitem.High);
  5480. nextSar = Math.max(nextSar, ysip + af * (sip - ysip));
  5481. }
  5482. else
  5483. {
  5484. position = SAR_LONG;
  5485. if (item.High > ysip)
  5486. {
  5487. sip = item.High;
  5488. af = Math.min(af + step / 100, exValue / 100);
  5489. }
  5490. nextSar = Math.min(item.Low, yitem.Low);
  5491. nextSar = Math.min(nextSar, result[i - 1] + af * (sip - result[i - 1]));
  5492. }
  5493. }
  5494. else if (position == SAR_SHORT)
  5495. {
  5496. if (item.High > result[i - 1])
  5497. {
  5498. position = SAR_LONG;
  5499. sip = item.High;
  5500. af = step / 100;
  5501. nextSar = Math.min(item.Low, yitem.Low);
  5502. nextSar = Math.min(nextSar, result[i - 1] + af * (sip - ysip));
  5503. }
  5504. else
  5505. {
  5506. position = SAR_SHORT;
  5507. if (item.Low < ysip)
  5508. {
  5509. sip = item.Low;
  5510. af = Math.min(af + step / 100, exValue / 100);
  5511. }
  5512. nextSar = Math.max(item.High, yitem.High);
  5513. nextSar = Math.max(nextSar, result[i - 1] + af * (sip - result[i - 1]));
  5514. }
  5515. }
  5516. result[i] = nextSar;
  5517. }
  5518. return result;
  5519. }
  5520. /*
  5521. 抛物转向点.
  5522. 用法:
  5523. SARTURN(N,S,M),N为计算周期,S为步长,M为极值,若发生向上转向则返回1,若发生向下转向则返回-1,否则为0
  5524. 其用法与SAR函数相同
  5525. */
  5526. this.SARTURN = function (n, step, exValue)
  5527. {
  5528. var result = [];
  5529. var sar = this.SAR(n, step, exValue);
  5530. var stockData = this.SymbolData.Data;
  5531. var index = 0;
  5532. for (index = 0; index < sar.length; ++index)
  5533. {
  5534. if (this.IsNumber(sar[index])) break;
  5535. }
  5536. var flag = 0;
  5537. if (index < stockData.Data.length) flag = stockData.Data[index].Close > sar[index];
  5538. for (var i = index + 1; i < stockData.Data.length; ++i)
  5539. {
  5540. var item = stockData.Data[i];
  5541. if (item.Close < sar[i] && flag) result[i] = -1;
  5542. else result[i] = (item.Close > sar[i] && !flag) ? 1 : 0;
  5543. flag = item.Close > sar[i];
  5544. }
  5545. return result;
  5546. }
  5547. /*
  5548. 属于未来函数,将当前位置到若干周期前的数据设为1.
  5549. 用法:
  5550. BACKSET(X,N),若X非0,则将当前位置到N周期前的数值设为1.
  5551. 例如:
  5552. BACKSET(CLOSE>OPEN,2)若收阳则将该周期及前一周期数值设为1,否则为0
  5553. */
  5554. this.BACKSET = function (condition, n)
  5555. {
  5556. var result = [];
  5557. if (!condition) return result;
  5558. var dataCount = condition.length;
  5559. if (!this.IsNumber(dataCount) || dataCount <= 0) return result;
  5560. if (Array.isArray(n))
  5561. {
  5562. for(var i=0;i<dataCount;++i) //初始化0
  5563. {
  5564. result[i]=0;
  5565. }
  5566. for(var i=0;i<dataCount;++i)
  5567. {
  5568. var value=condition[i];
  5569. var period=n[i];
  5570. if (this.IsNumber(value) && value && this.IsNumber(period))
  5571. {
  5572. for(var j=i,k=0; j>=0 && k<period; --j,++k)
  5573. {
  5574. result[j]=1;
  5575. }
  5576. }
  5577. }
  5578. }
  5579. else
  5580. {
  5581. for (var i = 0; i < dataCount; ++i) //初始化0
  5582. {
  5583. result[i] = 0;
  5584. }
  5585. for (var pos = 0; pos < dataCount; ++pos)
  5586. {
  5587. if (this.IsNumber(condition[pos])) break;
  5588. }
  5589. if (pos == dataCount) return result;
  5590. var num = Math.min(dataCount - pos, Math.max(n, 1));
  5591. for (var i = dataCount - 1, j = 0; i >= 0; --i)
  5592. {
  5593. var value = condition[i];
  5594. if (this.IsNumber(value) && value)
  5595. {
  5596. for (j = i; j > i - num; --j)
  5597. {
  5598. result[j] = 1;
  5599. }
  5600. }
  5601. }
  5602. if (condition[i])
  5603. {
  5604. for (j = i; j >= pos; --j) result[j] = 1;
  5605. }
  5606. }
  5607. return result;
  5608. }
  5609. //STRCAT(A,B):将两个字符串A,B(非序列化)相加成一个字符串C.
  5610. //用法: STRCAT('多头','开仓')将两个字符串'多头','开仓'相加成一个字符串'多头开仓'
  5611. this.STRCAT = function (str1, str2)
  5612. {
  5613. var result="";
  5614. if (IFrameSplitOperator.IsString(str1)) result+=str1;
  5615. if (IFrameSplitOperator.IsString(str2)) result+=str2;
  5616. return result;
  5617. }
  5618. //STRCAT6(A,B,C,D,E,F):将六个字符串A,B,C,D,E,F(非序列化)相加成一个字符串.
  5619. //用法: STRCAT6('多头','开仓','或者','空头','平仓','')将六个字符串相加成一个字符串
  5620. this.STRCAT6=function(str1, str2,str3, str4,str5, str6)
  5621. {
  5622. var result="";
  5623. if (IFrameSplitOperator.IsString(str1)) result+=str1;
  5624. if (IFrameSplitOperator.IsString(str2)) result+=str2;
  5625. if (IFrameSplitOperator.IsString(str3)) result+=str3;
  5626. if (IFrameSplitOperator.IsString(str4)) result+=str4;
  5627. if (IFrameSplitOperator.IsString(str5)) result+=str5;
  5628. if (IFrameSplitOperator.IsString(str6)) result+=str6;
  5629. return result;
  5630. }
  5631. //VARCAT(A,B):将两个字符串A,B相加成一个字符串C.
  5632. //用法: DRAWTEXT(CLOSE>OPEN,LOW,VARCAT('多头',VAR2STR(C,2))) 将两个字符串相加成一个字符串并按条件显示出来
  5633. this.VARCAT=function(data,data2)
  5634. {
  5635. var result=[];
  5636. if (Array.isArray(data) && Array.isArray(data2))
  5637. {
  5638. var nCount=Math.max(data.length, data2.length);
  5639. var strValue="";
  5640. for(var i=0;i<nCount;++i)
  5641. {
  5642. result[i]=null;
  5643. strValue="";
  5644. if (i<data.length)
  5645. {
  5646. var item=data[i];
  5647. if (this.IsString(item))
  5648. strValue+=item;
  5649. }
  5650. if (i<data2.length)
  5651. {
  5652. var item=data2[i];
  5653. if (this.IsString(item))
  5654. strValue+=item;
  5655. }
  5656. if (strValue!="")
  5657. result[i]=strValue;
  5658. }
  5659. }
  5660. else if (this.IsString(data) && Array.isArray(data2))
  5661. {
  5662. for(var i=0;i<data2.length;++i)
  5663. {
  5664. result[i]=null;
  5665. var item=data2[i];
  5666. if (this.IsString(item))
  5667. {
  5668. result[i]=data+item;
  5669. }
  5670. }
  5671. }
  5672. else if (Array.isArray(data) && this.IsString(data2))
  5673. {
  5674. for(var i=0;i<data.length;++i)
  5675. {
  5676. result[i]=null;
  5677. var item=data[i];
  5678. if (this.IsString(item))
  5679. {
  5680. result[i]=item+data2;
  5681. }
  5682. }
  5683. }
  5684. else if (this.IsString(data) && this.IsString(data2))
  5685. {
  5686. result=data+data2;
  5687. }
  5688. return result;
  5689. }
  5690. //VARCAT6(A,B,C,D,E,F):将六个字符串A,B,C,D,E,F相加成一个字符串.
  5691. //每个数据都进行序列运算,若用于多股选股,建议换用STRCAT6
  5692. //用法: VARCAT6('多头',VAR2STR(C,2),' ',VAR2STR(O,2),' ',VAR2STR(MA(C,5),2))将六个字符串相加成一个字符串
  5693. this.VARCAT6=function(data,data2,data3,data4,data5)
  5694. {
  5695. var aryData=[];
  5696. if (Array.isArray(data) || IFrameSplitOperator.IsString(data)) aryData.push(data);
  5697. if (Array.isArray(data2) || IFrameSplitOperator.IsString(data2)) aryData.push(data2);
  5698. if (Array.isArray(data3) || IFrameSplitOperator.IsString(data3)) aryData.push(data3);
  5699. if (Array.isArray(data4) || IFrameSplitOperator.IsString(data4)) aryData.push(data4);
  5700. if (Array.isArray(data5) || IFrameSplitOperator.IsString(data5)) aryData.push(data5);
  5701. if (!IFrameSplitOperator.IsNonEmptyArray(aryData)) return [];
  5702. if (aryData.length==1) return data;
  5703. var tempData=this.VARCAT(aryData[0], aryData[1]);
  5704. var result=tempData;
  5705. for(var i=2;i<aryData.length;++i)
  5706. {
  5707. result=this.VARCAT(tempData,aryData[i]);
  5708. tempData=result;
  5709. }
  5710. return result;
  5711. }
  5712. //FINDSTR(A,B):在字符串A中查找字符串B,如果找到返回1,否则返回0.
  5713. //用法: FINDSTR('多头开仓','开仓')在字符串'多头开仓'中查找字符串'开仓',返回1
  5714. this.FINDSTR=function(data, data2)
  5715. {
  5716. var result=[];
  5717. var str, str2;
  5718. if (IFrameSplitOperator.IsNumber(data)) str=data.toString();
  5719. else str=data;
  5720. if (IFrameSplitOperator.IsNumber(data2)) str2=data2.toString();
  5721. else str2=data2;
  5722. if (IFrameSplitOperator.IsString(str) && IFrameSplitOperator.IsString(str2))
  5723. {
  5724. if (str.indexOf(str2)>=0) return 1;
  5725. else return 0;
  5726. }
  5727. else if (Array.isArray(data) && IFrameSplitOperator.IsString(str2))
  5728. {
  5729. for(var i=0;i<data.length;++i)
  5730. {
  5731. var item=data[i];
  5732. if (IFrameSplitOperator.IsString(item))
  5733. {
  5734. result[i]=item.indexOf(str2)>=0?1:0;
  5735. }
  5736. else if (IFrameSplitOperator.IsNumber(item))
  5737. {
  5738. str=item.toString();
  5739. result[i]=str.indexOf(str2)>=0?1:0;
  5740. }
  5741. else
  5742. {
  5743. result[i]=0;
  5744. }
  5745. }
  5746. }
  5747. return result;
  5748. }
  5749. this.STRLEN=function(data)
  5750. {
  5751. if (IFrameSplitOperator.IsString(data)) return data.length;
  5752. if (Array.isArray(data))
  5753. {
  5754. var result=[];
  5755. for(var i=0;i<data.length;++i)
  5756. {
  5757. var item=data[i];
  5758. if (IFrameSplitOperator.IsString(item)) result[i]=item.length;
  5759. else result[i]=null;
  5760. }
  5761. return result;
  5762. }
  5763. return null;
  5764. }
  5765. this.STRCMP=function(data, data2)
  5766. {
  5767. if (IFrameSplitOperator.IsString(data) && IFrameSplitOperator.IsString(data2))
  5768. {
  5769. return data==data2? 1:0;
  5770. }
  5771. return null;
  5772. }
  5773. //STRSPACE(A):字符串附带一空格
  5774. this.STRSPACE=function(data)
  5775. {
  5776. var result=[];
  5777. if (Array.isArray(data))
  5778. {
  5779. for(var i=0;i<data.length;++i)
  5780. {
  5781. result[i]=null;
  5782. var item=data[i];
  5783. if (TouchList.IsString(item))
  5784. result[i]=item+' ';
  5785. }
  5786. }
  5787. else
  5788. {
  5789. if (this.IsString(data))
  5790. result=data+" ";
  5791. }
  5792. return result;
  5793. }
  5794. //CON2STR(A,N):取A最后的值(非序列值)转为字符串,小数位数N.
  5795. //用法: CON2STR(FINANCE(20),3)表示取营业收入,以3位小数转为字符串
  5796. this.CON2STR = function (data, n)
  5797. {
  5798. var result = "";
  5799. var dec=0;
  5800. if (IFrameSplitOperator.IsNumber(n)) dec=n;
  5801. if (Array.isArray(data))
  5802. {
  5803. for (var i = data.length - 1; i >= 0; --i)
  5804. {
  5805. var item = data[i];
  5806. if (this.IsNumber(item))
  5807. {
  5808. result = item.toFixed(dec);
  5809. return result;
  5810. }
  5811. }
  5812. }
  5813. else
  5814. {
  5815. if (this.IsNumber(data))
  5816. result = data.toFixed(dec);
  5817. }
  5818. return result;
  5819. }
  5820. //VAR2STR(A,N):取A的每一个值转为字符串,小数位数N.
  5821. //用法: VAR2STR(C,3)表示取收盘价,以3位小数转为字符串
  5822. this.VAR2STR=function(data,n)
  5823. {
  5824. var result=[];
  5825. var dec=0;
  5826. if (IFrameSplitOperator.IsNumber(n)) dec=n;
  5827. if (Array.isArray(data))
  5828. {
  5829. for(var i=0;i<data.length;++i)
  5830. {
  5831. result[i]=null;
  5832. var item=data[i];
  5833. if (this.IsNumber(item))
  5834. result[i]=item.toFixed(dec);
  5835. }
  5836. }
  5837. else
  5838. {
  5839. if (this.IsNumber(data))
  5840. result=data.toFixed(dec);
  5841. }
  5842. return result;
  5843. }
  5844. this.ZTPRICE = function (data, rate)
  5845. {
  5846. if (!this.IsNumber(rate)) return null;
  5847. if (Array.isArray(data))
  5848. {
  5849. var result = [];
  5850. for (var i in data)
  5851. {
  5852. var item = data[i];
  5853. if (this.IsNumber(item)) result[i] = (1 + rate) * item;
  5854. else result[i] = null;
  5855. }
  5856. return result;
  5857. }
  5858. else if (this.IsNumber(data))
  5859. {
  5860. var result = (1 + rate) * data;
  5861. return result;
  5862. }
  5863. }
  5864. this.DTPRICE = function (data, rate)
  5865. {
  5866. if (!this.IsNumber(rate)) return null;
  5867. if (Array.isArray(data))
  5868. {
  5869. var result = [];
  5870. for (var i in data)
  5871. {
  5872. var item = data[i];
  5873. if (this.IsNumber(item)) result[i] = (1 - rate) * item;
  5874. else result[i] = null;
  5875. }
  5876. return result;
  5877. }
  5878. else if (this.IsNumber(data))
  5879. {
  5880. var result = (1 - rate) * data;
  5881. return result;
  5882. }
  5883. }
  5884. /*
  5885. FRACPART(A) 取得小数部分
  5886. 含义:FRACPART(A)返回数值的小数部分
  5887. 阐释:例如FRACPART(12.3)求得0.3,FRACPART(-3.5)求得-0.5
  5888. */
  5889. this.FRACPART = function (data)
  5890. {
  5891. if (Array.isArray(data))
  5892. {
  5893. var result = [];
  5894. var integer = 0;
  5895. for (var i in data)
  5896. {
  5897. var item = data[i];
  5898. if (this.IsNumber(item))
  5899. {
  5900. integer = parseInt(item);
  5901. result[i] = item - integer;
  5902. }
  5903. else result[i] = null;
  5904. }
  5905. return result;
  5906. }
  5907. else if (this.IsNumber(data))
  5908. {
  5909. integer = parseInt(data);
  5910. var result = data - integer;
  5911. return result;
  5912. }
  5913. }
  5914. /*
  5915. 取符号.
  5916. 用法:
  5917. SIGN(X),返回X的符号.当X>0,X=0,X<0分别返回1,0,-1
  5918. */
  5919. this.SIGN=function(data)
  5920. {
  5921. if (Array.isArray(data))
  5922. {
  5923. var result=[];
  5924. for(var i=0;i<data.length;++i)
  5925. {
  5926. var item=data[i];
  5927. result[i]=null;
  5928. if (!IFrameSplitOperator.IsNumber(item)) continue;
  5929. if (item>0) result[i]=1;
  5930. else if (item==0) result[i]=0;
  5931. else result[i]=-1;
  5932. }
  5933. return result;
  5934. }
  5935. else
  5936. {
  5937. if (data>0) return 1;
  5938. else if (data==0) return 0;
  5939. else return -1;
  5940. }
  5941. }
  5942. /*
  5943. 统计连续满足条件的周期数.
  5944. 用法: BARSLASTCOUNT(X),统计连续满足X条件的周期数.
  5945. 例如: BARSLASTCOUNT(CLOSE>OPEN)表示统计连续收阳的周期数
  5946. */
  5947. this.BARSLASTCOUNT=function(data)
  5948. {
  5949. var result=null;
  5950. if (Array.isArray(data))
  5951. {
  5952. result=[];
  5953. if (data.length>0)
  5954. {
  5955. var count=0;
  5956. for(var i=data.length-1;i>=0;--i)
  5957. {
  5958. count=0;
  5959. for(var j=i;j>=0;--j)
  5960. {
  5961. if (data[j]) ++count;
  5962. else break;
  5963. }
  5964. result[i]=count;
  5965. }
  5966. }
  5967. }
  5968. else
  5969. {
  5970. if (data) result=1;
  5971. else result=0;
  5972. }
  5973. return result;
  5974. }
  5975. //取整.
  5976. //用法: INTPART(A)返回沿A绝对值减小方向最接近的整数
  5977. //例如:INTPART(12.3)求得12,INTPART(-3.5)求得-3
  5978. this.INTPART=function(data)
  5979. {
  5980. var result=null;
  5981. if (Array.isArray(data))
  5982. {
  5983. result=[];
  5984. for(var i in data)
  5985. {
  5986. var item=data[i];
  5987. if (this.IsNumber(item)) result[i]=parseInt(item);
  5988. else result[i]=null;
  5989. }
  5990. }
  5991. else if (this.IsNumber(data))
  5992. {
  5993. result=parseInt(data);
  5994. }
  5995. return result;
  5996. }
  5997. //用法:CONST(A),取A最后的值为常量.
  5998. //例如:CONST(INDEXC),表示取大盘现价
  5999. this.CONST=function(data)
  6000. {
  6001. if (Array.isArray(data))
  6002. {
  6003. var count=data.length;
  6004. if (count>0) return data[count-1];
  6005. return null;
  6006. }
  6007. else
  6008. {
  6009. return data;
  6010. }
  6011. }
  6012. //当前值是近多少周期内的最大值.
  6013. //用法: TOPRANGE(X):X是近多少周期内X的最大值
  6014. //例如: TOPRANGE(HIGH)表示当前最高价是近多少周期内最高价的最大值
  6015. this.TOPRANGE=function(data)
  6016. {
  6017. if (this.IsNumber(data)) return 0;
  6018. var result=[];
  6019. if (Array.isArray(data))
  6020. {
  6021. var count=data.length;
  6022. for(var i=count-1; i>=0;--i)
  6023. {
  6024. result[i]=0;
  6025. var item=data[i];
  6026. if (!this.IsNumber(item)) continue;
  6027. var value=0;
  6028. for(var j=i-1;j>=0;--j)
  6029. {
  6030. if (data[j]>item)
  6031. {
  6032. break;
  6033. }
  6034. ++value;
  6035. }
  6036. result[i]=value;
  6037. }
  6038. }
  6039. return result;
  6040. }
  6041. //当前值是近多少周期内的最小值.
  6042. //用法:LOWRANGE(X):X是近多少周期内X的最小值
  6043. //例如:LOWRANGE(LOW)表示当前最低价是近多少周期内最低价的最小值
  6044. this.LOWRANGE=function(data)
  6045. {
  6046. if (this.IsNumber(data)) return 0;
  6047. var result=[];
  6048. if (Array.isArray(data))
  6049. {
  6050. var count=data.length;
  6051. for(var i=count-1; i>=0;--i)
  6052. {
  6053. result[i]=0;
  6054. var item=data[i];
  6055. if (!this.IsNumber(item)) continue;
  6056. var value=0;
  6057. for(var j=i-1;j>=0;--j)
  6058. {
  6059. if (data[j]<item)
  6060. {
  6061. break;
  6062. }
  6063. ++value;
  6064. }
  6065. result[i]=value;
  6066. }
  6067. }
  6068. return result;
  6069. }
  6070. //N周期前的M周期内的第T个最小值.
  6071. //用法:FINDLOW(VAR,N,M,T):VAR在N日前的M天内第T个最低价
  6072. this.FINDLOW=function(data,n,m,t)
  6073. {
  6074. if (this.IsNumber(data)) return data;
  6075. var result=[];
  6076. if (Array.isArray(data))
  6077. {
  6078. var count=data.length;
  6079. for(var i=count-1;i>=0;--i)
  6080. {
  6081. result[i]=null;
  6082. var aryValue=[];
  6083. for(var j=n;j<m;++j)
  6084. {
  6085. var index=i-j;
  6086. if (index<0) break;
  6087. var item=data[index];
  6088. if (this.IsNumber(item)) aryValue.push(item);
  6089. }
  6090. if (aryValue.length>0)
  6091. {
  6092. aryValue.sort(function(a,b) { return a-b;});
  6093. var index=t-1;
  6094. if (index<0) index=0;
  6095. else if (index>=aryValue.length) index=aryValue.length-1;
  6096. result[i]=aryValue[index];
  6097. }
  6098. }
  6099. }
  6100. return result;
  6101. }
  6102. //N周期前的M周期内的第T个最大值.
  6103. //用法:FINDHIGH(VAR,N,M,T):VAR在N日前的M天内第T个最高价
  6104. this.FINDHIGH=function(data,n,m,t)
  6105. {
  6106. if (this.IsNumber(data)) return data;
  6107. var result=[];
  6108. if (Array.isArray(data))
  6109. {
  6110. var count=data.length;
  6111. for(var i=count-1;i>=0;--i)
  6112. {
  6113. result[i]=null;
  6114. var aryValue=[];
  6115. for(var j=n;j<m;++j)
  6116. {
  6117. var index=i-j;
  6118. if (index<0) break;
  6119. var item=data[index];
  6120. if (this.IsNumber(item)) aryValue.push(item);
  6121. }
  6122. if (aryValue.length>0)
  6123. {
  6124. aryValue.sort(function(a,b) { return b-a;});
  6125. var index=t-1;
  6126. if (index<0) index=0;
  6127. else if (index>=aryValue.length) index=aryValue.length-1;
  6128. result[i]=aryValue[index];
  6129. }
  6130. }
  6131. }
  6132. return result;
  6133. }
  6134. //N周期前的M周期内的第T个最大值到当前周期的周期数.
  6135. //用法:FINDHIGHBARS(VAR,N,M,T):VAR在N日前的M天内第T个最高价到当前周期的周期数
  6136. this.FINDHIGHBARS=function(data, n, m, t)
  6137. {
  6138. if (this.IsNumber(data)) return (m-n-t);
  6139. var result=[];
  6140. if (Array.isArray(data))
  6141. {
  6142. var count=data.length;
  6143. for(var i=count-1;i>=0;--i)
  6144. {
  6145. result[i]=null;
  6146. var aryValue=[];
  6147. for(var j=n;j<m;++j)
  6148. {
  6149. var index=i-j;
  6150. if (index<0) break;
  6151. var item=data[index];
  6152. if (this.IsNumber(item)) aryValue.push({ Value:item, Period:j });
  6153. }
  6154. if (aryValue.length>0)
  6155. {
  6156. aryValue.sort(function(a,b) { return b.Value-a.Value;});
  6157. var index=t-1;
  6158. if (index<0) index=0;
  6159. else if (index>=aryValue.length) index=aryValue.length-1;
  6160. result[i]=aryValue[index].Period;
  6161. }
  6162. }
  6163. }
  6164. return result;
  6165. }
  6166. //N周期前的M周期内的第T个最小值到当前周期的周期数.
  6167. //用法:FINDLOWBARS(VAR,N,M,T):VAR在N日前的M天内第T个最低价到当前周期的周期数.
  6168. this.FINDLOWBARS=function(data, n, m, t)
  6169. {
  6170. if (this.IsNumber(data)) return (m-n-t);
  6171. var result=[];
  6172. if (Array.isArray(data))
  6173. {
  6174. var count=data.length;
  6175. for(var i=count-1;i>=0;--i)
  6176. {
  6177. result[i]=null;
  6178. var aryValue=[];
  6179. for(var j=n;j<m;++j)
  6180. {
  6181. var index=i-j;
  6182. if (index<0) break;
  6183. var item=data[index];
  6184. if (this.IsNumber(item)) aryValue.push({ Value:item, Period:j });
  6185. }
  6186. if (aryValue.length>0)
  6187. {
  6188. aryValue.sort(function(a,b) { return a.Value-b.Value;});
  6189. var index=t-1;
  6190. if (index<0) index=0;
  6191. else if (index>=aryValue.length) index=aryValue.length-1;
  6192. result[i]=aryValue[index].Period;
  6193. }
  6194. }
  6195. }
  6196. return result;
  6197. }
  6198. //求高值名次.
  6199. //用法:HOD(X,N):求当前X数据是N周期内的第几个高值,N=0则从第一个有效值开始.
  6200. //例如:HOD(HIGH,20)返回是20日的第几个高价
  6201. this.HOD=function(data, n)
  6202. {
  6203. var result=[];
  6204. if (IFrameSplitOperator.IsNumber(data)) return 1;
  6205. if (Array.isArray(data))
  6206. {
  6207. var count=data.length;
  6208. for(var i=count-1;i>=0;--i)
  6209. {
  6210. var value=data[i];
  6211. if (!IFrameSplitOperator.IsNumber(value)) continue;
  6212. if (Array.isArray(n)) var subCount=parseInt(n[i]);
  6213. else var subCount=parseInt(n);
  6214. if (n<=0) subCount=i;
  6215. var index=1;
  6216. for(var j=i-1, k=1; j>=0 && k<subCount; --j, ++k)
  6217. {
  6218. var item=data[j];
  6219. if (IFrameSplitOperator.IsNumber(item) && item>value) ++index;
  6220. }
  6221. result[i]=index;
  6222. }
  6223. }
  6224. return result;
  6225. }
  6226. //求低值名次.
  6227. //用法:LOD(X,N):求当前X数据是N周期内的第几个低值,N=0则从第一个有效值开始.
  6228. //例如:LOD(LOW,20)返回是20日的第几个低价
  6229. this.LOD=function(data, n)
  6230. {
  6231. var result=[];
  6232. if (IFrameSplitOperator.IsNumber(data)) return 1;
  6233. if (Array.isArray(data))
  6234. {
  6235. var count=data.length;
  6236. for(var i=count-1;i>=0;--i)
  6237. {
  6238. var value=data[i];
  6239. if (!IFrameSplitOperator.IsNumber(value)) continue;
  6240. if (Array.isArray(n)) var subCount=parseInt(n[i]);
  6241. else var subCount=parseInt(n);
  6242. if (n<=0) subCount=i;
  6243. var index=1;
  6244. for(var j=i-1, k=1; j>=0 && k<subCount; --j, ++k)
  6245. {
  6246. var item=data[j];
  6247. if (IFrameSplitOperator.IsNumber(item) && item<value) ++index;
  6248. }
  6249. result[i]=index;
  6250. }
  6251. }
  6252. return result;
  6253. }
  6254. //属于未来函数,下一次条件成立到当前的周期数.
  6255. //用法:BARSNEXT(X):下一次X不为0到现在的天数
  6256. //例如:BARSNEXT(CLOSE/REF(CLOSE,1)>=1.1)表示下一个涨停板到当前的周期数
  6257. this.BARSNEXT=function(data)
  6258. {
  6259. if (!Array.isArray(data)) return 0;
  6260. var result=[];
  6261. for(var i=0;i<data.length;++i)
  6262. {
  6263. result[i]=0;
  6264. for(var j=i, k=0;j<data.length;++j, ++k)
  6265. {
  6266. var item=data[j];
  6267. if (item>0)
  6268. {
  6269. result[i]=k;
  6270. break;
  6271. }
  6272. }
  6273. }
  6274. return result;
  6275. }
  6276. //取随机数.
  6277. //用法:RAND(N),返回一个范围在1-N的随机整数
  6278. this.RAND=function(n)
  6279. {
  6280. if (Array.isArray(n))
  6281. {
  6282. var result=[];
  6283. for(var i in n)
  6284. {
  6285. result[i]=null;
  6286. var item=n[i];
  6287. var value=parseInt(item);
  6288. if (value<=0) continue;
  6289. result[i]=Math.ceil(Math.random()*value);
  6290. }
  6291. return result;
  6292. }
  6293. else
  6294. {
  6295. var value=parseInt(n);
  6296. if (value<=0) return null;
  6297. var stockData= this.SymbolData.Data;
  6298. var count=stockData.Data.length;
  6299. var result=[];
  6300. for(var i=0;i<count;++i)
  6301. {
  6302. result[i]=Math.ceil(Math.random()*value);
  6303. }
  6304. return result;
  6305. }
  6306. }
  6307. //求自适应均线值.
  6308. //用法:AMA(X,A),A为自适应系数,必须小于1.
  6309. //算法:Y=Y'+A*(X-Y').初值为X
  6310. this.AMA=function(data,n)
  6311. {
  6312. var result=[];
  6313. var period;
  6314. if (Array.isArray(n))
  6315. {
  6316. //取最新的一个数据做为自适应系数
  6317. for(var i=data.length-1;i>=0;--i)
  6318. {
  6319. if (this.IsNumber(n[i]))
  6320. {
  6321. period=n[i];
  6322. break;
  6323. }
  6324. }
  6325. }
  6326. else
  6327. {
  6328. period=n;
  6329. }
  6330. if (this.IsNumber(period))
  6331. {
  6332. if (period>1) return result;
  6333. var index=0;
  6334. var value=0;
  6335. for(index;index<data.length;++index)
  6336. {
  6337. result[index]=null;
  6338. if (this.IsNumber(data[index]))
  6339. {
  6340. value=data[index];
  6341. result[index]=value;
  6342. break;
  6343. }
  6344. }
  6345. for(var i=index+1;i<data.length;++i)
  6346. {
  6347. var item=data[i];
  6348. result[i]=result[i-1]+period*(item-result[i-1]);
  6349. }
  6350. }
  6351. return result;
  6352. }
  6353. //返回移动平均
  6354. //用法:TMA(X,A,B),A和B必须小于1,算法 Y=(A*Y'+B*X),其中Y'表示上一周期Y值.初值为X
  6355. this.TMA=function(data, a, b)
  6356. {
  6357. var result=[];
  6358. if (this.IsNumber(a) && a<=1 && this.IsNumber(b) && b<1)
  6359. {
  6360. var bFirstFind=false;
  6361. var proValue; //上一个值
  6362. for(var i in data)
  6363. {
  6364. result[i]=null;
  6365. if (bFirstFind==false)
  6366. {
  6367. var item=data[i];
  6368. if (this.IsNumber(item))
  6369. {
  6370. result[i]=item;
  6371. proValue=result[i];
  6372. bFirstFind=true;
  6373. }
  6374. }
  6375. else
  6376. {
  6377. var item=data[i];
  6378. if (!this.IsNumber(item)) continue;
  6379. result[i]=a*result[i-1]+b*item;
  6380. proValue=result[i];
  6381. }
  6382. }
  6383. }
  6384. return result;
  6385. }
  6386. this.ROUND=function(data)
  6387. {
  6388. if (this.IsNumber(data))
  6389. {
  6390. return Math.round(data);
  6391. }
  6392. var result=[];
  6393. if (Array.isArray(data))
  6394. {
  6395. for(var i in data)
  6396. {
  6397. var item=data[i];
  6398. if (this.IsNumber(item))
  6399. result[i]=Math.round(item);
  6400. else
  6401. result[i]=null;
  6402. }
  6403. }
  6404. return result;
  6405. }
  6406. this.ROUND2=function(data,n)
  6407. {
  6408. var ROUND2_SEED=
  6409. [
  6410. 1,10,100,1000,
  6411. 10000,
  6412. 100000,
  6413. 1000000,
  6414. 10000000,
  6415. 100000000,
  6416. 1000000000,
  6417. 10000000000,
  6418. 100000000000,
  6419. 1000000000000
  6420. ];
  6421. var decimal=0;
  6422. if (this.IsNumber(n)) decimal=parseInt(n);
  6423. if (n<0) decimal=0;
  6424. else if (n>=ROUND2_SEED.length) decimal=ROUND2_SEED.length-1;
  6425. if (this.IsNumber(data))
  6426. {
  6427. return Math.round(data*ROUND2_SEED[decimal])/ROUND2_SEED[decimal];
  6428. }
  6429. var result=[];
  6430. if (Array.isArray(data))
  6431. {
  6432. for(var i in data)
  6433. {
  6434. var item=data[i];
  6435. if (this.IsNumber(item))
  6436. {
  6437. result[i]=Math.round(item*ROUND2_SEED[decimal])/ROUND2_SEED[decimal];
  6438. }
  6439. else
  6440. {
  6441. result[i]=null;
  6442. }
  6443. }
  6444. }
  6445. return result;
  6446. }
  6447. /* 文华
  6448. TRMA(X,N): 求X在N个周期的三角移动平均值。
  6449. 算法:三角移动平均线公式,是采用算数移动平均,并且对第一个移动平均线再一次应用算数移动平均。
  6450. TRMA(X,N) 算法如下
  6451. ma_half= MA(X,N/2)
  6452. trma=MA(ma_half,N/2)
  6453. 注:
  6454. 1、N包含当前k线。
  6455. 2、当N为有效值,但当前的k线数不足N根,函数返回空值。
  6456. 3、N为0或空值的情况下,函数返回空值。
  6457. 例1:
  6458. TRMA5:TRMA(CLOSE,5);//计算5个周期内收盘价的三角移动平均。(N不能被2整除)
  6459. //TRMA(CLOSE,5)=MA(MA(CLOSE,(5+1)/2)),(5+1)/2);
  6460. 例2:
  6461. TRMA10:TRMA(CLOSE,10);// 计算10个周期内收盘价的三角移动平均。(N能被2整除)
  6462. TRMA(CLOSE,10)=MA(MA(CLOSE,10/2),(10/2)+1));
  6463. */
  6464. this.TRMA=function(data,n)
  6465. {
  6466. if (!this.IsNumber(n) || n<=0) return [];
  6467. n=parseInt(n);
  6468. var nFalf=0,nFalf2=0;
  6469. if (n%2==0)
  6470. {
  6471. nFalf=parseInt(n/2);
  6472. nFalf2=nFalf+1;
  6473. }
  6474. else
  6475. {
  6476. nFalf=parseInt((n+1)/2);
  6477. nFalf2=nFalf;
  6478. }
  6479. var maFalf=this.MA(data,nFalf);
  6480. var result=this.MA(maFalf,nFalf2);
  6481. return result;
  6482. }
  6483. //VALUEWHEN(COND,X)
  6484. //当COND条件成立时,取X的当前值,否则取VALUEWHEN的上个值.
  6485. this.VALUEWHEN=function(cond,data)
  6486. {
  6487. if (Array.isArray(cond))
  6488. {
  6489. var result=[];
  6490. if (Array.isArray(data))
  6491. {
  6492. var preValue=null;
  6493. for(var i in cond)
  6494. {
  6495. if (i>=data.length)
  6496. {
  6497. result[i]=preValue;
  6498. continue;
  6499. }
  6500. var item=data[i];
  6501. if (cond[i])
  6502. {
  6503. result[i]=item;
  6504. preValue=item;
  6505. }
  6506. else
  6507. {
  6508. result[i]=preValue;
  6509. }
  6510. }
  6511. }
  6512. else
  6513. {
  6514. var preValue=null;
  6515. for(var i in cond)
  6516. {
  6517. if (cond[i])
  6518. {
  6519. result[i]=data;
  6520. preValue=data;
  6521. }
  6522. else
  6523. {
  6524. result[i]=preValue;
  6525. }
  6526. }
  6527. }
  6528. return result;
  6529. }
  6530. else
  6531. {
  6532. return cond? 1:0;
  6533. }
  6534. }
  6535. /*
  6536. HARMEAN(X,N) 求X在N个周期内的调和平均值。
  6537. 算法举例:HARMEAN(X,5)=1/[(1/X1+1/X2+1/X3+1/X4+1/X5)/5]
  6538. 注:
  6539. 1、N包含当前k线。
  6540. 2、调和平均值与倒数的简单平均值互为倒数。
  6541. 3、当N为有效值,但当前的k线数不足N根,函数返回空值。
  6542. 4、N为0或空值的情况下,函数返回空值。
  6543. 5、X为0或空值的情况下,函数返回空值。
  6544. 6、N可以为变量。
  6545. 例:HM5:=HARMEAN(C,5);//求5周期收盘价的调和平均值。
  6546. */
  6547. this.HARMEAN=function(data, n)
  6548. {
  6549. var result=[];
  6550. if (Array.isArray(data))
  6551. {
  6552. if (Array.isArray(n))
  6553. {
  6554. for(var i=0;i<data.length;++i)
  6555. {
  6556. if (i>=n.length)
  6557. {
  6558. result[i]=null;
  6559. continue;
  6560. }
  6561. var count=parseInt(n[i]);
  6562. if (count<=0 || count>i)
  6563. {
  6564. result[i]=null;
  6565. continue;
  6566. }
  6567. var sum=0;
  6568. for(var j=0;j<count;++j)
  6569. {
  6570. var item=data[i-j];
  6571. if (!this.IsNumber(item) || item==0)
  6572. {
  6573. sum=null;
  6574. break;
  6575. }
  6576. sum+=1/item;
  6577. }
  6578. if (sum==null)
  6579. {
  6580. result[i]=null;
  6581. }
  6582. else
  6583. {
  6584. result[i]=1/(sum/count);
  6585. }
  6586. }
  6587. }
  6588. else if (this.IsNumber(n))
  6589. {
  6590. n=parseInt(n);
  6591. if (n<=0) return result;
  6592. for(var i=0;i<data.length;++i)
  6593. {
  6594. if (n>i)
  6595. {
  6596. result[i]=null;
  6597. continue;
  6598. }
  6599. var sum=0;
  6600. for(var j=0;j<n;++j)
  6601. {
  6602. var item=data[i-j];
  6603. if (!this.IsNumber(item) || item==0)
  6604. {
  6605. sum=null;
  6606. break;
  6607. }
  6608. sum+=1/item;
  6609. }
  6610. if (sum==null)
  6611. {
  6612. result[i]=null;
  6613. }
  6614. else
  6615. {
  6616. result[i]=1/(sum/n);
  6617. }
  6618. }
  6619. }
  6620. }
  6621. return result;
  6622. }
  6623. //指定日期到1990.12.19的天数.
  6624. //用法: DATETODAY(date)
  6625. //DATETODAY(date).返回date到1990.12.19的天数.有效日期为(901219-1341231)
  6626. //例如: DATETODAY(901219)返回0.
  6627. this.DATETODAY=function(data)
  6628. {
  6629. var result=[];
  6630. var startDate=new Date('1990-12-19')
  6631. var startValue=19901219;
  6632. var ONE_DAY=1000 * 60 * 60 * 24
  6633. if (Array.isArray(data))
  6634. {
  6635. for(var i in data)
  6636. {
  6637. result[i]=null;
  6638. var item=data[i];
  6639. if (!this.IsNumber(item)) continue;
  6640. var value=item+19000000;
  6641. if (value<startValue) continue;
  6642. var year=parseInt(value/10000);
  6643. var month=parseInt((value%10000)/100);
  6644. var day=parseInt(value%100);
  6645. var dateItem=new Date(`${year}-${month}-${day}`);
  6646. result[i]=Math.round((dateItem-startDate)/ONE_DAY);
  6647. }
  6648. }
  6649. else if (this.IsNumber(data))
  6650. {
  6651. var value=data+19000000;
  6652. if (value>=startValue)
  6653. {
  6654. var year=parseInt(value/10000);
  6655. var month=parseInt((value%10000)/100);
  6656. var day=parseInt(value%100);
  6657. var dateItem=new Date(`${year}-${month}-${day}`);
  6658. return Math.round((dateItem-dateItem)/ONE_DAY);
  6659. }
  6660. }
  6661. return result;
  6662. }
  6663. //求1990.12.19后第若干天的日期.
  6664. //用法:DAYTODATE(N)
  6665. //DAYTODATE(N).返回1990.12.19后第N天的日期.有效天数为(0-20000)
  6666. //例如:DAYTODATE(0)返回901219.
  6667. this.DAYTODATE=function(data)
  6668. {
  6669. var startDate=new Date('1990-12-19')
  6670. var result=[];
  6671. if (Array.isArray(data))
  6672. {
  6673. for(var i in data)
  6674. {
  6675. result[i]=null;
  6676. var item=data[i];
  6677. if (!this.IsNumber(item)) continue;
  6678. startDate.setDate(startDate.getDate()+item);
  6679. var value=startDate.getFullYear()*10000+(startDate.getMonth()+1)*100+startDate.getDate();
  6680. value-=19000000;
  6681. result[i]=value;
  6682. startDate.setDate(startDate.getDate()-item);
  6683. }
  6684. }
  6685. else if (this.IsNumber(data))
  6686. {
  6687. startDate.setDate(startDate.getDate()+data);
  6688. var value=startDate.getFullYear()*10000+(startDate.getMonth()+1)*100+startDate.getDate();
  6689. value-=19000000;
  6690. return value;
  6691. }
  6692. return result;
  6693. }
  6694. /*
  6695. 求指定时刻距0时有多长时间.
  6696. 用法:
  6697. TIMETOSEC(time)
  6698. TIMETOSEC(time).返回time时刻距0时有多长时间,单位为秒.有效时间为(0-235959)
  6699. 例如:
  6700. TIMETOSEC(93000)返回34200.
  6701. */
  6702. this.TIMETOSEC=function(time)
  6703. {
  6704. var hour=parseInt(time/10000);
  6705. var minute=parseInt((time%10000)/100);
  6706. var sec=time%100;
  6707. var value=hour*60*60+minute*60+sec;
  6708. return value;
  6709. }
  6710. /*
  6711. 求0时后若干秒是什么时间.
  6712. 用法:
  6713. SECTOTIME(N)
  6714. SECTOTIME(N).返回0时后N秒是什么时间.有效秒数为(0-86399)
  6715. 例如:
  6716. SECTOTIME(34200)返回93000.
  6717. */
  6718. this.SECTOTIME=function(data)
  6719. {
  6720. var daySec = 24 * 60 * 60;
  6721. var hourSec= 60 * 60;
  6722. var minuteSec=60;
  6723. var dd = Math.floor(data / daySec);
  6724. var hh = Math.floor((data % daySec) / hourSec);
  6725. var mm = Math.floor((data % hourSec) / minuteSec);
  6726. var ss=data%minuteSec;
  6727. var value=hh*10000+mm*100+ss;
  6728. return value;
  6729. }
  6730. this.MOD=function(data, data2)
  6731. {
  6732. var result=[];
  6733. let isNumber=typeof(data)=='number';
  6734. let isNumber2=typeof(data2)=='number';
  6735. //单数值
  6736. if (isNumber && isNumber2)
  6737. {
  6738. return JSAlgorithm.MOD(data,data2);
  6739. }
  6740. else if (!isNumber && !isNumber2) //都是数组相加
  6741. {
  6742. let count=Math.max(data.length, data2.length);
  6743. for(let i=0;i<count;++i)
  6744. {
  6745. result[i]=null; //初始化
  6746. if (i<data.length && i<data2.length)
  6747. {
  6748. if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=JSAlgorithm.MOD(data[i],data2[i]);
  6749. }
  6750. }
  6751. return result;
  6752. }
  6753. else if (isNumber && !isNumber2) //单数字 数组
  6754. {
  6755. for(var i in data2)
  6756. {
  6757. result[i]=null;
  6758. if (this.IsNumber(data) && this.IsNumber(data2[i])) result[i]=JSAlgorithm.MOD(data,data2[i]);
  6759. }
  6760. return result;
  6761. }
  6762. else if (!isNumber && isNumber2) //数组 单数字
  6763. {
  6764. for(var i in data)
  6765. {
  6766. result[i]=null;
  6767. if (this.IsNumber(data[i]) && this.IsNumber(data2)) result[i]=JSAlgorithm.MOD(data[i],data2);
  6768. }
  6769. return result;
  6770. }
  6771. return result;
  6772. }
  6773. this.POW=function(data, n)
  6774. {
  6775. var result=[];
  6776. if (Array.isArray(data) && Array.isArray(n))
  6777. {
  6778. for(var i=0;i<data.length;++i)
  6779. {
  6780. var value=data[i];
  6781. var value2=n[i];
  6782. if (this.IsNumber(value) && this.IsNumber(value2)) result[i]=Math.pow(value,value2);
  6783. else result[i]=null;
  6784. }
  6785. }
  6786. else if (this.IsNumber(data) && Array.isArray(n))
  6787. {
  6788. for(var i=0;i<n.length;++i)
  6789. {
  6790. var item=n[i];
  6791. if (this.IsNumber(item)) result[i]=Math.pow(data,item);
  6792. else result[i]=null;
  6793. }
  6794. }
  6795. else if (this.IsNumber(data) && this.IsNumber(n))
  6796. {
  6797. return Math.pow(data,n);
  6798. }
  6799. else if (Array.isArray(data) && this.IsNumber(n))
  6800. {
  6801. for(var i=0; i<data.length;++i)
  6802. {
  6803. var item=data[i];
  6804. if (this.IsNumber(item)) result[i]=Math.pow(item,n);
  6805. else result[i]=null;
  6806. }
  6807. }
  6808. return result;
  6809. }
  6810. this.CEILING=function(data)
  6811. {
  6812. let isNumber=typeof(data)=='number';
  6813. if (isNumber) return parseInt(data);
  6814. var result=[];
  6815. for(var i in data)
  6816. {
  6817. var item=data[i];
  6818. if (this.IsNumber(item)) result[i]=parseInt(item);
  6819. else result[i]=null;
  6820. }
  6821. return result;
  6822. }
  6823. this.FLOOR=function(data)
  6824. {
  6825. let isNumber=typeof(data)=='number';
  6826. if (isNumber) return parseInt((data-1));
  6827. var result=[];
  6828. for(var i in data)
  6829. {
  6830. var item=data[i];
  6831. if (this.IsNumber(item)) result[i]=parseInt((item-1));
  6832. else result[i]=null;
  6833. }
  6834. return result;
  6835. }
  6836. this.PWINNER=function(n, data, node)
  6837. {
  6838. var result=[];
  6839. return result;
  6840. }
  6841. //用法:ANY(CLOSE>OPEN,10),表示前10日内存在着阳线
  6842. this.ANY=function(data, n)
  6843. {
  6844. if (n<=0) n=1;
  6845. var result=[];
  6846. if (Array.isArray(data))
  6847. {
  6848. if (n>=data.length) return 0;
  6849. for(var i=n, j=0;i<data.length;++i)
  6850. {
  6851. var value=0;
  6852. for(j=0;j<n;++j)
  6853. {
  6854. var item=data[i-j];
  6855. if (item>0)
  6856. {
  6857. value=1;
  6858. break;
  6859. }
  6860. }
  6861. result[i]=value;
  6862. }
  6863. return result;
  6864. }
  6865. else if (IFrameSplitOperator.IsNumber(data))
  6866. {
  6867. if (data<=0) return 0;
  6868. if (n>=this.SymbolData.Data.Data.length) return 0;
  6869. for(var i=n; i<this.SymbolData.Data.Data.length; ++i)
  6870. {
  6871. result[i]=1;
  6872. }
  6873. return result;
  6874. }
  6875. else
  6876. {
  6877. return 0;
  6878. }
  6879. }
  6880. //用法:ALL(CLOSE>OPEN,10),表示前10日内一直阳线
  6881. this.ALL=function(data, n)
  6882. {
  6883. if (n<=0) n=1;
  6884. var result=[];
  6885. if (Array.isArray(data))
  6886. {
  6887. if (n>=data.length) return 0;
  6888. for(var i=n, j=0;i<data.length;++i)
  6889. {
  6890. var value=1;
  6891. for(j=0;j<n;++j)
  6892. {
  6893. var item=data[i-j];
  6894. if (!(item>0))
  6895. {
  6896. value=0;
  6897. break;
  6898. }
  6899. }
  6900. result[i]=value;
  6901. }
  6902. return result;
  6903. }
  6904. else if (IFrameSplitOperator.IsNumber(data))
  6905. {
  6906. if (data<=0) return 0;
  6907. if (n>=this.SymbolData.Data.Data.length) return 0;
  6908. for(var i=n; i<this.SymbolData.Data.Data.length; ++i)
  6909. {
  6910. result[i]=1;
  6911. }
  6912. return result;
  6913. }
  6914. else
  6915. {
  6916. return 0;
  6917. }
  6918. }
  6919. /*
  6920. TESTSKIP(A):满足A则直接返回.
  6921. 用法:
  6922. TESTSKIP(A)
  6923. 表示如果满足条件A则该公式直接返回,不再计算接下来的表达式 注意:A为非序列数据,只取最后一个数据
  6924. */
  6925. this.TESTSKIP=function(data, node)
  6926. {
  6927. if (Array.isArray(data))
  6928. {
  6929. if (data.length<=0) return false;
  6930. var item=data[data.length-1];
  6931. if (!item) return false;
  6932. return true;
  6933. }
  6934. else if (IFrameSplitOperator.IsNumber(data))
  6935. {
  6936. if (data<=0) return false;
  6937. return true;
  6938. }
  6939. else
  6940. {
  6941. if (!data) return false;
  6942. return true;
  6943. }
  6944. }
  6945. /*根据条件执行不同的语句,可中止(根据序列的最后一个数值来判断).
  6946. 用法:
  6947. IFC(X,A,B)若X不为0则执行A,否则执行B.IFC与IF函数的区别:根据X的值来选择性执行A、B表达式.
  6948. 例如:
  6949. IFC(CLOSE>OPEN,HIGH,TESTSKIP(1));L;表示当日收阳则返回最高值,并执行下一句"L;",否则退出公式计算
  6950. */
  6951. this.IFC=function(data)
  6952. {
  6953. if (Array.isArray(data))
  6954. {
  6955. var item=data[data.length-1];
  6956. if (IFrameSplitOperator.IsNumber(item)) return item>0;
  6957. return false;
  6958. }
  6959. else if (IFrameSplitOperator.IsNumber(data))
  6960. {
  6961. return data>0;
  6962. }
  6963. else
  6964. {
  6965. return false;
  6966. }
  6967. }
  6968. /*
  6969. 有效数据右对齐.
  6970. 用法:
  6971. ALIGNRIGHT(X)有效数据向右移动,左边空出来的周期填充无效值
  6972. 例如:TC:=IF(CURRBARSCOUNT=2 || CURRBARSCOUNT=5,DRAWNULL,C);XC:ALIGNRIGHT(TC);删除了两天的收盘价,并将剩余数据右移
  6973. */
  6974. this.ALIGNRIGHT=function(data)
  6975. {
  6976. if (Array.isArray(data))
  6977. {
  6978. var result=[];
  6979. var index=data.length-1;
  6980. for(var i=data.length-1;i>=0;--i)
  6981. {
  6982. var item=data[i];
  6983. if (IFrameSplitOperator.IsNumber(item) || IFrameSplitOperator.IsString(item))
  6984. {
  6985. result[index]=item;
  6986. --index;
  6987. }
  6988. }
  6989. for(var i=index;i>=0;--i)
  6990. {
  6991. result[i]=null;
  6992. }
  6993. return result;
  6994. }
  6995. else
  6996. {
  6997. return data;
  6998. }
  6999. }
  7000. //格式化字符串 "{0}-{1}", C, O;
  7001. this.STRFORMAT=function(strFormat,args,node)
  7002. {
  7003. var aryParam=strFormat.match(/{\d+}/g);
  7004. if (!IFrameSplitOperator.IsNonEmptyArray(aryParam)) return null;
  7005. var mapParam=new Map(); //key=index, value={Text}
  7006. var maxIndex=-1;
  7007. for(var i=0;i<aryParam.length;++i)
  7008. {
  7009. var item=aryParam[i];
  7010. if (item.length<3) continue;
  7011. var value=item.slice(1, item.length-1);
  7012. var index=parseInt(value);
  7013. var paramItem={ Src:item, Index:index, Text:null};
  7014. if (maxIndex<index) maxIndex=index;
  7015. mapParam.set(index, paramItem);
  7016. }
  7017. var isArray=false; //是否输出数组字符串
  7018. var maxCount=0;
  7019. for(var i=1;i<args.length;++i)
  7020. {
  7021. var item=args[i];
  7022. if (Array.isArray(item))
  7023. {
  7024. isArray=true;
  7025. if (maxCount<item.length) maxCount=item.length;
  7026. }
  7027. }
  7028. if (isArray)
  7029. {
  7030. var result=[];
  7031. for(var i=0;i<maxCount;++i)
  7032. {
  7033. var strItem=strFormat;
  7034. for(var item of mapParam)
  7035. {
  7036. var paramInfo=item[1];
  7037. var paramItem=args[paramInfo.Index+1];
  7038. var text="null";
  7039. if (paramItem)
  7040. {
  7041. if (Array.isArray(paramItem))
  7042. {
  7043. var value=paramItem[i];
  7044. if (value) text=`${value}`;
  7045. }
  7046. else
  7047. {
  7048. text=`${paramItem}`;
  7049. }
  7050. }
  7051. strItem=strItem.replace(paramInfo.Src, text);
  7052. }
  7053. result[i]=strItem;
  7054. }
  7055. return result;
  7056. }
  7057. else
  7058. {
  7059. var result=strFormat;
  7060. for(var item of mapParam)
  7061. {
  7062. var paramInfo=item[1];
  7063. var paramItem=args[paramInfo.Index+1];
  7064. var text="null";
  7065. if (paramItem)
  7066. {
  7067. text=`${paramItem}`;
  7068. }
  7069. result=result.replace(paramInfo.Src, text);
  7070. }
  7071. return result;
  7072. }
  7073. }
  7074. //函数调用
  7075. this.CallFunction=function(name,args,node)
  7076. {
  7077. switch(name)
  7078. {
  7079. case 'MAX':
  7080. case "MAX6":
  7081. return this.MAX(args,node);
  7082. case 'MIN':
  7083. case "MIN6":
  7084. return this.MIN(args,node);
  7085. case 'REF':
  7086. return this.REF(args[0], args[1]);
  7087. case "REFV":
  7088. return this.REFV(args[0], args[1]);
  7089. case 'REFX':
  7090. return this.REFX(args[0], args[1]);
  7091. case "REFXV":
  7092. return this.REFXV(args[0], args[1]);
  7093. case "REFX1": //文华函数
  7094. return this.REFX(args[0], args[1]);
  7095. case 'ABS':
  7096. return this.ABS(args[0]);
  7097. case 'MA':
  7098. return this.MA(args[0], args[1]);
  7099. case "EMA":
  7100. return this.EMA(args[0], args[1]);
  7101. case "SMA":
  7102. return this.SMA(args[0], args[1],args[2]);
  7103. case "DMA":
  7104. return this.DMA(args[0], args[1]);
  7105. case "XMA":
  7106. return this.XMA(args[0], args[1]);
  7107. case 'EXPMA':
  7108. return this.EXPMA(args[0], args[1]);
  7109. case 'EXPMEMA':
  7110. return this.EXPMEMA(args[0], args[1]);
  7111. case 'COUNT':
  7112. return this.COUNT(args[0], args[1]);
  7113. case 'LLV':
  7114. return this.LLV(args[0], args[1]);
  7115. case "LV":
  7116. return this.LV(args[0], args[1]);
  7117. case 'LLVBARS':
  7118. return this.LLVBARS(args[0], args[1]);
  7119. case 'HHV':
  7120. return this.HHV(args[0], args[1]);
  7121. case "HV":
  7122. return this.HV(args[0], args[1]);
  7123. case 'HHVBARS':
  7124. return this.HHVBARS(args[0], args[1]);
  7125. case 'MULAR':
  7126. return this.MULAR(args[0], args[1]);
  7127. case 'CROSS':
  7128. return this.CROSS(args[0], args[1]);
  7129. case "CROSSDOWN":
  7130. return this.CROSSDOWN(args[0], args[1]);
  7131. case 'LONGCROSS':
  7132. return this.LONGCROSS(args[0], args[1], args[2]);
  7133. case 'AVEDEV':
  7134. return this.AVEDEV(args[0], args[1]);
  7135. case 'STD':
  7136. return this.STD(args[0], args[1]);
  7137. case "STDDEV":
  7138. return this.STDDEV(args[0], args[1]);
  7139. case 'IF':
  7140. case 'IFF':
  7141. case "IFELSE":
  7142. return this.IF(args[0], args[1], args[2]);
  7143. case 'IFN':
  7144. return this.IFN(args[0], args[1], args[2]);
  7145. case 'NOT':
  7146. return this.NOT(args[0]);
  7147. case 'SUM':
  7148. return this.SUM(args[0], args[1]);
  7149. case 'RANGE':
  7150. return this.RANGE(args[0],args[1],args[2]);
  7151. case 'EXIST':
  7152. return this.EXIST(args[0],args[1]);
  7153. case 'EXISTR':
  7154. return this.EXISTR(args[0], args[1], args[2]);
  7155. case "ISVALID":
  7156. return this.ISVALID(args[0]);
  7157. case 'FILTER':
  7158. return this.FILTER(args[0], args[1]);
  7159. case 'TFILTER':
  7160. return this.TFILTER(args[0],args[1],args[2]);
  7161. case 'SLOPE':
  7162. return this.SLOPE(args[0],args[1]);
  7163. case 'BARSLAST':
  7164. return this.BARSLAST(args[0]);
  7165. case 'BARSCOUNT':
  7166. return this.BARSCOUNT(args[0]);
  7167. case 'BARSSINCEN':
  7168. return this.BARSSINCEN(args[0], args[1]);
  7169. case 'BARSSINCE':
  7170. return this.BARSSINCE(args[0]);
  7171. case 'LAST':
  7172. return this.LAST(args[0], args[1], args[2]);
  7173. case 'EVERY':
  7174. return this.EVERY(args[0], args[1]);
  7175. case 'ZIG':
  7176. return this.ZIG(args[0], args[1]);
  7177. case 'TROUGHBARS':
  7178. return this.TROUGHBARS(args[0], args[1], args[2]);
  7179. case "TROUGH":
  7180. return this.TROUGH(args[0],args[1],args[2]);
  7181. case 'PEAKBARS':
  7182. return this.PEAKBARS(args[0], args[1], args[2]);
  7183. case 'PEAK':
  7184. return this.PEAK(args[0],args[1],args[2]);
  7185. case 'COST':
  7186. return this.COST(args[0], node);
  7187. case 'WINNER':
  7188. return this.WINNER(args[0], node);
  7189. case "PWINNER":
  7190. return this.PWINNER(args[0],args[1],node);
  7191. case 'UPNDAY':
  7192. return this.UPNDAY(args[0], args[1]);
  7193. case 'DOWNNDAY':
  7194. return this.DOWNNDAY(args[0], args[1]);
  7195. case 'NDAY':
  7196. return this.NDAY(args[0], args[1], args[2]);
  7197. case 'DEVSQ':
  7198. return this.DEVSQ(args[0], args[1]);
  7199. case 'FORCAST':
  7200. return this.FORCAST(args[0], args[1]);
  7201. case 'STDP':
  7202. return this.STDP(args[0], args[1]);
  7203. case 'VAR':
  7204. return this.VAR(args[0], args[1]);
  7205. case 'VARP':
  7206. return this.VARP(args[0], args[1]);
  7207. case 'RELATE':
  7208. return this.RELATE(args[0], args[1], args[2]);
  7209. case 'COVAR':
  7210. return this.COVAR(args[0], args[1], args[2]);
  7211. case 'BETA':
  7212. return this.BETA(args[0]);
  7213. case 'BETA2':
  7214. return this.BETA2(args[0], args[1], args[2]);
  7215. case 'WMA':
  7216. return this.WMA(args[0], args[1]);
  7217. case 'MEMA':
  7218. return this.MEMA(args[0], args[1]);
  7219. case 'SUMBARS':
  7220. return this.SUMBARS(args[0], args[1]);
  7221. case 'REVERSE':
  7222. return this.REVERSE(args[0]);
  7223. case 'SAR':
  7224. return this.SAR(args[0], args[1], args[2]);
  7225. case 'SARTURN':
  7226. return this.SARTURN(args[0], args[1], args[2]);
  7227. case 'BACKSET':
  7228. return this.BACKSET(args[0], args[1]);
  7229. case 'STRCAT':
  7230. return this.STRCAT(args[0], args[1]);
  7231. case "STRCAT6":
  7232. return this.STRCAT6(args[0], args[1],args[2], args[3],args[4], args[5]);
  7233. case "VARCAT":
  7234. return this.VARCAT(args[0], args[1]);
  7235. case "VARCAT6":
  7236. return this.VARCAT6(args[0], args[1],args[2], args[3],args[4], args[5]);
  7237. case "VAR2STR":
  7238. return this.VAR2STR(args[0], args[1]);
  7239. case 'CON2STR':
  7240. return this.CON2STR(args[0], args[1]);
  7241. case "STRSPACE":
  7242. return this.STRSPACE(args[0]);
  7243. case 'FINDSTR':
  7244. return this.FINDSTR(args[0], args[1]);
  7245. case "STRCMP":
  7246. return this.STRCMP(args[0], args[1]);
  7247. case "STRLEN":
  7248. return this.STRLEN(args[0]);
  7249. case "STRFORMAT":
  7250. return this.STRFORMAT(args[0], args, node);
  7251. case 'DTPRICE':
  7252. return this.DTPRICE(args[0], args[1]);
  7253. case 'ZTPRICE':
  7254. return this.ZTPRICE(args[0], args[1]);
  7255. case 'FRACPART':
  7256. return this.FRACPART(args[0]);
  7257. case "SIGN":
  7258. return this.SIGN(args[0]);
  7259. case 'BARSLASTCOUNT':
  7260. return this.BARSLASTCOUNT(args[0]);
  7261. case 'INTPART':
  7262. return this.INTPART(args[0]);
  7263. case "CONST":
  7264. return this.CONST(args[0]);
  7265. case "TOPRANGE":
  7266. return this.TOPRANGE(args[0]);
  7267. case "LOWRANGE":
  7268. return this.LOWRANGE(args[0]);
  7269. case "FINDLOW":
  7270. return this.FINDLOW(args[0],args[1],args[2],args[3]);
  7271. case "FINDLOWBARS":
  7272. return this.FINDLOWBARS(args[0],args[1],args[2],args[3]);
  7273. case "FINDHIGH":
  7274. return this.FINDHIGH(args[0],args[1],args[2],args[3]);
  7275. case "FINDHIGHBARS":
  7276. return this.FINDHIGHBARS(args[0],args[1],args[2],args[3]);
  7277. case "BARSNEXT":
  7278. return this.BARSNEXT(args[0]);
  7279. case "HOD":
  7280. return this.HOD(args[0], args[1]);
  7281. case "LOD":
  7282. return this.LOD(args[0], args[1]);
  7283. case "AMA":
  7284. return this.AMA(args[0], args[1]);
  7285. case "TMA":
  7286. return this.TMA(args[0],args[1],args[2]);
  7287. case "ROUND":
  7288. return this.ROUND(args[0]);
  7289. case "ROUND2":
  7290. return this.ROUND2(args[0],args[1]);
  7291. case "TRMA":
  7292. return this.TRMA(args[0],args[1]);
  7293. case "VALUEWHEN":
  7294. return this.VALUEWHEN(args[0],args[1]);
  7295. case "HARMEAN":
  7296. return this.HARMEAN(args[0],args[1]);
  7297. case "DATETODAY":
  7298. return this.DATETODAY(args[0]);
  7299. case "DAYTODATE":
  7300. return this.DAYTODATE(args[0]);
  7301. case "TIMETOSEC":
  7302. return this.TIMETOSEC(args[0]);
  7303. case "SECTOTIME":
  7304. return this.SECTOTIME(args[0]);
  7305. case 'MOD':
  7306. return this.MOD(args[0],args[1]);
  7307. case 'POW':
  7308. return this.POW(args[0],args[1]);
  7309. case 'CEILING':
  7310. return this.CEILING(args[0]);
  7311. case 'FLOOR':
  7312. return this.FLOOR(args[0]);
  7313. case "BETWEEN":
  7314. return this.BETWEEN(args[0], args[1],args[2]);
  7315. case "ANY":
  7316. return this.ANY(args[0],args[1]);
  7317. case "ALL":
  7318. return this.ALL(args[0],args[1]);
  7319. case "ALIGNRIGHT":
  7320. return this.ALIGNRIGHT(args[0]);
  7321. //三角函数
  7322. case 'ATAN':
  7323. return this.Trigonometric(args[0], Math.atan);
  7324. case 'ACOS':
  7325. return this.ACOS(args[0]);
  7326. case 'ASIN':
  7327. return this.ASIN(args[0]);
  7328. case 'COS':
  7329. return this.Trigonometric(args[0], Math.cos);
  7330. case 'SIN':
  7331. return this.Trigonometric(args[0], Math.sin);
  7332. case 'TAN':
  7333. return this.Trigonometric(args[0], Math.tan);
  7334. case 'LN':
  7335. return this.Trigonometric(args[0], Math.log);
  7336. case 'LOG':
  7337. return this.Trigonometric(args[0], Math.log10);
  7338. case 'EXP':
  7339. return this.Trigonometric(args[0], Math.exp);
  7340. case 'SQRT':
  7341. return this.Trigonometric(args[0], Math.sqrt);
  7342. default:
  7343. this.ThrowUnexpectedNode(node,'函数'+name+'不存在');
  7344. }
  7345. }
  7346. //调用自定义函数 返回数据格式{Out:输出数据, Draw:绘图数据(可选)}
  7347. this.CallCustomFunction=function(name, args, symbolData, node)
  7348. {
  7349. var functionInfo=g_JSComplierResource.CustomFunction.Data.get(name);
  7350. var dwonloadData=symbolData.GetStockCacheData({ CustomName:name, Node:node });
  7351. if (!functionInfo.Invoke)
  7352. return { Out: dwonloadData }
  7353. JSConsole.Complier.Log('[JSAlgorithm::CallCustomFunction] call custom function functionInfo=',functionInfo);
  7354. var self=this;
  7355. var obj=
  7356. {
  7357. Name:name,
  7358. Args:args,
  7359. Symbol:symbolData.Symbol, Period:symbolData.Period, Right:symbolData.Right,
  7360. KData:symbolData.Data, //K线数据
  7361. DownloadData:dwonloadData,
  7362. ThrowError:function(error)
  7363. {
  7364. self.ThrowUnexpectedNode(node, error);
  7365. }
  7366. };
  7367. return functionInfo.Invoke(obj);
  7368. }
  7369. this.ThrowUnexpectedNode=function(node,message)
  7370. {
  7371. let marker=node.Marker;
  7372. let msg=message || "执行异常";
  7373. return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
  7374. }
  7375. }
  7376. //是否有是有效的数字
  7377. JSAlgorithm.prototype.IsNumber=function(value)
  7378. {
  7379. if (value==null) return false;
  7380. if (isNaN(value)) return false;
  7381. return true;
  7382. }
  7383. //是否是整形
  7384. JSAlgorithm.prototype.IsInteger=function(x)
  7385. {
  7386. return (typeof x === 'number') && (x % 1 === 0);
  7387. }
  7388. //是否有是有效的除数
  7389. JSAlgorithm.prototype.IsDivideNumber=function(value)
  7390. {
  7391. if (value==null) return false;
  7392. if (isNaN(value)) return false;
  7393. if (value==0) return false;
  7394. return true;
  7395. }
  7396. //取模
  7397. JSAlgorithm.MOD=function(number,divisor)
  7398. {
  7399. if( (number < 0 && divisor < 0) || (number >=0 && divisor >= 0)) //同号
  7400. {
  7401. if(parseInt(number) == number && parseInt(divisor) == divisor) //全为整数
  7402. {
  7403. return number%divisor;
  7404. }
  7405. else //被除数-(整商×除数)之后在第一位小数位进行四舍五入
  7406. {
  7407. var value = parseFloat((number - (Math.floor(number/divisor) * divisor)).toFixed(1));
  7408. return value;
  7409. }
  7410. }
  7411. else //异号
  7412. {
  7413. var absNumber = Math.abs(number); //绝对值
  7414. var absDivisor = Math.abs(divisor); //绝对值
  7415. var value = Math.abs(Math.abs(divisor) * (Math.floor(absNumber/absDivisor) + 1) - Math.abs(number));
  7416. if(divisor < 0) value = -value
  7417. return value;
  7418. }
  7419. }
  7420. //是否是字符串
  7421. JSAlgorithm.prototype.IsString=function(value)
  7422. {
  7423. if (value && typeof(value)=='string') return true;
  7424. return false;
  7425. }
  7426. /*
  7427. 绘图函数
  7428. */
  7429. function JSDraw(errorHandler, symbolData)
  7430. {
  7431. this.ErrorHandler=errorHandler;
  7432. this.SymbolData = symbolData;
  7433. this.DRAWTEXT=function(condition,price,text)
  7434. {
  7435. let drawData=[];
  7436. let result={DrawData:drawData, DrawType:'DRAWTEXT',Text:text};
  7437. if (Array.isArray(condition))
  7438. {
  7439. var IsNumber=this.IsNumber(price);
  7440. var isFixedPosition=false;
  7441. if (price==="TOP"|| price==="BOTTOM")
  7442. {
  7443. result.FixedPosition=price;
  7444. isFixedPosition=true;
  7445. }
  7446. for(var i=0; i<condition.length; ++i)
  7447. {
  7448. drawData[i]=null;
  7449. if (condition[i]!==1) continue;
  7450. if (IsNumber || isFixedPosition)
  7451. {
  7452. drawData[i]=price;
  7453. }
  7454. else
  7455. {
  7456. if (this.IsNumber(price[i])) drawData[i]=price[i];
  7457. }
  7458. }
  7459. }
  7460. else if (this.IsNumber(condition) && condition===1)
  7461. {
  7462. var IsNumber=this.IsNumber(price);
  7463. var isFixedPosition=false;
  7464. if (price==="TOP"|| price==="BOTTOM")
  7465. {
  7466. result.FixedPosition=price;
  7467. isFixedPosition=true;
  7468. }
  7469. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  7470. {
  7471. if (IsNumber || isFixedPosition)
  7472. {
  7473. drawData[i]=price;
  7474. }
  7475. else
  7476. {
  7477. if (this.IsNumber(price[i])) drawData[i]=price[i];
  7478. }
  7479. }
  7480. }
  7481. return result;
  7482. }
  7483. //1.固定位置显示文字;2.在指标排序中显示字符串栏目.
  7484. //用法:DRAWTEXT_FIX(COND,X,Y,TYPE,TEXT),COND中一般需要加ISLASTBAR,当COND条件满足时,在当前指标窗口内(X,Y)位置书写文字TEXT,X,Y为书写点在窗口中相对于左上角的百分比,TYPE:0为左对齐,1为右对齐,2=居中.
  7485. //例如:DRAWTEXT_FIX(ISLASTBAR AND CLOSE/OPEN>1.08,0.5,0.5,0,'大阳线')表示最后一个交易日实体阳线大于8%时在窗口中间位置显示'大阳线'字样.若文字中含有&,则进行折行.最多只能显示250个字符
  7486. this.DRAWTEXT_FIX=function(condition,x,y,type,text)
  7487. {
  7488. var drawData={ Value:[], Text:[] };
  7489. var result={DrawData:drawData, DrawType:'DRAWTEXT_FIX', Text:null, Position:{ X:x, Y:y, Type:type } };
  7490. if (Array.isArray(condition))
  7491. {
  7492. for(var i=0; i<condition.length; ++i)
  7493. {
  7494. drawData.Text[i]=null;
  7495. drawData.Value[i]=0;
  7496. if (condition[i]!==1) continue;
  7497. drawData.Value[i]=1;
  7498. drawData.Text[i]=text;
  7499. }
  7500. }
  7501. else
  7502. {
  7503. if(condition===1)
  7504. {
  7505. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  7506. {
  7507. drawData.Text[i]=text;
  7508. drawData.Value[i]=1;
  7509. }
  7510. }
  7511. }
  7512. return result;
  7513. }
  7514. /*
  7515. 固定位置显示数字.
  7516. 用法: DRAWNUMBER_FIX(COND,X,Y,TYPE,NUMBER,decimal=2),当COND条件满足时,在当前指标窗口内(X,Y)位置书写数字NUMBER,X,Y为书写点在窗口中相对于左上角的百分比,TYPE:0为左对齐,1为右对齐 2=居中
  7517. 例如: DRAWNUMBER_FIX(CURRBARSCOUNT=1 AND CLOSE/OPEN>1.08,0.5,0.5,0,C)表示最后一个交易日实体阳线大于8%时在窗口中间位置显示收盘价.
  7518. */
  7519. this.DRAWNUMBER_FIX=function(condition,x,y,align,data, decimal=2)
  7520. {
  7521. var drawData={ Value:[], Text:[], };
  7522. var result={ DrawData:drawData, DrawType:'DRAWNUMBER_FIX', Position:{ X:x, Y:y, Type:align } };
  7523. var isNumber=IFrameSplitOperator.IsNumber(data);
  7524. if (Array.isArray(condition))
  7525. {
  7526. for(var i=0; i<condition.length; ++i)
  7527. {
  7528. drawData.Text[i]=null;
  7529. drawData.Value[i]=null;
  7530. if (condition[i]!==1) continue;
  7531. if (isNumber)
  7532. {
  7533. drawData.Text[i]=data.toFixed(decimal);
  7534. drawData.Value[i]=data;
  7535. }
  7536. else
  7537. {
  7538. if (i>=data.length || !IFrameSplitOperator.IsNumber(data[i])) continue;
  7539. var item=data[i];
  7540. drawData.Text[i]=item.toFixed(decimal);
  7541. drawData.Value[i]=item;
  7542. }
  7543. }
  7544. }
  7545. else
  7546. {
  7547. if(condition!==1)
  7548. {
  7549. }
  7550. else
  7551. {
  7552. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  7553. {
  7554. if (isNumber)
  7555. {
  7556. drawData.Text[i]=data.toFixed(decimal);
  7557. drawData.Value[i]=data;
  7558. }
  7559. else
  7560. {
  7561. if (i>=data.length || !IFrameSplitOperator.IsNumber(data[i])) continue;
  7562. var item=data[i];
  7563. drawData.Text[i]=item.toFixed(decimal);
  7564. drawData.Value[i]=item;
  7565. }
  7566. }
  7567. }
  7568. }
  7569. return result;
  7570. }
  7571. //direction 文字Y轴位置 0=middle 1=价格的顶部 2=价格的底部
  7572. //offset 文字Y轴偏移
  7573. this.SUPERDRAWTEXT = function (condition, price, text, direction, offset)
  7574. {
  7575. let drawData = [];
  7576. let result = { DrawData: drawData, DrawType: 'SUPERDRAWTEXT', Text: text, YOffset: offset, Direction: direction, TextAlign: 'center' };
  7577. if (condition.length <= 0) return result;
  7578. var IsNumber = typeof (price) == "number";
  7579. for (var i in condition)
  7580. {
  7581. drawData[i] = null;
  7582. if (isNaN(condition[i]) || !condition[i]) continue;
  7583. if (IsNumber)
  7584. {
  7585. drawData[i] = price;
  7586. }
  7587. else
  7588. {
  7589. if (this.IsNumber(price[i])) drawData[i] = price[i];
  7590. }
  7591. }
  7592. return result;
  7593. }
  7594. this.STICKLINE=function(condition,data,data2,width,type)
  7595. {
  7596. let drawData=[];
  7597. let result={DrawData:drawData, DrawType:'STICKLINE',Width:width, Type:type};
  7598. var IsNumber=typeof(data)=="number";
  7599. var IsNumber2=typeof(data2)=="number";
  7600. if (Array.isArray(condition)) //数组
  7601. {
  7602. if(condition.length<=0) return result;
  7603. for(var i in condition)
  7604. {
  7605. drawData[i]=null;
  7606. if (isNaN(condition[i]) || !condition[i]) continue;
  7607. if (IsNumber && IsNumber2)
  7608. {
  7609. drawData[i]={Value:data,Value2:data2};
  7610. }
  7611. else if (IsNumber && !IsNumber2)
  7612. {
  7613. if (isNaN(data2[i])) continue;
  7614. drawData[i]={Value:data,Value2:data2[i]};
  7615. }
  7616. else if (!IsNumber && IsNumber2)
  7617. {
  7618. if (isNaN(data[i])) continue;
  7619. drawData[i]={Value:data[i],Value2:data2};
  7620. }
  7621. else
  7622. {
  7623. if (isNaN(data[i]) || isNaN(data2[i])) continue;
  7624. drawData[i]={Value:data[i],Value2:data2[i]};
  7625. }
  7626. }
  7627. }
  7628. else
  7629. {
  7630. if(!condition) return result;
  7631. for(var i=0;i<this.SymbolData.Data.Data.length;++i) //以K线长度为数据长度
  7632. {
  7633. drawData[i]=null;
  7634. if (IsNumber && IsNumber2)
  7635. {
  7636. drawData[i]={Value:data,Value2:data2};
  7637. }
  7638. else if (IsNumber && !IsNumber2)
  7639. {
  7640. if (!this.IsNumber(data2[i])) continue;
  7641. drawData[i]={Value:data,Value2:data2[i]};
  7642. }
  7643. else if (!IsNumber && IsNumber2)
  7644. {
  7645. if (!this.IsNumber(data[i])) continue;
  7646. drawData[i]={Value:data[i],Value2:data2};
  7647. }
  7648. else
  7649. {
  7650. if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i])) continue;
  7651. drawData[i]={Value:data[i],Value2:data2[i]};
  7652. }
  7653. }
  7654. }
  7655. return result;
  7656. }
  7657. /*
  7658. DRAWLINE 绘制直线段
  7659. 在图形上绘制直线段。
  7660. 用法: DRAWLINE(COND1,PRICE1,COND2,PRICE2,EXPAND)
  7661. 当COND1条件满足时,在PRICE1位置画直线起点,当COND2条件满足时,在PRICE2位置画直线终点,EXPAND为延长类型。
  7662. 例如: DRAWLINE(HIGH>=HHV(HIGH,20),HIGH,LOW<=LLV(LOW,20),LOW,1) 表示在创20天新高与创20天新低之间画直线并且向右延长。
  7663. */
  7664. this.DRAWLINE=function(condition,data,condition2,data2,expand)
  7665. {
  7666. let drawData=[];
  7667. let result={DrawData:drawData, DrawType:'DRAWLINE', Expand:expand};
  7668. if(condition.length<=0) return result;
  7669. let count=Math.max(condition.length,condition2.length);
  7670. let bFirstPoint=false;
  7671. let bSecondPont=false;
  7672. let lineCache={Start:{ },End:{ }, List:new Array()};
  7673. function CopyLineData(aryDest, arySrc)
  7674. {
  7675. if (!IFrameSplitOperator.IsNonEmptyArray(arySrc)) return;
  7676. for(var j=0; j<arySrc.length; ++j)
  7677. {
  7678. var item=arySrc[j];
  7679. aryDest[item.ID]=item.Value;
  7680. }
  7681. }
  7682. for(let i=0;i<count;++i)
  7683. {
  7684. drawData[i]=null;
  7685. if (i<condition.length && i<condition2.length)
  7686. {
  7687. if (bFirstPoint==false && bSecondPont==false)
  7688. {
  7689. if (condition[i]==null || !condition[i]) continue;
  7690. bFirstPoint=true;
  7691. lineCache.Start={ID:i, Value:data[i]}; //第1个点
  7692. }
  7693. else if (bFirstPoint==true && bSecondPont==false)
  7694. {
  7695. var bCondition2=(condition2[i]!=null && condition2[i]); //条件2
  7696. if (!bCondition2)
  7697. {
  7698. if (condition[i] ) //条件1满足
  7699. lineCache.Start={ID:i, Value:data[i]}; //移动第1个点
  7700. continue;
  7701. }
  7702. if (bCondition2)
  7703. {
  7704. bSecondPont=true;
  7705. lineCache.End={ID:i, Value:data2[i]}; //第2个点
  7706. if (condition[i])
  7707. {
  7708. var lineData=this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
  7709. CopyLineData(drawData,lineData);
  7710. bFirstPoint=true;
  7711. bSecondPont=false;
  7712. lineCache.Start={ID:i, Value:data[i]}; //第1个点
  7713. }
  7714. }
  7715. }
  7716. else if (bFirstPoint==true && bSecondPont==true)
  7717. {
  7718. var bCondition2=(condition2[i]!=null && condition2[i]); //条件2
  7719. if (bCondition2) //条件2满足
  7720. {
  7721. lineCache.End={ID:i, Value:data2[i]}; //移动第2个点
  7722. }
  7723. else if (condition[i]) //条件1满足
  7724. {
  7725. var lineData=this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
  7726. CopyLineData(drawData,lineData);
  7727. if (expand==1) this.CalculateDrawDataExtendLine(drawData, lineCache.Start.ID-2);//右延长线
  7728. bFirstPoint=bSecondPont=false;
  7729. lineCache={Start:{ },End:{ }};
  7730. bFirstPoint=true;
  7731. bSecondPont=false;
  7732. lineCache.Start={ID:i, Value:data[i]}; //第1个点
  7733. }
  7734. }
  7735. }
  7736. //最后一组线
  7737. if (bFirstPoint==true && bSecondPont==true)
  7738. {
  7739. var lineData=this.CalculateDrawLine(lineCache);
  7740. CopyLineData(drawData,lineData);
  7741. }
  7742. }
  7743. if (expand==1) this.CalculateDrawDataExtendLine(drawData);//右延长线
  7744. return result;
  7745. }
  7746. this.CalculateDrawDataExtendLine=function(drawData, maxCount)
  7747. {
  7748. if (maxCount<0) return;
  7749. var x2=null;
  7750. var count=drawData.length;
  7751. if (this.IsNumber(maxCount) && maxCount<count) count=maxCount;
  7752. for(var i=count-1;i>=0;--i)
  7753. {
  7754. if (this.IsNumber(drawData[i]))
  7755. {
  7756. x2=i;
  7757. break;
  7758. }
  7759. }
  7760. //y3=(y1-y2)*(x3-x1)/(x2-x1)
  7761. if (x2!=null && x2-1>=0)
  7762. {
  7763. var x1=x2-1;
  7764. for(var i=x2+1;i<count;++i)
  7765. {
  7766. var y1=drawData[x1];
  7767. var y2=drawData[x2];
  7768. var y3=(y1-y2)*(i-x1)/(x2-x1);
  7769. if (y1-y3<0) break;
  7770. drawData[i]=y1-y3;
  7771. }
  7772. }
  7773. }
  7774. /*
  7775. 画出带状线.
  7776. 用法: DRAWBAND(VAL1,COLOR1,VAL2,COLOR2),当VAL1>VAL2时,在VAL1和VAL2之间填充COLOR1;当VAL1<VAL2时,填充COLOR2,这里的颜色均使用RGB函数计算得到.
  7777. 例如: DRAWBAND(OPEN,RGB(0,224,224),CLOSE,RGB(255,96,96));
  7778. */
  7779. this.DRAWBAND=function(data,color,data2,color2)
  7780. {
  7781. let drawData=[];
  7782. let result = { DrawData: drawData, DrawType: 'DRAWBAND', Color: [color.toLowerCase(), color2.toLowerCase()]};
  7783. let count=Math.max(data.length, data2.length);
  7784. for(let i=0;i<count;++i)
  7785. {
  7786. let item={Value:null, Value2:null};
  7787. if (i<data.length) item.Value=data[i];
  7788. if (i<data2.length) item.Value2=data2[i];
  7789. drawData.push(item);
  7790. }
  7791. return result;
  7792. }
  7793. this.DRAWKLINE = function (high, open, low, close)
  7794. {
  7795. let drawData = [];
  7796. let result = { DrawData: drawData, DrawType: 'DRAWKLINE' };
  7797. let count = Math.max(high.length, open.length, low.length, close.length);
  7798. for (let i = 0; i < count; ++i)
  7799. {
  7800. let item = { Open: null, High: null, Low: null, Close: null };
  7801. if (i < high.length && i < open.length && i < low.length && i < close.length)
  7802. {
  7803. item.Open = open[i];
  7804. item.High = high[i];
  7805. item.Low = low[i];
  7806. item.Close = close[i];
  7807. }
  7808. drawData[i] = item;
  7809. }
  7810. return result;
  7811. }
  7812. //满足条件画一根K线
  7813. this.DRAWKLINE_IF = function (condition, high, open, low, close)
  7814. {
  7815. let drawData = [];
  7816. let result = { DrawData: drawData, DrawType: 'DRAWKLINE_IF' };
  7817. let count = Math.max(condition.length, high.length, open.length, low.length, close.length);
  7818. for (let i = 0; i < count; ++i) {
  7819. let item = { Open: null, High: null, Low: null, Close: null };
  7820. if (i < high.length && i < open.length && i < low.length && i < close.length && i < condition.length)
  7821. {
  7822. if (condition[i])
  7823. {
  7824. item.Open = open[i];
  7825. item.High = high[i];
  7826. item.Low = low[i];
  7827. item.Close = close[i];
  7828. }
  7829. }
  7830. drawData[i] = item;
  7831. }
  7832. return result;
  7833. }
  7834. /*
  7835. DRAWCOLORKLINE 绘制K线
  7836. 用法:
  7837. DRAWCOLORKLINE(Cond,Color,Empty);
  7838. 满足Cond条件时,按照Color颜色绘制K线,根据Empty标志判断是空心还是实心。COLOR代表颜色,Empty非0为空心。
  7839. 注:
  7840. 不支持将该函数定义为变量,即不支持下面的写法:
  7841. A:DRAWCOLORKLINE(Cond,Color,Empty);
  7842. 例:
  7843. DRAWCOLORKLINE(C>O,COLORBLUE,0);//收盘价大于开盘价,用蓝色绘制实心K线
  7844. */
  7845. this.DRAWCOLORKLINE=function(condition, color, empty)
  7846. {
  7847. let drawData=[];
  7848. let result={ DrawData:drawData, DrawType:'DRAWCOLORKLINE', IsEmptyBar:!(empty==0), Color:color };
  7849. if (Array.isArray(condition)) //数组
  7850. {
  7851. for(var i=0; i<condition.length && i<this.SymbolData.Data.Data.length; ++i)
  7852. {
  7853. drawData[i]=null;
  7854. var condItem=condition[i];
  7855. if (!condItem) continue;
  7856. var kItem=this.SymbolData.Data.Data[i];
  7857. if (!kItem) continue;
  7858. drawData[i]={Open:kItem.Open,High:kItem.High, Low:kItem.Low, Close:kItem.Close};
  7859. }
  7860. }
  7861. else
  7862. {
  7863. if (condition)
  7864. {
  7865. for(var i=0;i<this.SymbolData.Data.Data.length;++i) //以K线长度为数据长度
  7866. {
  7867. drawData[i]=null;
  7868. var kItem=this.SymbolData.Data.Data[i];
  7869. if (!kItem) continue;
  7870. drawData[i]={Open:kItem.Open,High:kItem.High, Low:kItem.Low, Close:kItem.Close };
  7871. }
  7872. }
  7873. }
  7874. return result;
  7875. }
  7876. /*
  7877. PLOYLINE 折线段
  7878. 在图形上绘制折线段。
  7879. 用法: PLOYLINE(COND,PRICE),当COND条件满足时,以PRICE位置为顶点画折线连接。
  7880. 例如: PLOYLINE(HIGH>=HHV(HIGH,20),HIGH)表示在创20天新高点之间画折线。
  7881. */
  7882. this.POLYLINE = function (condition, data)
  7883. {
  7884. let drawData = [];
  7885. let result = { DrawData: drawData, DrawType: 'POLYLINE' };
  7886. let isNumber = typeof (data) == 'number';
  7887. let bFirstPoint = false;
  7888. let bSecondPont = false;
  7889. if (isNumber)
  7890. {
  7891. for (let i in condition)
  7892. {
  7893. drawData[i] = null;
  7894. if (bFirstPoint == false)
  7895. {
  7896. if (!condition[i]) continue;
  7897. drawData[i] = data;
  7898. bFirstPoint = true;
  7899. }
  7900. else {
  7901. drawData[i] = data;
  7902. }
  7903. }
  7904. }
  7905. else
  7906. {
  7907. let lineCache = { Start: {}, End: {}, List: new Array() };
  7908. for (let i in condition)
  7909. {
  7910. drawData[i] = null;
  7911. if (bFirstPoint == false && bSecondPont == false)
  7912. {
  7913. if (condition[i] == null || !condition[i]) continue;
  7914. if (i >= data.length || !this.IsNumber(data[i])) continue;
  7915. bFirstPoint = true;
  7916. lineCache.Start = { ID: parseInt(i), Value: data[i] }; //第1个点
  7917. }
  7918. else if (bFirstPoint == true && bSecondPont == false)
  7919. {
  7920. if (condition[i] == null || !condition[i]) continue;
  7921. if (i >= data.length || !this.IsNumber(data[i])) continue;
  7922. lineCache.End = { ID: parseInt(i), Value: data[i] }; //第2个点
  7923. //根据起始点和结束点 计算中间各个点的数据
  7924. let lineData = this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
  7925. for (let j in lineData)
  7926. {
  7927. let item = lineData[j];
  7928. drawData[item.ID] = item.Value;
  7929. }
  7930. let start = { ID: lineCache.End.ID, Value: lineCache.End.Value };
  7931. lineCache = { Start: start, End: {} };
  7932. }
  7933. }
  7934. }
  7935. return result
  7936. }
  7937. /*
  7938. 画出数字.
  7939. 用法:
  7940. DRAWNUMBER(COND,PRICE,NUMBER),当COND条件满足时,在PRICE位置书写数字NUMBER.
  7941. 例如:
  7942. DRAWNUMBER(CLOSE/OPEN>1.08,LOW,C)表示当日实体阳线大于8%时在最低价位置显示收盘价.
  7943. */
  7944. this.DRAWNUMBER = function (condition, data, data2,decimal)
  7945. {
  7946. let drawData={ Value:[], Text:[] };
  7947. let result={ DrawData:drawData, DrawType:'DRAWNUMBER' };
  7948. var dec=2; //小数位数
  7949. if (IFrameSplitOperator.IsNumber(decimal)) dec=decimal;
  7950. var priceData={ DataType:0, SingleValue:null, ArrayValue:null }; //SingleValue=单值 ArrayValue=数组
  7951. if (Array.isArray(data))
  7952. {
  7953. priceData.ArrayValue=data;
  7954. priceData.DataType=2;
  7955. }
  7956. else
  7957. {
  7958. if (data==="TOP"|| data==="BOTTOM") result.FixedPosition=data;
  7959. priceData.SingleValue=data;
  7960. priceData.DataType=1;
  7961. }
  7962. var numberData={ DataType:0, SingleValue:null,ArrayValue:null };
  7963. if (Array.isArray(data2))
  7964. {
  7965. numberData.ArrayValue=data2;
  7966. numberData.DataType=2;
  7967. }
  7968. else
  7969. { //单值
  7970. numberData.SingleValue=data2;
  7971. numberData.DataType=1;
  7972. if (IFrameSplitOperator.IsNumber(data2))
  7973. {
  7974. if (IFrameSplitOperator.IsInteger(data2)) numberData.SingleValue=data2.toString();
  7975. else text=data2.toFixed(dec);
  7976. }
  7977. }
  7978. if (Array.isArray(condition))
  7979. {
  7980. for(var i=0; i<condition.length; ++i)
  7981. {
  7982. drawData.Value[i]=null;
  7983. if (!condition[i]) continue;
  7984. drawData.Value[i]=this.DRAWNUMBER_Temp_PriceItem(i,priceData);
  7985. drawData.Text[i]=this.DRAWNUMBER_Temp_NumberItem(i,numberData,dec);
  7986. }
  7987. }
  7988. else if (this.IsNumber(condition) && condition)
  7989. {
  7990. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  7991. {
  7992. drawData.Value[i]=this.DRAWNUMBER_Temp_PriceItem(i,priceData);
  7993. drawData.Text[i]=this.DRAWNUMBER_Temp_NumberItem(i,numberData,dec);
  7994. }
  7995. }
  7996. return result;
  7997. }
  7998. this.DRAWNUMBER_Temp_PriceItem=function(index, priceData)
  7999. {
  8000. if (!priceData) return null;
  8001. if (priceData.DataType==1) return priceData.SingleValue;
  8002. if (!IFrameSplitOperator.IsNonEmptyArray(priceData.ArrayValue)) return null;
  8003. return priceData.ArrayValue[index];
  8004. }
  8005. this.DRAWNUMBER_Temp_NumberItem=function(index,numberData,decimal)
  8006. {
  8007. if (!numberData) return null;
  8008. if (numberData.DataType==1)
  8009. {
  8010. var value=numberData.SingleValue;
  8011. if (IFrameSplitOperator.IsNumber(value)) return value.toFixed(decimal);
  8012. else if (value) return value.toString();
  8013. return null;
  8014. }
  8015. if (!IFrameSplitOperator.IsNonEmptyArray(numberData.ArrayValue)) return null;
  8016. var value=numberData.ArrayValue[index];
  8017. if (this.IsNumber(value))
  8018. {
  8019. if (IFrameSplitOperator.IsInteger(value)) return value.toString();
  8020. else return value.toFixed(decimal);
  8021. }
  8022. return value.toString();
  8023. }
  8024. /*
  8025. 在图形上绘制小图标.
  8026. 用法:
  8027. DRAWICON(COND,PRICE,TYPE),当COND条件满足时,在PRICE位置画TYPE号图标(TYPE为1--41).
  8028. 例如:
  8029. DRAWICON(CLOSE>OPEN,LOW,1)表示当收阳时在最低价位置画1号图标.
  8030. */
  8031. this.DRAWICON = function (condition, data, type, markID)
  8032. {
  8033. if (IFrameSplitOperator.IsString(type)) //把ICO1=>1
  8034. {
  8035. var value=type.replace('ICO',"");
  8036. type=parseInt(value);
  8037. }
  8038. let icon = g_JSComplierResource.GetDrawTextIcon(type);
  8039. if (!icon) icon = { Symbol: '●', Color: 'rgb(0,139,69)'};
  8040. let drawData = [];
  8041. let result = { DrawData: drawData, DrawType: 'DRAWICON', Icon: icon , IconID:type};
  8042. if (markID) result.MarkID=markID;
  8043. if (condition.length <= 0) return result;
  8044. var IsNumber = typeof (data) == "number";
  8045. if (typeof (condition) == 'number')
  8046. {
  8047. if (!condition) return result;
  8048. for (var i = 0; i < this.SymbolData.Data.Data.length; ++i)
  8049. {
  8050. if (IsNumber)
  8051. {
  8052. drawData[i] = data;
  8053. }
  8054. else
  8055. {
  8056. if (i < data.length && this.IsNumber(data[i])) drawData[i] = data[i];
  8057. else drawData[i] = null;
  8058. }
  8059. }
  8060. return result;
  8061. }
  8062. for (var i in condition)
  8063. {
  8064. drawData[i] = null;
  8065. if (!condition[i]) continue;
  8066. if (IsNumber)
  8067. {
  8068. drawData[i] = data;
  8069. }
  8070. else
  8071. {
  8072. if (this.IsNumber(data[i])) drawData[i] = data[i];
  8073. }
  8074. }
  8075. return result;
  8076. }
  8077. /*
  8078. ICON:在k线图上,显示小图标。
  8079. 用法:ICON(TYPE,ICON);
  8080. 当TYPE为1,则在K线最高价位置显示图标ICON,当TYPE为0,则在最低价位置显示
  8081. 图标ICON。
  8082. 注:
  8083. 1、该函数与判断条件连用,如:COND,ICON(TYPE,ICON);
  8084. 2、该函数支持在函数后设置垂直对齐方式:VALIGN0(上对齐)、VALIGN1(中对齐)、VALIGN2(下对齐)
  8085. 即可以写为如下格式:
  8086. CLOSE<OPEN,ICON(1,'阴'),VALIGN0;
  8087. 例1:
  8088. CLOSE>OPEN,ICON(1,'ICO1');//表示K线收盘大于开盘时,在最高价上显示图标1。
  8089. 写完“ICON(1,” 以后,点击插入图标按钮,再单击选中的图标插入到函数中,图标用
  8090. 'ICO1'~'ICO105'表示
  8091. */
  8092. this.ICON=function(position, type)
  8093. {
  8094. if (IFrameSplitOperator.IsString(type)) //把ICO1=>1
  8095. {
  8096. var value=type.replace('ICO',"");
  8097. type=parseInt(value);
  8098. }
  8099. var icon=g_JSComplierResource.GetDrawTextIcon(type);
  8100. if (!icon) icon={ Symbol: '●', Color: 'rgb(0,139,69)'};
  8101. let drawData=[];
  8102. let result={DrawData:drawData, DrawType:'ICON',Icon:icon};
  8103. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  8104. {
  8105. var kItem=this.SymbolData.Data.Data[i];
  8106. if (!kItem) continue;
  8107. if (position==0) drawData[i]=kItem.Low;
  8108. else if (position==1) drawData[i]=kItem.High;
  8109. }
  8110. return result;
  8111. }
  8112. // 相对位置上画矩形.
  8113. //用法: DRAWRECTREL(LEFT,TOP,RIGHT,BOTTOM,COLOR),以图形窗口(LEFT,TOP)为左上角,(RIGHT,BOTTOM)为右下角绘制矩形,坐标单位是窗口沿水平和垂直方向的1/1000,取值范围是0—999,超出范围则可能显示在图形窗口外,矩形中间填充颜色COLOR,COLOR为0表示不填充.
  8114. //例如: DRAWRECTREL(0,0,500,500,RGB(255,255,0))表示在图形最左上部1/4位置用黄色绘制矩形
  8115. this.DRAWRECTREL = function (left, top, right, bottom, color)
  8116. {
  8117. let drawData =
  8118. {
  8119. Rect:
  8120. {
  8121. Left: Math.min(left,right), Top: Math.min(top,bottom),
  8122. Right: Math.max(left,right), Bottom: Math.max(top,bottom)
  8123. },
  8124. Color: color
  8125. };
  8126. if (color == 0) drawData.Color = null;
  8127. let result = { DrawData: drawData, DrawType: 'DRAWRECTREL' };
  8128. return result;
  8129. }
  8130. //DRAWTEXTREL(X,Y,TEXT),在图形窗口(X,Y)坐标位置书写文字TEXT,坐标单位是窗口沿水平和垂直方向的1/1000,X、Y取值范围是0—999,超出范围则可能显示在图形窗口外。
  8131. //例如:DRAWTEXTREL(500,500,'注意')表示在图形中间位置显示'注意'字样。
  8132. this.DRAWTEXTREL=function(x, y, text)
  8133. {
  8134. let drawData={ Point:{X:x, Y:y} };
  8135. if (IFrameSplitOperator.IsString(text))
  8136. drawData.Text=text;
  8137. else if (IFrameSplitOperator.IsNonEmptyArray(text))
  8138. drawData.Text=text[0];
  8139. let result={DrawData:drawData, DrawType:'DRAWTEXTREL'};
  8140. return result;
  8141. }
  8142. //DRAWTEXTABS(X,Y,TEXT),在图形窗口(X,Y)坐标位置书写文字TEXT,坐标单位是像素,图形窗口左上角坐标为(0,0)。
  8143. //例如:DRAWTEXTABS(0,0,'注意')表示在图形最左上角位置显示'注意'字样。
  8144. this.DRAWTEXTABS=function(x, y, text)
  8145. {
  8146. let drawData={ Point:{X:x, Y:y} };
  8147. if (IFrameSplitOperator.IsString(text))
  8148. drawData.Text=text;
  8149. else if (IFrameSplitOperator.IsNonEmptyArray(text))
  8150. drawData.Text=text[0];
  8151. let result={DrawData:drawData, DrawType:'DRAWTEXTABS'};
  8152. return result;
  8153. }
  8154. //填充背景.
  8155. //用法: DRAWGBK(COND,COLOR1,COLOR2,colorAngle) colorAngle=渐近色角度
  8156. //例如: DRAWGBK(O>C,RGB(0,255,0),RGB(255,0,0),0);
  8157. this.DRAWGBK=function(condition, color, color2, colorAngle)
  8158. {
  8159. let drawData={ Color:[], Angle:colorAngle };
  8160. if (color) drawData.Color.push(color);
  8161. if (color2) drawData.Color.push(color2);
  8162. let result={DrawData:null, DrawType:'DRAWGBK'};
  8163. if (Array.isArray(condition))
  8164. {
  8165. for(var i in condition)
  8166. {
  8167. var item=condition[i];
  8168. if (item)
  8169. {
  8170. result.DrawData=drawData;
  8171. break;
  8172. }
  8173. }
  8174. }
  8175. else
  8176. {
  8177. if (condition) result.DrawData=drawData;
  8178. }
  8179. return result;
  8180. }
  8181. this.DRAWGBK2=function(condition, color, color2, colorAngle)
  8182. {
  8183. let drawData={ Color:[], Angle:colorAngle };
  8184. if (color) drawData.Color.push(color);
  8185. if (color2) drawData.Color.push(color2);
  8186. let result={DrawData:null, DrawType:'DRAWGBK2'};
  8187. if (Array.isArray(condition))
  8188. {
  8189. drawData.Data=[];
  8190. for(var i in condition)
  8191. {
  8192. var item=condition[i];
  8193. drawData.Data[i]=item ? 1:0;
  8194. }
  8195. result.DrawData=drawData;
  8196. }
  8197. else
  8198. {
  8199. if (condition)
  8200. {
  8201. result.DrawData=drawData;
  8202. result.DrawType="DRAWGBK";
  8203. }
  8204. }
  8205. return result;
  8206. }
  8207. //填充部分背景.
  8208. //用法:
  8209. //DRAWGBK_DIV(COND,COLOR1,COLOR2,填色方式,填充范围),填充满足COND条件的背景区域
  8210. //填色方式:0是上下渐进 1是左右渐进 2是用COLOR1画框线 3是用COLOR1画框线, 用COLOR2填充
  8211. //填充范围:0为整个区域 1为最高最低区 2为开盘收盘区
  8212. //例如:
  8213. //DRAWGBK_DIV(C>O,RGB(0,255,0),RGB(255,0,0),0,0);
  8214. this.DRAWGBK_DIV=function(condition, color, color2, colorType, fillType)
  8215. {
  8216. var drawData={ AryColor:[color, color2], ColorType:colorType, FillType:fillType, Data:[] };
  8217. var result={ DrawData:drawData, DrawType:'DRAWGBK_DIV' };
  8218. if (!this.SymbolData || !this.SymbolData.Data || !IFrameSplitOperator.IsNonEmptyArray(this.SymbolData.Data.Data)) return result;
  8219. var aryKData=this.SymbolData.Data.Data;
  8220. if (Array.isArray(condition))
  8221. {
  8222. for(var i=0; i<aryKData.length; ++i)
  8223. {
  8224. var condItem=condition[i];
  8225. var item=null;
  8226. if (condItem)
  8227. {
  8228. var kItem=aryKData[i];
  8229. if (fillType==1) item={ AryValue:[kItem.High, kItem.Low] }
  8230. else if (fillType==2) item={ AryValue:[kItem.Open, kItem.Close] }
  8231. else item={ AryValue:null };
  8232. }
  8233. drawData.Data[i]=item;
  8234. }
  8235. }
  8236. else
  8237. {
  8238. if (condition)
  8239. {
  8240. for(var i=0; i<aryKData.length; ++i)
  8241. {
  8242. var kItem=aryKData[i];
  8243. var item=null;
  8244. if (fillType==1) item={ AryValue:[kItem.High, kItem.Low] }
  8245. else if (fillType==2) item={ AryValue:[kItem.Open, kItem.Close] }
  8246. else item={ AryValue:null };
  8247. drawData.Data[i]=item;
  8248. }
  8249. }
  8250. }
  8251. return result;
  8252. }
  8253. this.RGB = function (r, g, b)
  8254. {
  8255. var rgb = `rgb(${r},${g},${b})`;
  8256. return rgb;
  8257. }
  8258. this.RGBA = function (r, g, b, a)
  8259. {
  8260. var rgba = `rgba(${r},${g},${b},${a})`;
  8261. return rgba;
  8262. }
  8263. this.UPCOLOR=function(color)
  8264. {
  8265. return color;
  8266. }
  8267. this.DOWNCOLOR=function(color)
  8268. {
  8269. return color;
  8270. }
  8271. this.STICKTYPE=function(value)
  8272. {
  8273. return value;
  8274. }
  8275. //数据左右偏移
  8276. this.XMOVE=function(offset)
  8277. {
  8278. return offset;
  8279. }
  8280. //数据上下偏移
  8281. this.YMOVE=function(offset)
  8282. {
  8283. return offset;
  8284. }
  8285. this.LINEDASH=function(aryData)
  8286. {
  8287. if (IFrameSplitOperator.IsNonEmptyArray(aryData)) return aryData.slice();
  8288. return [];
  8289. }
  8290. //该函数和DRAWTEXT连用
  8291. //{ Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] }
  8292. this.BACKGROUND=function(color, borderColor, left, right, top, bottom)
  8293. {
  8294. var bg={ Margin:[0,1,1,1] };
  8295. if (color) bg.Color=color;
  8296. if (borderColor) bg.Border=borderColor;
  8297. if (IFrameSplitOperator.IsNumber(left)) bg.Margin[2]=left;
  8298. if (IFrameSplitOperator.IsNumber(right)) bg.Margin[3]=right;
  8299. if (IFrameSplitOperator.IsNumber(top)) bg.Margin[0]=top;
  8300. if (IFrameSplitOperator.IsNumber(bottom)) bg.Margin[1]=bottom;
  8301. return bg;
  8302. }
  8303. //该函数和DRAWTEXT, DRAWNUMBER连用
  8304. //{ color:线段颜色, lineWidth:宽度 lineType:线段样式0=直线 1=虚线}
  8305. this.CKLINE=function(color, lineWidth, lineType, lineDotted)
  8306. {
  8307. var drawData={ Color:color, LineWidth: 1, LineType:0, LineDot:[3,3] };
  8308. if (IFrameSplitOperator.IsPlusNumber(lineWidth)) drawData.LineWidth=lineWidth;
  8309. if (IFrameSplitOperator.IsPlusNumber(lineType)) drawData.LineType=lineType;
  8310. if (lineDotted)
  8311. {
  8312. let ary=lineDotted.split(',');
  8313. var dotted=[];
  8314. for(var i in ary)
  8315. {
  8316. var item=ary[i];
  8317. if (!item) continue;
  8318. var value=parseInt(ary[i]);
  8319. if (value<=0) continue;
  8320. dotted.push(value);
  8321. }
  8322. if (dotted.length>0) drawData.LineDotted=dotted;
  8323. }
  8324. drawData.Data=[];
  8325. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  8326. {
  8327. var item=this.SymbolData.Data.Data[i];
  8328. drawData.Data[i]={ High:item.High, Low:item.Low };
  8329. }
  8330. return drawData;
  8331. }
  8332. //用法:PARTLINE(PRICE,COND1,COLOR1,COND2,COLOR2...),
  8333. //绘制PRICE线,当COND1条件满足时,用COLOR1颜色,当COND2条件满足时,用COLOR2颜色,否则不绘制,从COLOR1之后的参数均可以省略,最多可以有10组条件
  8334. //例如:PARTLINE(CLOSE,CLOSE>OPEN,RGB(255,0,0),CLOSE<OPEN,RGB(0,255,0),1,RGB(0,0,255))
  8335. //表示画收盘价线,阳线时用红色,阴线时用绿色,平盘用蓝色.注意最后一个条件为1,表示前面都不满足时必然满足这个条件
  8336. this.PARTLINE=function(args)
  8337. {
  8338. let drawData=[];
  8339. let result={DrawData:drawData, DrawType:'PARTLINE'};
  8340. if (args.length<3) return result;
  8341. var data=args[0];
  8342. var condition=[];
  8343. for(var i=1;i<args.length && i+1<args.length;i+=2)
  8344. {
  8345. condition.push({Cond:args[i], RGB:args[i+1]});
  8346. }
  8347. for(var i in data)
  8348. {
  8349. var drawItem={Value:null, RGB:null};
  8350. drawData[i]=drawItem;
  8351. var value=data[i];
  8352. if (!this.IsNumber(value)) continue;
  8353. var rgb=null;
  8354. for(var j in condition)
  8355. {
  8356. var item=condition[j];
  8357. if (Array.isArray(item.Cond))
  8358. {
  8359. if (i<item.Cond.length && item.Cond[i])
  8360. {
  8361. rgb=item.RGB;
  8362. break;
  8363. }
  8364. }
  8365. else
  8366. {
  8367. if (this.IsNumber(item.Cond) && item.Cond) //单数值条件
  8368. {
  8369. rgb=item.RGB;
  8370. break;
  8371. }
  8372. }
  8373. }
  8374. if (rgb)
  8375. {
  8376. drawItem.Value=value;
  8377. drawItem.RGB=rgb;
  8378. }
  8379. }
  8380. return result;
  8381. }
  8382. }
  8383. JSDraw.prototype.CalculateDrawLine=function(lineCache)
  8384. {
  8385. lineCache.List=[];
  8386. for(let i=lineCache.Start.ID; i<=lineCache.End.ID; ++i) lineCache.List.push(i);
  8387. let height=Math.abs(lineCache.Start.Value-lineCache.End.Value);
  8388. let width=lineCache.List.length-1;
  8389. var result=[];
  8390. result.push({ID:lineCache.Start.ID, Value:lineCache.Start.Value}); //第1个点
  8391. if (lineCache.Start.Value>lineCache.End.Value)
  8392. {
  8393. for(let i=1;i<lineCache.List.length-1;++i)
  8394. {
  8395. var value=height*(lineCache.List.length-1-i)/width+lineCache.End.Value;
  8396. result.push({ID:lineCache.List[i], Value:value});
  8397. }
  8398. }
  8399. else
  8400. {
  8401. for(let i=1;i<lineCache.List.length-1;++i)
  8402. {
  8403. var value=height*i/width+lineCache.Start.Value;
  8404. result.push({ID:lineCache.List[i], Value:value});
  8405. }
  8406. }
  8407. result.push({ID:lineCache.End.ID, Value:lineCache.End.Value}); //最后一个点
  8408. return result;
  8409. }
  8410. //是否有是有效的数字
  8411. JSDraw.prototype.IsNumber = function (value)
  8412. {
  8413. if (value == null) return false;
  8414. if (isNaN(value)) return false;
  8415. return true;
  8416. }
  8417. //是否是整形
  8418. JSDraw.prototype.IsInteger=function(x)
  8419. {
  8420. return (typeof x === 'number') && (x % 1 === 0);
  8421. }
  8422. JSDraw.prototype.IsDrawFunction=function(name)
  8423. {
  8424. let setFunctionName = new Set(
  8425. [
  8426. "STICKLINE", "DRAWTEXT", 'SUPERDRAWTEXT', "DRAWTEXT_FIX", 'DRAWLINE', 'DRAWBAND', "DRAWKLINE1","DRAWCOLORKLINE",
  8427. 'DRAWKLINE', 'DRAWKLINE_IF', 'PLOYLINE', 'POLYLINE', 'DRAWNUMBER', 'DRAWNUMBER_FIX', 'DRAWICON', "ICON", "PARTLINE",
  8428. 'DRAWRECTREL', "DRAWTEXTABS","DRAWTEXTREL", "DRAWGBK", "DRAWGBK2","DRAWGBK_DIV"
  8429. ]);
  8430. if (setFunctionName.has(name)) return true;
  8431. return false;
  8432. }
  8433. //http://www.newone.com.cn/helpcontroller/index?code=zszy_pc
  8434. var DYNAINFO_ARGUMENT_ID=
  8435. {
  8436. YCLOSE:3,
  8437. OPEN:4,
  8438. HIGH:5,
  8439. LOW:6,
  8440. CLOSE: 7,
  8441. VOL: 8,
  8442. AMOUNT: 10,
  8443. AMPLITUDE:13, //振幅
  8444. INCREASE:14, //涨幅
  8445. EXCHANGERATE:37, //换手率
  8446. };
  8447. function JSSymbolData(ast,option,jsExecute)
  8448. {
  8449. this.AST=ast; //语法树
  8450. this.Execute=jsExecute;
  8451. this.Symbol='600000.sh';
  8452. this.Name;
  8453. this.Data=null; //个股数据
  8454. this.SourceData = null; //不复权的个股数据
  8455. this.MarketValue = null; //总市值
  8456. this.Period=0; //周期
  8457. this.Right=0; //复权
  8458. this.DataType = 0; //默认K线数据 2=分钟走势图数据
  8459. this.KLineApiUrl = g_JSComplierResource.Domain+"/API/KLine2"; //日线
  8460. this.MinuteKLineApiUrl = g_JSComplierResource.Domain +'/API/KLine3'; //分钟K线
  8461. this.RealtimeApiUrl = g_JSComplierResource.Domain +'/API/stock'; //实时行情
  8462. this.StockHistoryDayApiUrl = g_JSComplierResource.Domain +'/API/StockHistoryDay'; //历史财务数据
  8463. this.StockHistoryDay3ApiUrl = g_JSComplierResource.Domain +'/API/StockHistoryDay3'; //历史财务数据
  8464. this.StockNewsAnalysisApiUrl = g_JSComplierResource.CacheDomain+'/cache/newsanalyze'; //新闻分析数据
  8465. this.MaxRequestDataCount=1000;
  8466. this.MaxRequestMinuteDayCount=5;
  8467. this.KLineDateTimeRange; //请求的K线日期范围
  8468. this.LatestData=new Map(); //最新行情
  8469. this.IndexData; //大盘指数
  8470. this.MarginData = new Map(); //融资融券
  8471. this.NewsAnalysisData = new Map(); //新闻统计
  8472. this.ExtendData = new Map(); //其他的扩展数据
  8473. this.ScriptIndexOutData=new Map(); //调用脚本执行返回的数据
  8474. this.OtherSymbolData=new Map(); //其他股票信息 key=symbol value=[historydata]
  8475. //股票数据缓存 key=函数名(参数) { Data: value=拟合的数据 , Error: }
  8476. //FinValue(id)
  8477. this.StockData=new Map();
  8478. this.NetworkFilter; //网络请求回调 function(data, callback);
  8479. this.DrawInfo; //当前屏信息
  8480. //使用option初始化
  8481. if (option)
  8482. {
  8483. if (option.HQDataType) this.DataType = option.HQDataType;
  8484. if (option.Data)
  8485. {
  8486. this.Data=option.Data;
  8487. if (this.DataType != 2) //2=分钟走势图数据 没有周期和复权
  8488. {
  8489. this.Period=option.Data.Period; //周期
  8490. this.Right=option.Data.Right; //复权
  8491. }
  8492. //this.Data=null;
  8493. }
  8494. if (option.SourceData) this.SourceData = option.SourceData;
  8495. if (option.Symbol) this.Symbol=option.Symbol;
  8496. if (option.Symbol) this.Symbol = option.Symbol;
  8497. if (option.MaxRequestDataCount>0) this.MaxRequestDataCount=option.MaxRequestDataCount;
  8498. if (option.MaxRequestMinuteDayCount>0) this.MaxRequestMinuteDayCount=option.MaxRequestMinuteDayCount;
  8499. if (option.KLineApiUrl) this.KLineApiUrl=option.KLineApiUrl;
  8500. if (option.NetworkFilter) this.NetworkFilter = option.NetworkFilter;
  8501. if (option.DayCount>0) this.DayCount=option.DayCount;
  8502. if (option.IsApiPeriod) this.IsApiPeriod=option.IsApiPeriod;
  8503. if (option.Right) this.Right=option.Right;
  8504. if (option.Period) this.Period=option.Period;
  8505. if (option.KLineRange) this.KLineDateTimeRange=option.KLineRange;
  8506. if (option.DrawInfo) this.DrawInfo=option.DrawInfo;
  8507. }
  8508. this.GetLatestDataKey=function(key)
  8509. {
  8510. var key=`DYNAINFO-${key}`;
  8511. return key;
  8512. }
  8513. //最新行情
  8514. this.GetLatestData=function(jobItem)
  8515. {
  8516. var aryArgs=this.JobArgumentsToArray(jobItem, 1);
  8517. var lID=aryArgs[0];
  8518. var key=this.GetLatestDataKey(lID);
  8519. if (this.LatestData.has(key)) return this.Execute.RunNextJob();
  8520. var self=this;
  8521. JSNetwork.HttpRequest({
  8522. url: self.RealtimeApiUrl,
  8523. data:
  8524. {
  8525. "field": ["name","symbol","yclose","open","price","high","low","vol","amount","date","time","increase","exchangerate","amplitude"],
  8526. "symbol": [this.Symbol]
  8527. },
  8528. method:"POST",
  8529. dataType: "json",
  8530. success: function (recvData)
  8531. {
  8532. self.RecvLatestData(recvData);
  8533. self.Execute.RunNextJob();
  8534. },
  8535. error: function(request)
  8536. {
  8537. self.RecvError(request);
  8538. }
  8539. });
  8540. }
  8541. this.RecvLatestData = function (recvData)
  8542. {
  8543. let data=recvData.data;
  8544. if (data.ver==2.0)
  8545. {
  8546. this.RecvLatestDataVer2(data);
  8547. return;
  8548. }
  8549. if (!data.stock || data.stock.length!=1) return;
  8550. let stock=data.stock[0];
  8551. if (!stock) return;
  8552. if (IFrameSplitOperator.IsNumber(stock.yclose)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.YCLOSE),stock.yclose);
  8553. if (IFrameSplitOperator.IsNumber(stock.open)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.OPEN),stock.open);
  8554. if (IFrameSplitOperator.IsNumber(stock.high)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.HIGH),stock.high);
  8555. if (IFrameSplitOperator.IsNumber(stock.low)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.LOW),stock.low);
  8556. if (IFrameSplitOperator.IsNumber(stock.price)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.CLOSE),stock.price);
  8557. if (IFrameSplitOperator.IsNumber(stock.vol)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.VOL),stock.vol);
  8558. if (IFrameSplitOperator.IsNumber(stock.amount)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.AMOUNT),stock.amount);
  8559. if (IFrameSplitOperator.IsNumber(stock.increase)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.INCREASE),stock.increase);
  8560. if (IFrameSplitOperator.IsNumber(stock.exchangerate)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.EXCHANGERATE),stock.exchangerate);
  8561. if (IFrameSplitOperator.IsNumber(stock.amplitude)) this.LatestData.set(this.GetLatestDataKey(DYNAINFO_ARGUMENT_ID.AMPLITUDE),stock.amplitude);
  8562. /*
  8563. this.LatestData={ Symbol:stock.symbol, Name:stock.name, Date:stock.date, Time:stock.time,
  8564. YClose:stock.yclose,Price:stock.price, Open:stock.open, High:stock.high, Low:stock.low, Vol:stock.vol, Amount:stock.amount,
  8565. Increase:stock.increase, Exchangerate:stock.exchangerate, Amplitude:stock.amplitude};
  8566. */
  8567. JSConsole.Complier.Log('[JSSymbolData::RecvLatestData] symbol, LatestData', stock.symbol, this.LatestData);
  8568. }
  8569. //data:[{ id:, value: }]
  8570. this.RecvLatestDataVer2=function(recvData)
  8571. {
  8572. let data=recvData.data;
  8573. if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
  8574. var symbol=data.symbol;
  8575. for(var i=0;i<data.data.length;++i)
  8576. {
  8577. var item=data.data[i];
  8578. if (!item) continue;
  8579. if (!IFrameSplitOperator.IsNumber(item.id)) continue;
  8580. if (IFrameSplitOperator.IsNumber(item.value) || IFrameSplitOperator.IsString(item.value))
  8581. {
  8582. JSConsole.Complier.Log(`[JSSymbolData::RecvLatestDataVer2] symbol=${symbol} DYNAINFO(${item.id})=${item.value}.`);
  8583. this.LatestData.set(this.GetLatestDataKey(item.id), item.value);
  8584. }
  8585. }
  8586. JSConsole.Complier.Log('[JSSymbolData::RecvLatestDataVer2]', this.LatestData);
  8587. }
  8588. this.GetLatestCacheData=function(dataID)
  8589. {
  8590. var key=this.GetLatestDataKey(dataID);
  8591. if (!this.LatestData.has(key)) return null;
  8592. var data=this.LatestData.get(key);
  8593. //DYNAINFO(36) 自由流通换手率(序列数据,每个周期的数据不同,使用最新的自由流通股本) 转换成幅度需要乘100 比如DYNAINFO(36)>0.25表示换手超过25%
  8594. //DYNAINFO(37) 换手率(序列数据,每个周期的数据不同,使用的流通股本为最近数据) 转换成幅度需要乘100 比如DYNAINFO(37)>0.1表示换手超过10%
  8595. if (dataID==37 || dataID==36)
  8596. {
  8597. var value=null;
  8598. if (IFrameSplitOperator.IsNumber(data)) value=data;
  8599. else if (IFrameSplitOperator.IsNonEmptyArray(data) && IFrameSplitOperator.IsNumber(data[0])) value=data[0];
  8600. else return null;
  8601. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null;
  8602. var aryData=[];
  8603. for(var i=0;i<this.Data.Data.length;++i)
  8604. {
  8605. var kItem=this.Data.Data[i];
  8606. aryData[i]=null;
  8607. if (!kItem || !IFrameSplitOperator.IsNumber(kItem.Vol)) continue;
  8608. aryData[i]=kItem.Vol/value*100.0;// 换手率
  8609. }
  8610. return aryData;
  8611. }
  8612. return data;
  8613. }
  8614. this.GetDynaCacheData=function(name)
  8615. {
  8616. if (MAP_DYNAINFO_SHORTCUT.has(name))
  8617. {
  8618. var item=MAP_DYNAINFO_SHORTCUT.get(name);
  8619. return this.GetLatestCacheData(item.ID);
  8620. }
  8621. return null;
  8622. }
  8623. this.GetVolRateData = function (job, node)
  8624. {
  8625. var volrKey = job.ID.toString() + '-VolRate-' + this.Symbol;
  8626. if (this.ExtendData.has(volrKey)) return this.Execute.RunNextJob();
  8627. var self=this;
  8628. var dayCount=30;
  8629. if (this.NetworkFilter)
  8630. {
  8631. var dateRange=this.Data.GetDateRange();
  8632. var dayCount=1;
  8633. if (this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) dayCount=this.DayCount;
  8634. var obj=
  8635. {
  8636. Name:'JSSymbolData::GetVolRateData', //类名:: 函数
  8637. Explain:'分时量比数据(成交量)',
  8638. Request:
  8639. {
  8640. Url:self.KLineApiUrl, Type:'POST' ,
  8641. Data: { symbol:self.Symbol, dayCount:dayCount, field: ["name","symbol","vol"], period:0, right:0, dateRange:dateRange }
  8642. },
  8643. Self:this,
  8644. PreventDefault:false
  8645. };
  8646. this.NetworkFilter(obj, function(recvData)
  8647. {
  8648. self.RecvVolRateData(recvData,volrKey);
  8649. self.Execute.RunNextJob();
  8650. });
  8651. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  8652. }
  8653. JSNetwork.HttpRequest({
  8654. url: self.KLineApiUrl,
  8655. data:
  8656. {
  8657. "field": ["name","symbol","vol"],
  8658. "symbol": self.Symbol,
  8659. "start": -1,
  8660. "count": dayCount
  8661. },
  8662. type:"post",
  8663. dataType: "json",
  8664. async:true,
  8665. success: function (recvData)
  8666. {
  8667. self.RecvVolRateData(recvData,volrKey);
  8668. self.Execute.RunNextJob();
  8669. },
  8670. error: function(request)
  8671. {
  8672. self.RecvError(request);
  8673. }
  8674. });
  8675. }
  8676. this.RecvVolRateData = function (recvData, key)
  8677. {
  8678. var data=recvData.data;
  8679. var sumVol=0,avgVol5=0;
  8680. var mapAvgVol5=new Map();
  8681. if (data.Ver==2.0) // {Ver:2.0 , data:[ [日期,5日vol均值]] }
  8682. {
  8683. if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
  8684. for(var i=0;i<data.data.length;++i)
  8685. {
  8686. var item=data.data[i];
  8687. if (!IFrameSplitOperator.IsNonEmptyArray(item)) continue;
  8688. if (item.length<2) continue;
  8689. if (IFrameSplitOperator.IsNumber(item[0]) && IFrameSplitOperator.IsPlusNumber(item[1]))
  8690. {
  8691. mapAvgVol5.set(item[0],{ AvgVol5:item[1] } );
  8692. }
  8693. }
  8694. }
  8695. else
  8696. {
  8697. if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
  8698. var minuteCount=241;
  8699. if (IFrameSplitOperator.IsNumber(data.minutecount)) minuteCount=data.minutecount;
  8700. for(var i=0,j=0,dayCount=0;i<data.data.length;++i) //每天的5日成交均量
  8701. {
  8702. sumVol=0;
  8703. for(j=i,dayCount=0;j>=0 && dayCount<5;--j, ++dayCount)
  8704. {
  8705. var item=data.data[j];
  8706. if (IFrameSplitOperator.IsNumber(item[6]))
  8707. sumVol+=item[6];
  8708. }
  8709. if (dayCount>0)
  8710. {
  8711. avgVol5=sumVol/dayCount/minuteCount;
  8712. var item=data.data[i];
  8713. mapAvgVol5.set(item[0],
  8714. {
  8715. //for debug
  8716. //Vol5:sumVol, MinuteCount:minuteCount,,Count:dayCount,
  8717. AvgVol5:avgVol5
  8718. } );
  8719. }
  8720. }
  8721. }
  8722. if (mapAvgVol5.size>0) this.ExtendData.set(key,mapAvgVol5);
  8723. JSConsole.Complier.Log('[JSSymbolData::RecvVolRateData]', mapAvgVol5);
  8724. }
  8725. this.GetVolRateCacheData=function(node)
  8726. {
  8727. var key=JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA.toString()+'-VolRate-'+this.Symbol;
  8728. if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node,'不支持VOLR');
  8729. var result=[];
  8730. var mapAvgVol5=this.ExtendData.get(key);
  8731. var totalVol=0, preDate=0, avgVol5=null;
  8732. for(var i=0, j=0;i<this.Data.Data.length;++i)
  8733. {
  8734. result[i]=null;
  8735. var item=this.Data.Data[i];
  8736. if (preDate!=item.Date)
  8737. {
  8738. avgVol5=null;
  8739. j=0;
  8740. totalVol=0;
  8741. if (mapAvgVol5.has(item.Date))
  8742. {
  8743. var volItem=mapAvgVol5.get(item.Date);
  8744. avgVol5=volItem.AvgVol5;
  8745. }
  8746. preDate=item.Date;
  8747. }
  8748. if (avgVol5==null) continue;
  8749. totalVol+=item.Vol;
  8750. result[i]=totalVol/(j+1)/avgVol5*100;
  8751. ++j;
  8752. }
  8753. return result;
  8754. }
  8755. this.GetOtherSymbolParam=function(name)
  8756. {
  8757. var args=name.split("$");
  8758. var setStockDataName=new Set(['CLOSE',"C",'VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT','AMO','VOLINSTK']);
  8759. if (!setStockDataName.has(args[1])) return null;
  8760. var symbol=args[0];
  8761. if (symbol.length==6)
  8762. {
  8763. if (symbol[0]=="6" || symbol[0]=="5" || symbol[0]=="8" || symbol[0]=="9")
  8764. symbol+=".SH";
  8765. else if (symbol[0]=='0' || symbol[0]=='1' || symbol[0]=='2' || symbol[0]=='3')
  8766. symbol+='.SZ';
  8767. }
  8768. else if (symbol.indexOf("SZ")==0)
  8769. {
  8770. symbol=symbol.substr(2)+".SZ";
  8771. }
  8772. else if (symbol.indexOf("SH")==0)
  8773. {
  8774. symbol=symbol.substr(2)+".SH";
  8775. }
  8776. else if (symbol.indexOf("_")>0)
  8777. {
  8778. var arySymbol=symbol.split("_");
  8779. symbol=`${arySymbol[1]}.${arySymbol[0]}`;
  8780. }
  8781. else
  8782. return null;
  8783. return { Symbol:symbol.toLowerCase(), DataName:args[1] };
  8784. }
  8785. //获取其他股票数据
  8786. this.GetOtherSymbolData=function(job)
  8787. {
  8788. var symbol=this.Symbol;
  8789. if (job.Literal)
  8790. {
  8791. var args=this.GetOtherSymbolParam(job.Literal.toUpperCase());
  8792. if (!args)
  8793. {
  8794. var token=job.Token;
  8795. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.Literal} Error.`);
  8796. }
  8797. symbol=args.Symbol;
  8798. }
  8799. else
  8800. {
  8801. var args=job.Args;
  8802. if (args.length>0)
  8803. {
  8804. var item=args[0];
  8805. if (item.Type==Syntax.Literal)
  8806. {
  8807. symbol=item.Value;
  8808. }
  8809. else if (item.Type==Syntax.Identifier) //变量 !!只支持默认的变量值
  8810. {
  8811. var isFind=false;
  8812. for(var j in this.Arguments)
  8813. {
  8814. const argItem=this.Arguments[j];
  8815. if (argItem.Name==item.Name)
  8816. {
  8817. symbol=argItem.Value;
  8818. isFind=true;
  8819. break;
  8820. }
  8821. }
  8822. if (!isFind)
  8823. {
  8824. var token=job.Token;
  8825. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: can't read ${item.Name}`);
  8826. }
  8827. }
  8828. }
  8829. }
  8830. job.Symbol=symbol.toLowerCase();
  8831. if (job.Symbol==this.Symbol) return this.Execute.RunNextJob();
  8832. if (this.OtherSymbolData.has(job.Symbol)) return this.Execute.RunNextJob();
  8833. var self=this;
  8834. if (this.DataType==HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
  8835. {
  8836. if (this.NetworkFilter)
  8837. {
  8838. var dateRange=this.Data.GetDateRange();
  8839. var obj=
  8840. {
  8841. Name:'JSSymbolData::GetOtherSymbolData', //类名::函数名
  8842. Explain:'指定个股数据',
  8843. Request:
  8844. {
  8845. Data:
  8846. {
  8847. symbol:job.Symbol,
  8848. right:self.Right,
  8849. period:self.Period,
  8850. dateRange:dateRange
  8851. }
  8852. },
  8853. Self:this,
  8854. PreventDefault:false
  8855. };
  8856. this.NetworkFilter(obj, function(data)
  8857. {
  8858. self.RecvOtherSymbolKData(data,job);
  8859. self.Execute.RunNextJob();
  8860. });
  8861. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  8862. }
  8863. JSNetwork.HttpRequest({
  8864. url: self.KLineApiUrl,
  8865. data:
  8866. {
  8867. "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
  8868. "symbol": job.Symbol,
  8869. "start": -1,
  8870. "count": self.MaxRequestDataCount+500 //多请求2年的数据 确保股票剔除停牌日期以后可以对上
  8871. },
  8872. method: "POST",
  8873. dataType: "json",
  8874. async:true,
  8875. success: function (recvData)
  8876. {
  8877. self.RecvOtherSymbolKDayData(recvData,job);
  8878. self.Execute.RunNextJob();
  8879. },
  8880. error: function(request)
  8881. {
  8882. self.RecvError(request);
  8883. }
  8884. });
  8885. }
  8886. else if (ChartData.IsMinutePeriod(this.Period, true) || this.DataType==HQ_DATA_TYPE.MINUTE_ID || this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) //请求分钟数据
  8887. {
  8888. if (this.NetworkFilter)
  8889. {
  8890. var dateRange=this.Data.GetDateRange();
  8891. var obj=
  8892. {
  8893. Name:'JSSymbolData::GetOtherSymbolData', //类名::函数名
  8894. Explain:'指定个股数据',
  8895. Request:
  8896. {
  8897. Data:
  8898. {
  8899. symbol:job.Symbol,
  8900. right:self.Right,
  8901. period:self.Period,
  8902. dateRange:dateRange
  8903. }
  8904. },
  8905. Self:this,
  8906. PreventDefault:false
  8907. };
  8908. this.NetworkFilter(obj, function(data)
  8909. {
  8910. self.RecvOtherSymbolKData(data,job);
  8911. self.Execute.RunNextJob();
  8912. });
  8913. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  8914. }
  8915. JSNetwork.HttpRequest({
  8916. url: self.MinuteKLineApiUrl,
  8917. data:
  8918. {
  8919. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  8920. "symbol": job.Symbol,
  8921. "start": -1,
  8922. "count": self.MaxRequestMinuteDayCount+5
  8923. },
  8924. method: "POST",
  8925. dataType: "json",
  8926. async:true,
  8927. success: function (data)
  8928. {
  8929. self.RecvOtherSymbolKMinuteData(data,job);
  8930. self.Execute.RunNextJob();
  8931. },
  8932. error: function(request)
  8933. {
  8934. self.RecvError(request);
  8935. }
  8936. });
  8937. }
  8938. }
  8939. //第3方数据对接
  8940. this.RecvOtherSymbolKData=function(recvData,job)
  8941. {
  8942. var data=recvData.data;
  8943. JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKData] recv data' , data);
  8944. var kData=new ChartData();
  8945. var hisData=null;
  8946. var period=this.Period;
  8947. if (this.DataType==HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //日线数据
  8948. {
  8949. hisData=this.JsonDataToHistoryData(data);
  8950. kData.DataType=0;
  8951. }
  8952. else //分钟线数据
  8953. {
  8954. hisData=this.JsonDataToMinuteHistoryData(data);
  8955. kData.DataType=1;
  8956. //走势图使用1分钟K线模式
  8957. if (this.DataType==HQ_DATA_TYPE.MINUTE_ID || this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID)
  8958. period=4;
  8959. }
  8960. kData.Period=this.Period;
  8961. kData.Right=this.Right;
  8962. kData.Data=this.Data.FixKData(hisData,period);
  8963. this.OtherSymbolData.set(job.Symbol, kData);
  8964. }
  8965. this.RecvOtherSymbolKDayData=function(recvData,job)
  8966. {
  8967. var data=recvData.data;
  8968. JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKDayData] recv data' , data);
  8969. let hisData=this.JsonDataToHistoryData(data);
  8970. var kData=new ChartData();
  8971. kData.DataType=0; //日线数据
  8972. kData.Data=hisData;
  8973. var aryOverlayData=this.SourceData.GetOverlayData(kData.Data); //和主图数据拟合以后的数据
  8974. kData.Data=aryOverlayData;
  8975. if (ChartData.IsDayPeriod(this.Period,false)) //周期数据
  8976. {
  8977. let periodData=kData.GetPeriodData(this.Period);
  8978. kData.Data=periodData;
  8979. }
  8980. this.OtherSymbolData.set(job.Symbol, kData);
  8981. }
  8982. this.RecvOtherSymbolKMinuteData=function(recvData, job)
  8983. {
  8984. var data=recvData.data;
  8985. JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKMinuteData] recv data' , data);
  8986. let hisData=this.JsonDataToMinuteHistoryData(data);
  8987. var kData=new ChartData();
  8988. kData.DataType=1; /*分钟线数据 */
  8989. kData.Data=hisData;
  8990. if (ChartData.IsMinutePeriod(this.Period,false)) //周期数据
  8991. {
  8992. let periodData=kData.GetPeriodData(this.Period);
  8993. kData.Data=periodData;
  8994. }
  8995. this.OtherSymbolData.set(job.Symbol, kData);
  8996. }
  8997. this.GetOtherSymolCacheData=function(obj)
  8998. {
  8999. var symbol,dataName;
  9000. if (obj.FunctionName)
  9001. {
  9002. dataName=obj.FunctionName;
  9003. var args=obj.Args;
  9004. if (args.length<=0) return this.GetSymbolCacheData(dataName);
  9005. symbol=args[0].toString().toLowerCase();
  9006. }
  9007. else if (obj.Literal)
  9008. {
  9009. var args=this.GetOtherSymbolParam(obj.Literal.toUpperCase());
  9010. if (!args) return [];
  9011. symbol=args.Symbol;
  9012. dataName=args.DataName;
  9013. }
  9014. if (symbol==this.Symbol) return this.GetSymbolCacheData(dataName);
  9015. if (!this.OtherSymbolData.has(symbol)) return [];
  9016. var kData=this.OtherSymbolData.get(symbol);
  9017. var upperSymbol=symbol.toUpperCase();
  9018. switch(dataName)
  9019. {
  9020. case 'CLOSE':
  9021. case 'C':
  9022. return kData.GetClose();
  9023. case 'VOL':
  9024. case 'V':
  9025. return kData.GetVol(MARKET_SUFFIX_NAME.GetVolUnit(upperSymbol));
  9026. case 'OPEN':
  9027. case 'O':
  9028. return kData.GetOpen();
  9029. case 'HIGH':
  9030. case 'H':
  9031. return kData.GetHigh();
  9032. case 'LOW':
  9033. case 'L':
  9034. return kData.GetLow();
  9035. case 'AMOUNT':
  9036. case 'AMO':
  9037. return kData.GetAmount();
  9038. case 'VOLINSTK':
  9039. return kData.GetPosition();
  9040. }
  9041. }
  9042. //获取大盘指数数据
  9043. this.GetIndexData=function()
  9044. {
  9045. if (this.IndexData) return this.Execute.RunNextJob();
  9046. var self=this;
  9047. if (JSCommonData.ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
  9048. {
  9049. JSNetwork.HttpRequest({
  9050. url: self.KLineApiUrl,
  9051. data:
  9052. {
  9053. "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", 'up', 'down', 'stop', 'unchanged'],
  9054. "symbol": '000001.sh',
  9055. "start": -1,
  9056. "count": self.MaxRequestDataCount+500 //多请求2年的数据 确保股票剔除停牌日期以后可以对上
  9057. },
  9058. method: 'POST',
  9059. dataType: "json",
  9060. success: function (recvData)
  9061. {
  9062. self.RecvIndexHistroyData(recvData);
  9063. self.Execute.RunNextJob();
  9064. },
  9065. error: function(request)
  9066. {
  9067. self.RecvError(request);
  9068. }
  9069. });
  9070. }
  9071. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true)) //请求分钟数据
  9072. {
  9073. JSNetwork.HttpRequest({
  9074. url: self.MinuteKLineApiUrl,
  9075. data:
  9076. {
  9077. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  9078. "symbol": '000001.sh',
  9079. "start": -1,
  9080. "count": self.MaxRequestMinuteDayCount+5
  9081. },
  9082. method: 'POST',
  9083. dataType: "json",
  9084. success: function (data)
  9085. {
  9086. self.RecvIndexMinuteHistroyData(data);
  9087. self.Execute.RunNextJob();
  9088. },
  9089. error: function(request)
  9090. {
  9091. self.RecvError(request);
  9092. }
  9093. });
  9094. }
  9095. }
  9096. this.RecvIndexHistroyData=function(recvData)
  9097. {
  9098. let data = recvData.data;
  9099. JSConsole.Complier.Log('[JSSymbolData::RecvIndexHistroyData] recv data' , data);
  9100. let hisData=this.JsonDataToHistoryData(data);
  9101. this.IndexData = new JSCommonData.ChartData();
  9102. this.IndexData.DataType=0; /*日线数据 */
  9103. this.IndexData.Data=hisData;
  9104. var aryOverlayData = this.SourceData.GetOverlayData(this.IndexData.Data); //和主图数据拟合以后的数据
  9105. this.IndexData.Data=aryOverlayData;
  9106. if (JSCommonData.ChartData.IsDayPeriod(this.Period, false)) //周期数据
  9107. {
  9108. let periodData=this.IndexData.GetPeriodData(this.Period);
  9109. this.IndexData.Data=periodData;
  9110. }
  9111. }
  9112. this.RecvIndexMinuteHistroyData = function (recvData)
  9113. {
  9114. let data = recvData.data;
  9115. JSConsole.Complier.Log('[JSSymbolData::RecvIndexMinuteHistroyData] recv data' , data);
  9116. let hisData=this.JsonDataToMinuteHistoryData(data);
  9117. this.IndexData = new JSCommonData.ChartData();
  9118. this.IndexData.DataType=1; /*分钟线数据 */
  9119. this.IndexData.Data=hisData;
  9120. if (JSCommonData.ChartData.IsMinutePeriod(this.Period, false)) //周期数据
  9121. {
  9122. let periodData=this.IndexData.GetPeriodData(this.Period);
  9123. this.IndexData.Data=periodData;
  9124. }
  9125. }
  9126. //获取大盘指数缓存数据
  9127. this.GetIndexCacheData=function(dataName)
  9128. {
  9129. if (!this.IndexData) return new Array();
  9130. switch(dataName)
  9131. {
  9132. case 'INDEXA':
  9133. return this.IndexData.GetAmount();
  9134. case 'INDEXC':
  9135. return this.IndexData.GetClose();
  9136. case 'INDEXH':
  9137. return this.IndexData.GetHigh();
  9138. case 'INDEXL':
  9139. return this.IndexData.GetLow();
  9140. case 'INDEXO':
  9141. return this.IndexData.GetOpen();
  9142. case 'INDEXV':
  9143. return this.IndexData.GetVol();
  9144. case 'INDEXADV':
  9145. return this.IndexData.GetUp();
  9146. case 'INDEXDEC':
  9147. return this.IndexData.GetDown();
  9148. }
  9149. }
  9150. //分钟涨幅股票个数统计数据下载
  9151. this.GetIndexIncreaseData = function (job)
  9152. {
  9153. var upKey = job.ID.toString() + '-UpCount-' + job.Symbol;
  9154. var downKey = job.ID.toString() + '-DownCount-' + job.Symbol;
  9155. if (this.ExtendData.has(upKey) && this.ExtendData.has(downKey)) return this.Execute.RunNextJob();
  9156. var symbol = job.Symbol;
  9157. symbol = symbol.replace('.CI', '.ci');
  9158. var self = this;
  9159. var apiUrl = g_JSComplierResource.CacheDomain + '/cache/analyze/increaseanalyze/' + symbol + '.json';
  9160. JSConsole.Complier.Log('[JSSymbolData::GetIndexIncreaseData] Get url=', apiUrl);
  9161. JSNetwork.HttpRequest({
  9162. url: apiUrl,
  9163. method: "GET",
  9164. dataType: "json",
  9165. success: function (data)
  9166. {
  9167. self.RecvMinuteIncreaseData(data, { UpKey: upKey, DownKey: downKey });
  9168. self.Execute.RunNextJob();
  9169. },
  9170. error: function (request)
  9171. {
  9172. self.RecvError(request);
  9173. }
  9174. });
  9175. }
  9176. this.RecvMinuteIncreaseData = function (recvData, key)
  9177. {
  9178. JSConsole.Complier.Log('[JSSymbolData::RecvMinuteIncreaseData] recv data', recvData);
  9179. var data=recvData.data;
  9180. if (!data.minute) return;
  9181. var minuteData = data.minute;
  9182. if (!minuteData.time || !minuteData.up || !minuteData.down) return;
  9183. var upData = [], downData = [];
  9184. for (var i = 0; i < minuteData.time.length; ++i) {
  9185. upData[i] = minuteData.up[i];
  9186. downData[i] = minuteData.down[i];
  9187. }
  9188. this.ExtendData.set(key.UpKey, upData);
  9189. this.ExtendData.set(key.DownKey, downData);
  9190. }
  9191. //分钟涨幅股票个数统计数据
  9192. this.GetIndexIncreaseCacheData = function (funcName, symbol, node) {
  9193. var key;
  9194. if (funcName == 'UPCOUNT') key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA.toString() + '-UpCount-' + symbol;
  9195. else if (funcName == 'DOWNCOUNT') key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA.toString() + '-DownCount-' + symbol;
  9196. if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node, '不支持函数' + funcName + '(' + symbol + ')');
  9197. return this.ExtendData.get(key);
  9198. }
  9199. this.GetSymbolData=function()
  9200. {
  9201. if (this.Data) return this.Execute.RunNextJob();
  9202. let self=this;
  9203. if (this.DataType === 2) //当天分钟数据
  9204. {
  9205. JSNetwork.HttpRequest({
  9206. url: self.RealtimeApiUrl,
  9207. data:
  9208. {
  9209. "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", "amount", "date", "minute", "time", "minutecount"],
  9210. "symbol": [self.Symbol],
  9211. "start": -1
  9212. },
  9213. method: 'POST',
  9214. dataType: "json",
  9215. async: true,
  9216. success: function (recvData) {
  9217. self.RecvMinuteData(recvData);
  9218. self.Execute.RunNextJob();
  9219. }
  9220. });
  9221. return;
  9222. }
  9223. if (JSCommonData.ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
  9224. {
  9225. if (this.NetworkFilter)
  9226. {
  9227. var obj=
  9228. {
  9229. Name:'JSSymbolData::GetSymbolData',
  9230. Explain:"日线数据",
  9231. Request:
  9232. { Url:self.RealtimeApiUrl, Type:'POST' ,
  9233. Data:
  9234. {
  9235. "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
  9236. "symbol": self.Symbol,
  9237. "start": -1,
  9238. "count": self.MaxRequestDataCount,
  9239. "period":this.Period,
  9240. "right":this.Right
  9241. }
  9242. },
  9243. Self:this,
  9244. PreventDefault:false
  9245. };
  9246. if (this.KLineDateTimeRange)
  9247. {
  9248. obj.Request.KLineDataTimeRange={Start:{ Date:this.KLineDateTimeRange.Start.Date}, End:{ Date:this.KLineDateTimeRange.End.Date} };
  9249. if (this.IsNumber(this.KLineDateTimeRange.Start.Time)) obj.Request.KLineDataTimeRange.Start.Time=this.KLineDateTimeRange.Start.Time;
  9250. if (this.IsNumber(this.KLineDateTimeRange.End.Time)) obj.Request.KLineDataTimeRange.End.Time=this.KLineDateTimeRange.End.Time;
  9251. }
  9252. this.NetworkFilter(obj, function(data)
  9253. {
  9254. self.RecvHistroyData(data);
  9255. self.Execute.RunNextJob();
  9256. });
  9257. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9258. }
  9259. JSNetwork.HttpRequest({
  9260. url: self.KLineApiUrl,
  9261. data:
  9262. {
  9263. "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
  9264. "symbol": self.Symbol,
  9265. "start": -1,
  9266. "count": self.MaxRequestDataCount
  9267. },
  9268. method: 'POST',
  9269. dataType: "json",
  9270. async:true,
  9271. success: function (recvData)
  9272. {
  9273. self.RecvHistroyData(recvData);
  9274. self.Execute.RunNextJob();
  9275. },
  9276. error: function(request)
  9277. {
  9278. self.RecvError(request);
  9279. }
  9280. });
  9281. }
  9282. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true)) //请求分钟数据
  9283. {
  9284. if (this.NetworkFilter)
  9285. {
  9286. var obj=
  9287. {
  9288. Name:'JSSymbolData::GetSymbolData',
  9289. Explain:"分钟K线数据",
  9290. Request:
  9291. { Url:self.MinuteKLineApiUrl, Type:'POST' ,
  9292. Data:
  9293. {
  9294. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  9295. "symbol": self.Symbol,
  9296. "start": -1,
  9297. "count": self.MaxRequestMinuteDayCount,
  9298. "period":this.Period,
  9299. "right":this.Right
  9300. }
  9301. },
  9302. Self:this,
  9303. PreventDefault:false
  9304. };
  9305. if (this.KLineDateTimeRange)
  9306. {
  9307. obj.Request.KLineDataTimeRange={Start:{ Date:this.KLineDateTimeRange.Start.Date}, End:{ Date:this.KLineDateTimeRange.End.Date} };
  9308. if (this.IsNumber(this.KLineDateTimeRange.Start.Time)) obj.Request.KLineDataTimeRange.Start.Time=this.KLineDateTimeRange.Start.Time;
  9309. if (this.IsNumber(this.KLineDateTimeRange.End.Time)) obj.Request.KLineDataTimeRange.End.Time=this.KLineDateTimeRange.End.Time;
  9310. }
  9311. this.NetworkFilter(obj, function(data)
  9312. {
  9313. self.RecvMinuteHistroyData(data);
  9314. self.Execute.RunNextJob();
  9315. });
  9316. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9317. }
  9318. JSNetwork.HttpRequest({
  9319. url: this.MinuteKLineApiUrl,
  9320. data:
  9321. {
  9322. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  9323. "symbol": self.Symbol,
  9324. "start": -1,
  9325. "count": self.MaxRequestMinuteDayCount
  9326. },
  9327. method: 'POST',
  9328. dataType: "json",
  9329. async:true,
  9330. success: function (data)
  9331. {
  9332. self.RecvMinuteHistroyData(data);
  9333. self.Execute.RunNextJob();
  9334. },
  9335. error: function(request)
  9336. {
  9337. self.RecvError(request);
  9338. }
  9339. });
  9340. }
  9341. }
  9342. this.RecvHistroyData=function(recvData)
  9343. {
  9344. let data=recvData.data;
  9345. JSConsole.Complier.Log('[JSSymbolData::RecvHistroyData] recv data' , data);
  9346. let hisData=this.JsonDataToHistoryData(data);
  9347. this.Data=new JSCommonData.ChartData();
  9348. this.Data.DataType=0; /*日线数据 */
  9349. this.Data.Data=hisData;
  9350. this.SourceData = new JSCommonData.ChartData;
  9351. this.SourceData.Data = hisData;
  9352. if (this.IsApiPeriod) //后台周期 前端不处理
  9353. {
  9354. }
  9355. else
  9356. {
  9357. if (this.Right>0) //复权
  9358. {
  9359. let rightData=this.Data.GetRightDate(this.Right);
  9360. this.Data.Data=rightData;
  9361. }
  9362. if (JSCommonData.ChartData.IsDayPeriod(this.Period, false)) //周期数据
  9363. {
  9364. let periodData=this.Data.GetPeriodData(this.Period);
  9365. this.Data.Data=periodData;
  9366. }
  9367. }
  9368. this.Data.Right=this.Right;
  9369. this.Data.Period=this.Period;
  9370. this.Name = data.name;
  9371. }
  9372. this.RecvMinuteHistroyData = function (recvData)
  9373. {
  9374. let data = recvData.data;
  9375. JSConsole.Complier.Log('[JSSymbolData::RecvMinuteHistroyData] recv data' , data);
  9376. let hisData=this.JsonDataToMinuteHistoryData(data);
  9377. this.Data = new JSCommonData.ChartData();
  9378. this.Data.DataType=1; /*分钟线数据 */
  9379. this.Data.Data=hisData;
  9380. this.SourceData = new JSCommonData.ChartData;
  9381. this.SourceData.Data = hisData;
  9382. if (this.IsApiPeriod) //后台周期 前端不处理
  9383. {
  9384. }
  9385. else
  9386. {
  9387. if (JSCommonData.ChartData.IsMinutePeriod(this.Period, false)) //周期数据
  9388. {
  9389. let periodData=this.Data.GetPeriodData(this.Period);
  9390. this.Data.Data=periodData;
  9391. }
  9392. }
  9393. this.Data.Period=this.Period;
  9394. this.Name = data.name;
  9395. }
  9396. //最新的分钟数据走势图
  9397. this.RecvMinuteData = function (recvData)
  9398. {
  9399. let data = recvData.data;
  9400. JSConsole.Complier.Log('[JSSymbolData::RecvMinuteData] recv data', data);
  9401. var aryMinuteData = this.JsonDataToMinuteData(data);
  9402. this.Data = new JSCommonData.ChartData();
  9403. this.Data.DataType = 2; /*分钟走势图数据 */
  9404. this.Data.Data = aryMinuteData;
  9405. this.Name = data.stock[0].name;
  9406. }
  9407. this.GetSymbolCacheData=function(dataName)
  9408. {
  9409. if (!this.Data) return new Array();
  9410. var upperSymbol=this.Symbol.toUpperCase();
  9411. switch(dataName)
  9412. {
  9413. case 'CLOSE':
  9414. case 'C':
  9415. return this.Data.GetClose();
  9416. case 'VOL':
  9417. case 'V':
  9418. return this.Data.GetVol(MARKET_SUFFIX_NAME.GetVolUnit(upperSymbol));
  9419. case 'OPEN':
  9420. case 'O':
  9421. return this.Data.GetOpen();
  9422. case 'HIGH':
  9423. case 'H':
  9424. return this.Data.GetHigh();
  9425. case 'LOW':
  9426. case 'L':
  9427. return this.Data.GetLow();
  9428. case 'AMOUNT':
  9429. case 'AMO':
  9430. return this.Data.GetAmount();
  9431. case "OPI": //文华 持仓量
  9432. case 'VOLINSTK':
  9433. return this.Data.GetPosition();
  9434. case "ZSTJJ": //均价
  9435. return this.Data.GetAvPrice();
  9436. case "SETTLE": //文华 结算价
  9437. case "QHJSJ": //通达信 结算价
  9438. return this.Data.GetSettlementPrice(); //结算价
  9439. case "ISEQUAL": //平盘
  9440. return this.Data.GetIsEqual();
  9441. case "ISUP": //收阳
  9442. return this.Data.GetIsUp();
  9443. case "ISDOWN": //收阴
  9444. return this.Data.GetIsDown();
  9445. }
  9446. }
  9447. this.GetCurrBarsCount=function()
  9448. {
  9449. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return new Array();
  9450. let lCount=this.Data.Data.length;
  9451. let result=[];
  9452. for(let i=lCount-1;i>=0;--i)
  9453. result.push(i);
  9454. return result;
  9455. }
  9456. this.GetTotalBarsCount=function()
  9457. {
  9458. let lCount=this.Data.Data.length;
  9459. return lCount;
  9460. }
  9461. this.GetTotalTradeMinuteCount=function()
  9462. {
  9463. var data=g_MinuteCoordinateData.GetCoordinateData(this.Symbol);
  9464. if (data && data.Count>0) return data.Count-1;
  9465. return 242;
  9466. }
  9467. //BARPOS 返回从第一根K线开始到当前的周期数。
  9468. //注:
  9469. //1、BARPOS返回本地已有的K线根数,从本机上存在的数据开始算起。
  9470. //2、本机已有的第一根K线上返回值为1。
  9471. this.GetBarPos=function()
  9472. {
  9473. let result=[];
  9474. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  9475. let lCount=this.Data.Data.length;
  9476. for(let i=0;i<lCount;++i)
  9477. result.push(i+1);
  9478. return result;
  9479. }
  9480. this.GetIsLastBar = function ()
  9481. {
  9482. let result = [];
  9483. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result
  9484. let lCount = this.Data.Data.length;
  9485. for (let i = 0; i < lCount; ++i)
  9486. {
  9487. if (i == lCount - 1) result.push(1);
  9488. else result.push(0);
  9489. }
  9490. return result;
  9491. }
  9492. //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置.
  9493. //例如:BARSTATUS=2表示当天是该数据的最后一个周期.
  9494. this.GetBarStatus=function()
  9495. {
  9496. let result=[];
  9497. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result
  9498. let lCount=this.Data.Data.length;
  9499. for(var i=0 ;i<lCount;++i)
  9500. {
  9501. if (i==0) result[i]=1;
  9502. else if (i==lCount-1) result[i]=2;
  9503. else result[i]=0;
  9504. }
  9505. return result;
  9506. }
  9507. //融资融券函数
  9508. this.GetMarginCacheData = function (id, node)
  9509. {
  9510. let jobID = JS_EXECUTE_JOB_ID.GetMarginJobID(id);
  9511. if (!jobID) this.Execute.ThrowUnexpectedNode(node, '不支持MARGIN(' + id + ')');
  9512. if (this.MarginData.has(jobID)) return this.MarginData.get(jobID);
  9513. return [];
  9514. }
  9515. //下融资融券
  9516. this.GetMarginData = function (jobID)
  9517. {
  9518. if (this.MarginData.has(jobID)) return this.Execute.RunNextJob();
  9519. JSConsole.Complier.Log('[JSSymbolData::GetMarginData] jobID=', jobID);
  9520. var self = this;
  9521. let fieldList = ["name", "date", "symbol"];
  9522. switch (jobID)
  9523. {
  9524. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE: //融资融券余额
  9525. fieldList.push("margin.balance");
  9526. break;
  9527. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE: //融资占比
  9528. fieldList.push("margin.rate");
  9529. break;
  9530. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
  9531. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
  9532. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
  9533. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
  9534. fieldList.push("margin.buy");
  9535. break;
  9536. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
  9537. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
  9538. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
  9539. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
  9540. fieldList.push("margin.sell");
  9541. break;
  9542. }
  9543. //请求数据
  9544. JSNetwork.HttpRequest({
  9545. url: this.StockHistoryDayApiUrl,
  9546. data:
  9547. {
  9548. "field": fieldList,
  9549. "symbol": [this.Symbol],
  9550. "orderfield": "date"
  9551. },
  9552. method: 'POST',
  9553. dataType: "json",
  9554. async: true,
  9555. success: function (recvData) {
  9556. self.RecvMarginData(recvData, jobID);
  9557. self.Execute.RunNextJob();
  9558. }
  9559. });
  9560. }
  9561. this.RecvMarginData = function (recvData, jobID)
  9562. {
  9563. var data = recvData.data;
  9564. //JSConsole.Complier.Log(data);
  9565. if (!data.stock || data.stock.length != 1) return;
  9566. let stock = data.stock[0];
  9567. var aryData = new Array();
  9568. var aryData2 = [], aryData3 = [], aryData4 = []; //其他3个数据
  9569. for (let i in stock.stockday)
  9570. {
  9571. var item = stock.stockday[i];
  9572. var marginData = item.margin;
  9573. if (!marginData) continue;
  9574. let indexData = new JSCommonData.SingleData();
  9575. indexData.Date = item.date;
  9576. switch (jobID)
  9577. {
  9578. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE:
  9579. if (!this.IsNumber(marginData.balance)) continue;
  9580. indexData.Value = marginData.balance; //融资融券余额
  9581. aryData.push(indexData);
  9582. break;
  9583. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE:
  9584. if (!this.IsNumber(marginData.rate)) continue;
  9585. indexData.Value = marginData.rate; //融资占比
  9586. aryData.push(indexData);
  9587. break;
  9588. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
  9589. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
  9590. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
  9591. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
  9592. var buyData = marginData.buy;
  9593. if (!buyData) continue;
  9594. if (!this.IsNumber(buyData.balance) || !this.IsNumber(buyData.amount) || !this.IsNumber(buyData.repay) || !this.IsNumber(buyData.net)) continue;
  9595. indexData.Value = buyData.balance;
  9596. var indexData2 = new JSCommonData.SingleData();
  9597. indexData2.Date = item.date;
  9598. indexData2.Value = buyData.amount;
  9599. var indexData3 = new JSCommonData.SingleData();
  9600. indexData3.Date = item.date;
  9601. indexData3.Value = buyData.repay;
  9602. var indexData4 = new JSCommonData.SingleData();
  9603. indexData4.Date = item.date;
  9604. indexData4.Value = buyData.net;
  9605. aryData.push(indexData);
  9606. aryData2.push(indexData2);
  9607. aryData3.push(indexData3);
  9608. aryData4.push(indexData4);
  9609. break;
  9610. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
  9611. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
  9612. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
  9613. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
  9614. var sellData = marginData.sell;
  9615. if (!sellData) continue;
  9616. if (!this.IsNumber(sellData.balance) || !this.IsNumber(sellData.volume) || !this.IsNumber(sellData.repay) || !this.IsNumber(sellData.net)) continue;
  9617. indexData.Value = buyData.balance;
  9618. var indexData2 = new JSCommonData.SingleData();
  9619. indexData2.Date = item.date;
  9620. indexData2.Value = buyData.volume;
  9621. var indexData3 = new JSCommonData.SingleData();
  9622. indexData3.Date = item.date;
  9623. indexData3.Value = buyData.repay;
  9624. var indexData4 = new JSCommonData.SingleData();
  9625. indexData4.Date = item.date;
  9626. indexData4.Value = buyData.net;
  9627. aryData.push(indexData);
  9628. aryData2.push(indexData2);
  9629. aryData3.push(indexData3);
  9630. aryData4.push(indexData4);
  9631. break;
  9632. default:
  9633. continue;
  9634. }
  9635. }
  9636. var allData = [];
  9637. if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE)
  9638. {
  9639. allData.push({ JobID: jobID, Data: aryData });
  9640. }
  9641. else if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT ||
  9642. jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET)
  9643. {
  9644. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE, Data: aryData });
  9645. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT, Data: aryData2 });
  9646. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY, Data: aryData3 });
  9647. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET, Data: aryData4 });
  9648. }
  9649. else if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME ||
  9650. jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET)
  9651. {
  9652. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE, Data: aryData });
  9653. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME, Data: aryData2 });
  9654. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY, Data: aryData3 });
  9655. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET, Data: aryData4 });
  9656. }
  9657. for (let i in allData)
  9658. {
  9659. let aryFixedData = this.Data.GetFittingData(allData[i].Data);
  9660. var bindData = new JSCommonData.ChartData();
  9661. bindData.Data = aryFixedData;
  9662. bindData.Period = this.Period; //周期
  9663. if (bindData.Period > 0) //周期数据
  9664. {
  9665. var periodData = bindData.GetPeriodSingleData(bindData.Period);
  9666. bindData.Data = periodData;
  9667. }
  9668. let data = bindData.GetValue();
  9669. this.MarginData.set(allData[i].JobID, data);
  9670. }
  9671. }
  9672. this.GetNewsAnalysisCacheData = function (id, node)
  9673. {
  9674. let jobID = JS_EXECUTE_JOB_ID.GetNewsAnalysisID(id);
  9675. if (!jobID) this.Execute.ThrowUnexpectedNode(node, '不支持NEWS(' + id + ')');
  9676. if (this.NewsAnalysisData.has(jobID)) return this.NewsAnalysisData.get(jobID);
  9677. return [];
  9678. }
  9679. //下载新闻统计
  9680. this.GetNewsAnalysisData = function (jobID)
  9681. {
  9682. if (this.NewsAnalysisData.has(jobID)) return this.Execute.RunNextJob();
  9683. var self = this;
  9684. var mapFolder = new Map([
  9685. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE, "negative"],
  9686. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH, 'research'],
  9687. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT, 'interact'],
  9688. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE, 'holderchange'], //NEWS(4) 股东增持
  9689. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2, 'holderchange'], //NEWS(5) 股东减持
  9690. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER, 'trustholder'], //NEWS(6) 信托持股
  9691. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING, 'Blocktrading'], //NEWS(7) 大宗交易
  9692. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS, 'companynews'], //NEWS(8) 官网新闻
  9693. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS, 'topmanagers'], //NEWS(9) 高管要闻
  9694. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE, 'Pledge'], //NEWS(10) 股权质押
  9695. ]);
  9696. if (!mapFolder.has(jobID))
  9697. {
  9698. this.Execute.RunNextJob();
  9699. return;
  9700. }
  9701. var folderName = mapFolder.get(jobID);
  9702. var url = this.StockNewsAnalysisApiUrl + '/' + folderName + '/' + this.Symbol + '.json';
  9703. //请求数据
  9704. JSNetwork.HttpRequest({
  9705. url: url,
  9706. method: 'GET',
  9707. dataType: "json",
  9708. async: true,
  9709. success: function (recvData)
  9710. {
  9711. if (recvData.statusCode==200)
  9712. self.RecvNewsAnalysisData(recvData, jobID);
  9713. else
  9714. self.RecvNewsAnalysisDataError(recvData, jobID);
  9715. self.Execute.RunNextJob();
  9716. },
  9717. fail: function (request, textStatus)
  9718. {
  9719. //self.RecvNewsAnalysisDataError(request, textStatus, jobID);
  9720. self.Execute.RunNextJob();
  9721. }
  9722. });
  9723. }
  9724. this.RecvNewsAnalysisDataError = function (recvData, jobID)
  9725. {
  9726. JSConsole.Complier.Log('[JSSymbolData::RecvNewsAnalysisDataError] request error.', recvData.statusCode);
  9727. //没有新闻使用0数据填充
  9728. var aryData = [];
  9729. for (var i = 0; i < this.Data.Data.length; ++i)
  9730. {
  9731. var item = new JSCommonData.SingleData();
  9732. item.Date = this.Data.Data[i].Date;
  9733. item.Value = 0
  9734. aryData.push(item);
  9735. }
  9736. var bindData = new JSCommonData.ChartData();
  9737. bindData.Data = aryData;
  9738. this.NewsAnalysisData.set(jobID, bindData.GetValue());
  9739. }
  9740. this.RecvNewsAnalysisData = function (recvData, jobID)
  9741. {
  9742. var data=recvData.data;
  9743. if (!data.data || !data.date) return;
  9744. if (data.data.length <= 0 || data.data.length != data.date.length) return;
  9745. JSConsole.Complier.Log('[JSSymbolData::RecvNewsAnalysisData] jobID', jobID, data.update);
  9746. if (jobID == JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE || jobID == JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2)
  9747. {
  9748. var aryData = [], aryData2 = [];
  9749. for (var i = 0; i < data.data.length; ++i)
  9750. {
  9751. var item = new JSCommonData.SingleData();
  9752. item.Date = data.date[i];
  9753. item.Value = data.data[i];
  9754. if (this.IsNumber(item.Value)) aryData.push(item);
  9755. if (i < data.data2.length)
  9756. {
  9757. item = new JSCommonData.SingleData();
  9758. item.Date = data.date[i];
  9759. item.Value = data.data2[i];
  9760. if (this.IsNumber(item.Value)) aryData2.push(item);
  9761. }
  9762. }
  9763. let aryFixedData = this.Data.GetFittingData2(aryData, 0);
  9764. var bindData = new JSCommonData.ChartData();
  9765. bindData.Data = aryFixedData;
  9766. this.NewsAnalysisData.set(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE, bindData.GetValue());
  9767. aryFixedData = this.Data.GetFittingData2(aryData2, 0);
  9768. bindData = new JSCommonData.ChartData();
  9769. bindData.Data = aryFixedData;
  9770. this.NewsAnalysisData.set(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2, bindData.GetValue());
  9771. }
  9772. else
  9773. {
  9774. var aryData = [];
  9775. for (var i = 0; i < data.data.length; ++i)
  9776. {
  9777. var item = new JSCommonData.SingleData();
  9778. item.Date = data.date[i];
  9779. item.Value = data.data[i];
  9780. aryData.push(item);
  9781. }
  9782. let aryFixedData = this.Data.GetFittingData2(aryData, 0);
  9783. var bindData = new JSCommonData.ChartData();
  9784. bindData.Data = aryFixedData;
  9785. this.NewsAnalysisData.set(jobID, bindData.GetValue());
  9786. }
  9787. }
  9788. this.GetStockDataKey=function(jobItem, aryArgs)
  9789. {
  9790. var key=jobItem.FunctionName;
  9791. if (aryArgs.length>0)
  9792. {
  9793. key+="(";
  9794. for(var i=0;i<aryArgs.length;++i)
  9795. {
  9796. if (i>0) key+=",";
  9797. key+=aryArgs[i].toString();
  9798. }
  9799. key+=")";
  9800. }
  9801. return key;
  9802. }
  9803. this.GetFinance=function(jobItem)
  9804. {
  9805. var aryArgs=this.JobArgumentsToArray(jobItem, 1);
  9806. var lID=aryArgs[0];
  9807. var key=this.GetStockDataKey(jobItem,aryArgs);
  9808. if (this.StockData.has(key)) return this.Execute.RunNextJob();
  9809. var self=this;
  9810. if (this.NetworkFilter)
  9811. {
  9812. var dateRange=this.Data.GetDateRange();
  9813. var obj=
  9814. {
  9815. Name:'JSSymbolData::GetFinance', //类名::
  9816. Explain:'财务数据FINANCE(ID)',
  9817. JobID:jobItem.ID,
  9818. Request:{ Url:self.RealtimeApiUrl, Type:'POST', Data:{ id:lID, symbol: this.Symbol, daterange:dateRange } },
  9819. Self:this,
  9820. PreventDefault:false
  9821. };
  9822. this.NetworkFilter(obj, function(recvData)
  9823. {
  9824. self.RecvStockValue(recvData,jobItem,key,0);
  9825. self.Execute.RunNextJob();
  9826. });
  9827. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9828. }
  9829. var apiDownload=new DownloadFinanceData(
  9830. {
  9831. Job:jobItem,
  9832. Symbol:this.Symbol,
  9833. Url:this.StockHistoryDayApiUrl,
  9834. RealtimeUrl:this.RealtimeApiUrl,
  9835. Args:aryArgs,
  9836. DataKey:key,
  9837. Callback:function(recvData, jobItem, key)
  9838. {
  9839. self.RecvStockValue(recvData, jobItem, key,0);
  9840. self.Execute.RunNextJob();
  9841. },
  9842. ErrorCallback:function(strError)
  9843. {
  9844. self.AddStockValueError(key,strError);
  9845. }
  9846. });
  9847. apiDownload.Download();
  9848. }
  9849. this.GetVariantData=function(jobItem)
  9850. {
  9851. var key=jobItem.VariantName;
  9852. if (this.StockData.has(key)) return this.Execute.RunNextJob();
  9853. var self=this;
  9854. if (this.NetworkFilter)
  9855. {
  9856. var dateRange=this.Data.GetDateRange();
  9857. var obj=
  9858. {
  9859. Name:'JSSymbolData::GetVariantData', //类名::
  9860. Explain:'变量数据下载',
  9861. JobID:jobItem.ID,
  9862. Request:{ Url:"数据地址", Type:'POST', Data:{ VariantName:jobItem.VariantName, symbol: this.Symbol, daterange:dateRange } },
  9863. Self:this,
  9864. PreventDefault:false
  9865. };
  9866. this.NetworkFilter(obj, function(recvData)
  9867. {
  9868. if (recvData.Error)
  9869. {
  9870. self.AddStockValueError(key,recvData.Error);
  9871. }
  9872. else
  9873. {
  9874. var dataType=0;
  9875. if (IFrameSplitOperator.IsNumber(recvData.DataType)) dataType=recvData.DataType;
  9876. self.RecvStockValue(recvData.Data,jobItem,key,dataType);
  9877. }
  9878. self.Execute.RunNextJob();
  9879. });
  9880. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9881. }
  9882. var errorCallback=function(strError)
  9883. {
  9884. self.AddStockValueError(key,strError);
  9885. };
  9886. var apiDownload;
  9887. if (jobItem.VariantName=="CAPITAL" || jobItem.VariantName=="TOTALCAPITAL" || jobItem.VariantName=="EXCHANGE")
  9888. {
  9889. var callback=function(recvData, jobItem, key)
  9890. {
  9891. self.RecvStockValue(recvData, jobItem, key,0);
  9892. self.Execute.RunNextJob();
  9893. };
  9894. apiDownload=new DownloadFinanceData(
  9895. {
  9896. Job:jobItem,
  9897. Symbol:this.Symbol,
  9898. Url:this.StockHistoryDayApiUrl,
  9899. RealtimeUrl:this.RealtimeApiUrl,
  9900. Args:[jobItem.VariantName],
  9901. DataKey:key,
  9902. Callback:callback,
  9903. ErrorCallback:errorCallback
  9904. });
  9905. }
  9906. else if (jobItem.VariantName=="HYBLOCK" || jobItem.VariantName=="DYBLOCK" || jobItem.VariantName=="GNBLOCK")
  9907. {
  9908. var callback=function(recvData, jobItem, key, dataType)
  9909. {
  9910. self.RecvStockValue(recvData, jobItem, key, dataType);
  9911. self.Execute.RunNextJob();
  9912. };
  9913. apiDownload=new DownloadGroupData(
  9914. {
  9915. Job:jobItem,
  9916. Symbol:this.Symbol,
  9917. Url:this.StockHistoryDayApiUrl,
  9918. RealtimeUrl:this.RealtimeApiUrl,
  9919. Args:[jobItem.VariantName],
  9920. DataKey:key,
  9921. Callback:callback,
  9922. ErrorCallback:errorCallback
  9923. });
  9924. }
  9925. else if (jobItem.VariantName=="INBLOCK")
  9926. {
  9927. var errorMessage=`${jobItem.VariantName}, 请对接外部数据.`;
  9928. this.AddStockValueError(key,errorMessage);
  9929. this.Execute.RunNextJob();
  9930. return;
  9931. }
  9932. else
  9933. {
  9934. var errorMessage=`不支持变量${jobItem.VariantName}, 请对接外部数据.`;
  9935. this.AddStockValueError(key,errorMessage);
  9936. this.Execute.RunNextJob();
  9937. return;
  9938. }
  9939. apiDownload.Download();
  9940. }
  9941. this.GetProFinance=function(jobItem)
  9942. {
  9943. var jobID=jobItem.ID;
  9944. var finder=null;
  9945. for(var i=0;i<JS_ARRAY_PROFESSIONAL_FINANCE.length;++i)
  9946. {
  9947. var item=JS_ARRAY_PROFESSIONAL_FINANCE[i];
  9948. if (item.JobID==jobID)
  9949. {
  9950. finder=item;
  9951. break;
  9952. }
  9953. }
  9954. if (!finder) return this.Execute.RunNextJob();
  9955. var aryArgs=this.JobArgumentsToArray(jobItem, finder.ArgCount);
  9956. var key=this.GetStockDataKey(jobItem,aryArgs);
  9957. if (this.StockData.has(key)) return this.Execute.RunNextJob();
  9958. var self=this;
  9959. var dataType=0;
  9960. if ([JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE,JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE,JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE].includes(jobID))
  9961. {
  9962. dataType=aryArgs[2]==1?0:2; //TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
  9963. }
  9964. if (this.NetworkFilter)
  9965. {
  9966. var dateRange=this.Data.GetDateRange();
  9967. var obj=
  9968. {
  9969. Name:finder.FuncName, //类名::
  9970. Explain:finder.Explain,
  9971. JobID:jobID,
  9972. Request:{ Url:self.StockHistoryDayApiUrl, Type:'POST', Data:{ Args:aryArgs, symbol: this.Symbol, daterange:dateRange } },
  9973. Self:this,
  9974. PreventDefault:false
  9975. };
  9976. this.NetworkFilter(obj, function(recvData)
  9977. {
  9978. self.RecvStockValue(recvData,jobItem,key,dataType);
  9979. self.Execute.RunNextJob();
  9980. });
  9981. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9982. }
  9983. JSConsole.Chart.Warn(`[JSSymbolData::GetProFinance] ${finder.FuncName} Not implemented.`);
  9984. }
  9985. //自定义变量数据下载
  9986. this.GetCustomVariantData=function(jobItem)
  9987. {
  9988. var key=jobItem.VariantName;
  9989. if (this.StockData.has(key)) return this.Execute.RunNextJob();
  9990. var variantInfo=g_JSComplierResource.CustomVariant.Data.get(key);
  9991. var self=this;
  9992. if (this.NetworkFilter)
  9993. {
  9994. var dateRange=this.Data.GetDateRange();
  9995. var obj=
  9996. {
  9997. Name:'JSSymbolData::GetCustomVariantData', //类名::函数名
  9998. Explain:'自定义变量数据下载',
  9999. JobID:jobItem.ID,
  10000. Request:{ Url:"数据地址", Type:'POST', Data:{ VariantName:jobItem.VariantName, symbol: this.Symbol, daterange:dateRange } },
  10001. Self:this,
  10002. VariantInfo:variantInfo,
  10003. PreventDefault:false
  10004. };
  10005. this.NetworkFilter(obj, function(recvData)
  10006. {
  10007. if (recvData.Error) self.AddStockValueError(key,recvData.Error);
  10008. else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
  10009. self.Execute.RunNextJob();
  10010. });
  10011. }
  10012. else
  10013. {
  10014. this.AddStockValueError(key, `自定义变量${key}下载失败`);
  10015. this.Execute.RunNextJob();
  10016. }
  10017. }
  10018. this.GetCustomFunctionData=function(jobItem)
  10019. {
  10020. var key=jobItem.FunctionName;
  10021. var functionInfo=g_JSComplierResource.CustomFunction.Data.get(key);
  10022. if (!functionInfo.IsDownload) return this.Execute.RunNextJob();
  10023. if (this.StockData.has(key)) return this.Execute.RunNextJob(); //一个函数只能缓存一个数据, 保存多个外部自己保存
  10024. var self=this;
  10025. if (this.NetworkFilter)
  10026. {
  10027. var dateRange=this.Data.GetDateRange();
  10028. var obj=
  10029. {
  10030. Name:'JSSymbolData::GetCustomFunctionData', //类名::函数名
  10031. Explain:'自定义函数数据下载',
  10032. JobID:jobItem.ID,
  10033. Request:
  10034. {
  10035. Url:"数据地址", Type:'POST',
  10036. Data:
  10037. {
  10038. FunctionName:jobItem.FunctionName,
  10039. symbol: this.Symbol, daterange:dateRange,
  10040. JobItem:jobItem //函数编译信息
  10041. }
  10042. },
  10043. Self:this,
  10044. FunctionInfo:functionInfo,
  10045. PreventDefault:false
  10046. };
  10047. this.NetworkFilter(obj, function(recvData)
  10048. {
  10049. if (recvData.Error) self.AddStockValueError(key,recvData.Error);
  10050. else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
  10051. self.Execute.RunNextJob();
  10052. });
  10053. }
  10054. else
  10055. {
  10056. this.AddStockValueError(key, `自定义函数${key}下载失败`);
  10057. this.Execute.RunNextJob();
  10058. }
  10059. }
  10060. this.GetCustomFunctionDataV2=function(jobItem)
  10061. {
  10062. var funcName=jobItem.FunctionName;
  10063. var functionInfo=g_JSComplierResource.CustomDataFunction.Data.get(funcName);
  10064. if (!functionInfo) return;
  10065. var aryArgs=this.JobArgumentsToArray(jobItem, functionInfo.ArgCount);
  10066. var key=this.GetStockDataKey(jobItem,aryArgs);
  10067. if (this.StockData.has(key)) return this.Execute.RunNextJob(); //一个函数只能缓存一个数据, 保存多个外部自己保存
  10068. var self=this;
  10069. if (this.NetworkFilter)
  10070. {
  10071. var dateRange=this.Data.GetDateRange();
  10072. var obj=
  10073. {
  10074. Name:'JSSymbolData::GetCustomFunctionData', //类名::函数名
  10075. Explain:'自定义函数数据下载',
  10076. JobID:jobItem.ID,
  10077. Request:
  10078. {
  10079. Url:"数据地址", Type:'POST',
  10080. Data:
  10081. {
  10082. FunctionName:jobItem.FunctionName,
  10083. symbol: this.Symbol, daterange:dateRange,
  10084. JobItem:jobItem, //函数编译信息
  10085. Key:key,
  10086. period:this.Period,
  10087. right:this.Right,
  10088. }
  10089. },
  10090. Self:this,
  10091. FunctionInfo:functionInfo,
  10092. PreventDefault:false
  10093. };
  10094. this.NetworkFilter(obj, function(recvData)
  10095. {
  10096. if (recvData.Error) self.AddStockValueError(key,recvData.Error);
  10097. else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
  10098. self.Execute.RunNextJob();
  10099. });
  10100. }
  10101. else
  10102. {
  10103. this.AddStockValueError(key, `自定义函数${key}下载失败`);
  10104. this.Execute.RunNextJob();
  10105. }
  10106. }
  10107. this.RecvStockValue=function(recvData,jobItem,key,dataType)
  10108. {
  10109. if (!recvData)
  10110. {
  10111. JSConsole.Complier.Log(`[JSSymbolData::RecvStockValue] key=${key} data is null`);
  10112. return;
  10113. }
  10114. if (dataType==0)
  10115. {
  10116. if (Array.isArray(recvData))
  10117. {
  10118. var kdata=this.Data; //K线
  10119. var aryFittingData;
  10120. if (this.DataType==HQ_DATA_TYPE.KLINE_ID)
  10121. {
  10122. if (JSCommonData.ChartData.IsDayPeriod(this.Period,true))
  10123. aryFittingData=kdata.GetFittingFinanceData(recvData); //数据和主图K线拟合
  10124. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period,true))
  10125. aryFittingData=kdata.GetMinuteFittingFinanceData(recvData); //数据和主图K线拟合
  10126. else
  10127. return;
  10128. }
  10129. else
  10130. {
  10131. aryFittingData=kdata.GetMinuteFittingFinanceData(recvData); //数据和主图分时拟合
  10132. }
  10133. var bindData=new JSCommonData.ChartData();
  10134. bindData.Data=aryFittingData;
  10135. var result=bindData.GetValue();
  10136. if (key=="EXCHANGE") //计算换手率=成交量/流通股本*100
  10137. {
  10138. for(var i in result)
  10139. {
  10140. var kitem=kdata.Data[i];
  10141. if (result[i]>0)
  10142. result[i]=kitem.Vol/result[i] * 100;
  10143. }
  10144. }
  10145. this.StockData.set(key,{ Data:result });
  10146. }
  10147. else
  10148. {
  10149. this.StockData.set(key,{ Data:recvData.Value });
  10150. }
  10151. }
  10152. else if (dataType==1) //单数值
  10153. {
  10154. this.StockData.set(key,{ Data:recvData.Value });
  10155. }
  10156. else if (dataType==2) //数据不做平滑处理
  10157. {
  10158. var kdata=this.Data; //K线
  10159. var aryFittingData;
  10160. if (this.DataType==HQ_DATA_TYPE.KLINE_ID)
  10161. {
  10162. if (JSCommonData.ChartData.IsDayPeriod(this.Period,true))
  10163. aryFittingData=kdata.GetFittingTradeData(recvData, 0, false); //数据和主图K线拟合
  10164. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period,true))
  10165. aryFittingData=kdata.GetMinuteFittingTradeData(recvData, 0, false); //数据和主图K线拟合
  10166. else
  10167. return;
  10168. }
  10169. else
  10170. {
  10171. aryFittingData=kdata.GetMinuteFittingTradeData(recvData, 0); //数据和主图分钟拟合
  10172. }
  10173. var bindData=new JSCommonData.ChartData();
  10174. bindData.Data=aryFittingData;
  10175. var result=bindData.GetValue();
  10176. this.StockData.set(key,{ Data:result });
  10177. }
  10178. }
  10179. this.AddStockValueError=function(key, message)
  10180. {
  10181. this.StockData.set(key,{ Error:message });
  10182. }
  10183. this.GetStockCacheData=function(obj)
  10184. {
  10185. var key;
  10186. if (obj.FunctionName)
  10187. key=this.GetStockDataKey({FunctionName:obj.FunctionName}, obj.Args);
  10188. else if (obj.VariantName)
  10189. key=obj.VariantName;
  10190. else if (obj.CustomName)
  10191. key=obj.CustomName; //自定义名字
  10192. else
  10193. return null;
  10194. if (!this.StockData.has(key)) return null;
  10195. var data=this.StockData.get(key);
  10196. if (data.Error) this.Execute.ThrowUnexpectedNode(obj.Node, data.Error);
  10197. return data.Data;
  10198. }
  10199. this.IsInBlock=function(blockName, node)
  10200. {
  10201. var data=this.GetStockCacheData({ VariantName:"INBLOCK", Node:node });
  10202. if (!data) return 0;
  10203. var aryBlock=data.split('|');
  10204. for(var i=0; i<aryBlock.length; ++i)
  10205. {
  10206. var item=aryBlock[i];
  10207. if (item==blockName) return 1;
  10208. }
  10209. return 0;
  10210. }
  10211. /*
  10212. 飞狐函数 SYSPARAM
  10213. SYSPARAM(1)画面上光标位置(K线序号)
  10214. SYSPARAM(2)主图可见K线最初位置
  10215. SYSPARAM(3)主图可见K线最后位置,注意:该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
  10216. SYSPARAM(4)主图可见K线最高价,注意:该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
  10217. SYSPARAM(5)主图可见K线最低价,注意:该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
  10218. SYSPARAM(6)画面上光标数值,注意:该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
  10219. */
  10220. this.SysParam=function(id, jsExec)
  10221. {
  10222. if (!this.DrawInfo) return [];
  10223. if (id==2)
  10224. {
  10225. jsExec.IsUsePageData=true;
  10226. if (IFrameSplitOperator.IsNumber(this.DrawInfo.Start))
  10227. return this.DrawInfo.Start+1;
  10228. }
  10229. else if (id==3)
  10230. {
  10231. jsExec.IsUsePageData=true;
  10232. if (IFrameSplitOperator.IsNumber(this.DrawInfo.End))
  10233. return this.DrawInfo.End+1;
  10234. }
  10235. else if (id==4)
  10236. {
  10237. jsExec.IsUsePageData=true;
  10238. if (!IFrameSplitOperator.IsNumber(this.DrawInfo.End) ||!IFrameSplitOperator.IsNumber(this.DrawInfo.Start)) return [];
  10239. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return [];
  10240. var high=null;
  10241. for(var i=this.DrawInfo.Start; i<=this.DrawInfo.End && i<this.Data.Data.length; ++i)
  10242. {
  10243. var item=this.Data.Data[i];
  10244. if (!IFrameSplitOperator.IsNumber(item.High)) continue;
  10245. if (high==null) high=item.High;
  10246. else if(high<item.High) high=item.High;
  10247. }
  10248. return high;
  10249. }
  10250. else if (id==5)
  10251. {
  10252. jsExec.IsUsePageData=true;
  10253. if (!IFrameSplitOperator.IsNumber(this.DrawInfo.End) ||!IFrameSplitOperator.IsNumber(this.DrawInfo.Start)) return [];
  10254. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return [];
  10255. var low=null;
  10256. for(var i=this.DrawInfo.Start;i<=this.DrawInfo.End && i<this.Data.Data.length;++i)
  10257. {
  10258. var item=this.Data.Data[i];
  10259. if (!IFrameSplitOperator.IsNumber(item.Low)) continue;
  10260. if (low==null) low=item.Low;
  10261. else if(low>item.Low) low=item.Low;
  10262. }
  10263. return low;
  10264. }
  10265. return [];
  10266. }
  10267. this.JobArgumentsToArray=function(job, lCount)
  10268. {
  10269. var args=job.Args;
  10270. if (args.length!=lCount)
  10271. {
  10272. var token=job.Token;
  10273. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: argument count error.`);
  10274. }
  10275. var aryValue=[];
  10276. for(var i=0;i<args.length;++i)
  10277. {
  10278. var item=args[i];
  10279. if (this.IsNumber(item))
  10280. {
  10281. aryValue.push(item);
  10282. }
  10283. else if (item.Type==Syntax.Literal)
  10284. {
  10285. aryValue.push(item.Value);
  10286. }
  10287. else if (item.Type==Syntax.Identifier) //变量 !!只支持默认的变量值
  10288. {
  10289. var isFind=false;
  10290. for(var j in this.Arguments)
  10291. {
  10292. const argItem=this.Arguments[j];
  10293. if (argItem.Name==item.Name)
  10294. {
  10295. aryValue.push(argItem.Value);
  10296. isFind=true;
  10297. break;
  10298. }
  10299. }
  10300. if (!isFind)
  10301. {
  10302. var token=job.Token;
  10303. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: can't read ${item.Name}`);
  10304. }
  10305. }
  10306. }
  10307. return aryValue;
  10308. }
  10309. this.DownloadCustomAPIData = function (job)
  10310. {
  10311. if (!this.NetworkFilter) return this.Execute.RunNextJob();
  10312. var args = [];
  10313. for (var i in job.Args)
  10314. {
  10315. var item = job.Args[i];
  10316. if (item.Type == Syntax.Literal)
  10317. {
  10318. args.push(item.Value);
  10319. }
  10320. else if (item.Type == Syntax.Identifier) //变量 !!只支持默认的变量值
  10321. {
  10322. var isFind = false;
  10323. for (var j in this.Arguments)
  10324. {
  10325. const argItem = this.Arguments[j];
  10326. if (argItem.Name == item.Name)
  10327. {
  10328. args.push(argItem.Value);
  10329. isFind = true;
  10330. break;
  10331. }
  10332. }
  10333. if (!isFind)
  10334. {
  10335. var token = job.Token;
  10336. this.Execute.ErrorHandler.ThrowError(token.Index, token.Line, 0, `LoadAPIData() Error: can't read ${item.Name}`);
  10337. }
  10338. }
  10339. else
  10340. {
  10341. return this.Execute.RunNextJob();
  10342. }
  10343. }
  10344. var self = this;
  10345. var obj =
  10346. {
  10347. Name: 'JSSymbolData::DownloadCustomAPIData', //类名::函数名
  10348. Explain: '下载自定义api数据',
  10349. Period: this.Period,
  10350. Right: this.Right,
  10351. Symbol: this.Symbol,
  10352. KData: this.Data, //K线数据
  10353. Cache: this.CustomAPIData,
  10354. Args: args,
  10355. Self: this,
  10356. PreventDefault: false
  10357. };
  10358. this.NetworkFilter(obj, function (data) {
  10359. self.RecvCustomAPIData(data, args);
  10360. self.Execute.RunNextJob();
  10361. });
  10362. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  10363. this.Execute.RunNextJob();
  10364. }
  10365. this.RecvCustomAPIData = function (recvData, args)
  10366. {
  10367. if (!recvData || !recvData.data) return;
  10368. var data = recvData.data;
  10369. var apiKey = this.GenerateCustomAPIKey(args);
  10370. if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true))
  10371. {
  10372. if (!data.date || !data.time) return;
  10373. var date = data.date;
  10374. var time = data.time;
  10375. for (var key in data)
  10376. {
  10377. if (key == 'date' || key == 'time') continue;
  10378. var item = data[key];
  10379. }
  10380. }
  10381. else if (JSCommonData.ChartData.IsDayPeriod(this.Period, true))
  10382. {
  10383. if (!data.date) return;
  10384. var date = data.date;
  10385. var result = { __Type__: "Object" };
  10386. for (var key in data) {
  10387. if (key == 'date') continue;
  10388. var item = data[key];
  10389. if (Array.isArray(item))
  10390. {
  10391. var value = this.FittingCustomAPIArray(item, date);
  10392. result[key] = value;
  10393. }
  10394. else if (this.IsNumber(item))
  10395. {
  10396. result[key] = item;
  10397. }
  10398. }
  10399. this.CustomAPIData.set(apiKey, result);
  10400. }
  10401. }
  10402. this.FittingCustomAPIArray = function (data, date, time)
  10403. {
  10404. var kdata = this.Data; //K线
  10405. var arySingleData = [];
  10406. for (var i in data)
  10407. {
  10408. var value = data[i];
  10409. var indexItem = new JSCommonData.SingleData(); //单列指标数据
  10410. indexItem.Date = date[i];
  10411. if (time && i < time.length) indexItem.Time = time[i];
  10412. indexItem.Value = value;
  10413. arySingleData.push(indexItem);
  10414. }
  10415. var aryFittingData;
  10416. if (JSCommonData.ChartData.IsDayPeriod(this.Period, true))
  10417. aryFittingData = kdata.GetFittingData(arySingleData); //数据和主图K线拟合
  10418. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true))
  10419. aryFittingData = kdata.GetMinuteFittingData(arySingleData); //数据和主图K线拟合
  10420. else
  10421. return null;
  10422. var bindData = new JSCommonData.ChartData();
  10423. bindData.Data = aryFittingData;
  10424. var result = bindData.GetValue();
  10425. return result;
  10426. }
  10427. //MA.MA1#WEEK
  10428. this.ReadIndexFunctionValue=function(item, result) //返回 {Period:周期, Out:输出变量, Error:, Name:脚本名字 }
  10429. {
  10430. var indexParam={};
  10431. if (typeof(item)=== 'object')
  10432. {
  10433. if (!this.ReadArgumentValue(item,indexParam))
  10434. {
  10435. result.Error=indexParam.Error;
  10436. return false;
  10437. }
  10438. }
  10439. else
  10440. {
  10441. indexParam.Value=item;
  10442. }
  10443. var pos=indexParam.Value.indexOf("\.");
  10444. if (pos!=-1)
  10445. {
  10446. result.Name=indexParam.Value.slice(0, pos); //名字
  10447. var pos2=indexParam.Value.indexOf('#', pos+1);
  10448. if (pos2!=-1)
  10449. {
  10450. result.Out=indexParam.Value.slice(pos+1, pos2); //输出变量
  10451. result.Period=indexParam.Value.slice(pos2+1); //周期
  10452. }
  10453. else
  10454. {
  10455. result.Out=indexParam.Value.slice(pos+1);
  10456. }
  10457. }
  10458. else
  10459. {
  10460. var pos2=indexParam.Value.indexOf('#');
  10461. if (pos2!=-1)
  10462. {
  10463. result.Name=indexParam.Value.slice(0,pos2);
  10464. result.Period=indexParam.Value.slice(pos2+1); //周期
  10465. }
  10466. else
  10467. {
  10468. result.Name=indexParam.Value;
  10469. }
  10470. }
  10471. const PERIOD_MAP=new Map([
  10472. ["DAY",0 ], ["WEEK", 1 ], ["MONTH",2 ], ["SEASON",9 ], ["YEAR", 3], ["HALFYEAR",22], ["WEEK2",21],
  10473. ["MIN1", 4], ["MIN5", 5 ], ["MIN15", 6 ], ["MIN30",7 ], ["MIN60", 8 ],["MIN120",11],["MIN240",12],
  10474. ["DAY2", 40002],["MULTIDAY",40002],["DAY3", 40003],["DAY4", 40004],["DAY5",40005],
  10475. ["DAY6", 40006],["DAY7", 40007],["DAY8", 40008],["DAY9", 40009],["DAY10",40010],
  10476. ["DAY11", 40011],["DAY12", 40012],["DAY13", 40013],["DAY14", 40014],["DAY15", 40015],
  10477. ]);
  10478. if (result.Period)
  10479. {
  10480. if (!PERIOD_MAP.has(result.Period))
  10481. {
  10482. result.Error=`${result.Period}, 周期错误`;
  10483. return false;
  10484. }
  10485. result.PeriodID=PERIOD_MAP.get(result.Period);
  10486. }
  10487. return true;
  10488. }
  10489. this.ReadSymbolArgumentValue=function(item, result) //返回{ Value:股票代码, Error:错误信息}
  10490. {
  10491. var readArgument={};
  10492. if (typeof(item)=== 'object')
  10493. {
  10494. if (!this.ReadArgumentValue(item,readArgument))
  10495. {
  10496. result.Error=readArgument.Error;
  10497. return false;
  10498. }
  10499. }
  10500. else
  10501. {
  10502. readArgument.Value=item;
  10503. }
  10504. if (readArgument.Value=='') readArgument.Value=this.Symbol; //缺省使用股票代码
  10505. var symbol=readArgument.Value;
  10506. //支持 SH60000, SZ000001
  10507. //A股后缀小写
  10508. if (symbol.indexOf('.SH')>0) result.Symbol=symbol.replace('.SH', ".sh");
  10509. else if (symbol.indexOf('.SZ')>0) result.Symbol=symbol.replace('.SZ', ".sz");
  10510. else if (symbol.indexOf("SH")==0) result.Symbol=symbol.slice(2)+".sh";
  10511. else if (symbol.indexOf("SZ")==0) result.Symbol=symbol.slice(2)+".sz";
  10512. else result.Symbol=symbol;
  10513. return true;
  10514. }
  10515. this.ReadIndexArgumentValue=function(args, result)
  10516. {
  10517. result.Args=[];
  10518. for(var i in result.SytemIndex.Args) //复制参数
  10519. {
  10520. var item=result.SytemIndex.Args[i];
  10521. result.Args.push({Value:item.Value, Name:item.Name});
  10522. }
  10523. if (args.length>2 && result.SytemIndex.Args && result.SytemIndex.Args.length>0)
  10524. {
  10525. for(var i=2, j=0; i<args.length && j<result.SytemIndex.Args.length; ++i, ++j)
  10526. {
  10527. var readArgument={};
  10528. var item=args[i];
  10529. if (typeof(item)=== 'object')
  10530. {
  10531. if (!this.ReadArgumentValue(item,readArgument))
  10532. {
  10533. result.Error=readArgument.Error;
  10534. return false;
  10535. }
  10536. }
  10537. else
  10538. {
  10539. readArgument.Value=item;
  10540. }
  10541. result.Args[j].Value=readArgument.Value;
  10542. }
  10543. }
  10544. return true;
  10545. }
  10546. this.ReadArgumentValue=function(item, result) //读取变量值
  10547. {
  10548. result.Name=item.Name;
  10549. if (item.Type==Syntax.Literal)
  10550. {
  10551. result.Value=item.Value;
  10552. return true;
  10553. }
  10554. if (item.Type==Syntax.Identifier)
  10555. {
  10556. var isFind=false;
  10557. for(var i in this.Arguments)
  10558. {
  10559. const argItem=this.Arguments[i];
  10560. if (argItem.Name==item.Name)
  10561. {
  10562. result.Value=argItem.Value;
  10563. isFind=true;
  10564. return true;
  10565. }
  10566. }
  10567. if (!isFind)
  10568. {
  10569. result.Error=`can't read ${item.Name}` ;
  10570. return false;
  10571. }
  10572. }
  10573. result.Error=`can't read ${item.Name}, type error.`;
  10574. return false;
  10575. }
  10576. this.ReadIndexFunctionOut=function(item, result)
  10577. {
  10578. var indexParam={};
  10579. if (typeof(item)=== 'object')
  10580. {
  10581. if (!this.ReadArgumentValue(item,indexParam))
  10582. {
  10583. result.Error=indexParam.Error;
  10584. return false;
  10585. }
  10586. }
  10587. else
  10588. {
  10589. indexParam.Value=item;
  10590. }
  10591. result.OutIndex=indexParam.Value;
  10592. result.Out=null;
  10593. return true;
  10594. }
  10595. //TMP2:=KDJ.K#WEEK;
  10596. this.CallMemberScriptIndex=function(job)
  10597. {
  10598. if (job.Member.Object.Type!=Syntax.Identifier ||job.Member.Property.Type!=Syntax.Identifier)
  10599. {
  10600. var token=job.Token;
  10601. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: 参数错误`);
  10602. }
  10603. var objName=job.Member.Object.Name;
  10604. var PropertyName=job.Member.Property.Name;
  10605. if (PropertyName=="" || PropertyName==null)
  10606. {
  10607. var token=job.Token;
  10608. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: ${objName}.${PropertyName} 指标输出变量错误`);
  10609. }
  10610. if (this.Execute.VarTable.has(objName))
  10611. {
  10612. var memberValue=this.Execute.VarTable.get(objName);
  10613. if (memberValue.hasOwnProperty(PropertyName))
  10614. {
  10615. JSConsole.Complier.Log(`[JSSymbolData::CallMemberScriptIndex] index data ${objName}.${PropertyName} in cache.`);
  10616. return this.Execute.RunNextJob();
  10617. }
  10618. }
  10619. var callInfo=objName+"."+PropertyName;
  10620. var indexInfo={ Job:job, PeriodID:this.Period , Symbol:this.Symbol };
  10621. if (!this.ReadIndexFunctionValue(callInfo,indexInfo)) //读取指标
  10622. {
  10623. var token=job.Token;
  10624. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: '${callInfo}' ${indexInfo.Error}`);
  10625. }
  10626. var systemIndex=new JSIndexScript();
  10627. var systemItem=systemIndex.Get(indexInfo.Name);
  10628. if (!systemItem)
  10629. {
  10630. var token=job.Token;
  10631. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: '${callInfo}' ${indexInfo.Name} 指标不存在`);
  10632. }
  10633. if (Array.isArray(systemItem.Args) && systemItem.Args.length>0)
  10634. {
  10635. indexInfo.Args=[];
  10636. for(var i in systemItem.Args) //复制参数
  10637. {
  10638. var item=systemItem.Args[i];
  10639. indexInfo.Args.push({Value:item.Value, Name:item.Name});
  10640. }
  10641. }
  10642. JSConsole.Complier.Log('[JSSymbolData::CallMemberScriptIndex] call script index', indexInfo);
  10643. var dateTimeRange=this.Data.GetDateRange();
  10644. var option=
  10645. {
  10646. HQDataType:this.DataType,
  10647. Symbol:indexInfo.Symbol,
  10648. Name:'',
  10649. Right:this.Right, //复权
  10650. Period:indexInfo.PeriodID, //周期
  10651. Data:null,
  10652. SourceData:null,
  10653. Callback:(outVar,job, symbolData)=> {
  10654. this.RecvMemberScriptIndexData(outVar,job,symbolData);
  10655. this.Execute.RunNextJob();
  10656. },
  10657. CallbackParam:indexInfo,
  10658. Async:true,
  10659. MaxRequestDataCount:this.MaxRequestDataCount+30*2,
  10660. MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
  10661. Arguments:indexInfo.Args,
  10662. //Condition:this.Condition,
  10663. IsBeforeData:this.IsBeforeData,
  10664. NetworkFilter:this.NetworkFilter,
  10665. IsApiPeriod:this.IsApiPeriod,
  10666. KLineRange:dateTimeRange //K线数据范围
  10667. };
  10668. //执行脚本
  10669. var run=JSComplier.Execute(systemItem.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
  10670. }
  10671. this.CallDynamicScriptIndex=function(job, varTable)
  10672. {
  10673. var callInfo=job.DynamicName;
  10674. var indexInfo={ Job:job, PeriodID:this.Period , Symbol:this.Symbol };
  10675. if (!this.ReadIndexFunctionValue(callInfo,indexInfo)) //读取指标
  10676. {
  10677. var token=job.Token;
  10678. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() Error: '${callInfo}' ${indexInfo.Error}`);
  10679. }
  10680. var systemIndex=new JSIndexScript(); //系统指标
  10681. var systemItem=systemIndex.Get(indexInfo.Name);
  10682. if (!systemItem)
  10683. {
  10684. var token=job.Token;
  10685. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() Error: '${callInfo}' ${indexInfo.Name} 指标不存在`);
  10686. }
  10687. indexInfo.SytemIndex=systemItem;
  10688. if (!this.ReadDynamicIndexArgumentValue(job.Args, indexInfo, varTable))
  10689. {
  10690. var token=job.Token;
  10691. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() ${indexInfo.Name} 指标参数错误 : ${indexInfo.Error} `);
  10692. }
  10693. JSConsole.Complier.Log('[JSSymbolData::CallMemberScriptIndex] call script index', indexInfo);
  10694. var dateTimeRange=this.Data.GetDateRange();
  10695. var option=
  10696. {
  10697. HQDataType:this.DataType,
  10698. Symbol:indexInfo.Symbol,
  10699. Name:'',
  10700. Right:this.Right, //复权
  10701. Period:indexInfo.PeriodID, //周期
  10702. Data:null,
  10703. SourceData:null,
  10704. Callback:(outVar,job, symbolData)=> {
  10705. this.RecvDynamicScriptIndexData(outVar,job,symbolData);
  10706. this.Execute.RunNextJob();
  10707. },
  10708. CallbackParam:indexInfo,
  10709. Async:true,
  10710. MaxRequestDataCount:this.MaxRequestDataCount+30*2,
  10711. MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
  10712. Arguments:indexInfo.Args,
  10713. //Condition:this.Condition,
  10714. IsBeforeData:this.IsBeforeData,
  10715. NetworkFilter:this.NetworkFilter,
  10716. IsApiPeriod:this.IsApiPeriod,
  10717. KLineRange:dateTimeRange //K线数据范围
  10718. };
  10719. //执行脚本
  10720. var run=JSComplier.Execute(systemItem.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
  10721. }
  10722. this.ReadDynamicIndexArgumentValue=function(args, result, varTable)
  10723. {
  10724. result.Args=[];
  10725. for(var i =0;i<result.SytemIndex.Args.length; ++i) //复制参数
  10726. {
  10727. var item=result.SytemIndex.Args[i];
  10728. result.Args.push({ Value:item.Value, Name:item.Name, IsDefault:true });
  10729. }
  10730. if (!IFrameSplitOperator.IsNonEmptyArray(args)) return true;
  10731. for(var i=0;i<args.length;++i)
  10732. {
  10733. var item=args[i];
  10734. var argItem=result.Args[i];
  10735. if (!argItem) continue;
  10736. if (item.Type==Syntax.Literal)
  10737. {
  10738. argItem.Value=item.Value;
  10739. argItem.IsDefault=false;
  10740. }
  10741. else if (item.Type==Syntax.Identifier) //支持传参
  10742. {
  10743. if (varTable.has(item.Name))
  10744. {
  10745. argItem.Value=varTable.get(item.Name);
  10746. argItem.IsDefault=false;
  10747. }
  10748. }
  10749. }
  10750. return true;
  10751. }
  10752. /*****************************************************************************************************************************
  10753. 脚本调用
  10754. STKINDI
  10755. STKINDI('600000.sh','MA.MA1#WEEK',5,10,20,30,60,120);
  10756. 1=股票代码 2=指标名字.输出变量#周期, 3....参数
  10757. CALCSTOCKINDEX
  10758. 用法:CALCSTOCKINDEX(品种代码,指标名称,指标线),返回该指标相应输出的计算值.
  10759. 例如:
  10760. CALCSTOCKINDEX('SH600000','KDJ',3)表示上证600000的KDJ指标第3个输出即J之值,第一个参数可在前面加SZ(深市),SH(沪市),BJ(京市),或市场_,,
  10761. CALCSTOCKINDEX('47_IFL0','MACD',2)表示IFL0品种的MACD指标第2个输出值.
  10762. "MA.MA1"(6,12,18)
  10763. *******************************************************************************************************************************/
  10764. this.CallScriptIndex=function(job, varTable)
  10765. {
  10766. if (job.Member) return this.CallMemberScriptIndex(job);
  10767. if (job.DynamicName) return this.CallDynamicScriptIndex(job, varTable);
  10768. if (!job.Args || !(job.Args.length>=2))
  10769. {
  10770. var token=job.Token;
  10771. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${job.FunctionName} 参数错误`);
  10772. }
  10773. var indexInfo={ Job:job, PeriodID:this.Period };
  10774. if (!this.ReadSymbolArgumentValue(job.Args[0],indexInfo)) //读取代码
  10775. {
  10776. var token=job.Token;
  10777. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
  10778. }
  10779. if (!this.ReadIndexFunctionValue(job.Args[1],indexInfo)) //读取指标
  10780. {
  10781. var token=job.Token;
  10782. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
  10783. }
  10784. if (job.FunctionName=="CALCSTOCKINDEX")
  10785. {
  10786. if (!this.ReadIndexFunctionOut(job.Args[2],indexInfo)) //读取返回值索引
  10787. {
  10788. var token=job.Token;
  10789. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
  10790. }
  10791. }
  10792. var systemIndex=new JSIndexScript();
  10793. var systemItem=systemIndex.Get(indexInfo.Name);
  10794. if (!systemItem)
  10795. {
  10796. var token=job.Token;
  10797. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标不存在`);
  10798. }
  10799. indexInfo.SytemIndex=systemItem; //系统指标
  10800. if (!this.ReadIndexArgumentValue(job.Args,indexInfo))
  10801. {
  10802. var token=job.Token;
  10803. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标参数错误 : ${indexInfo.Error} `);
  10804. }
  10805. JSConsole.Complier.Log('[JSSymbolData::CallScriptIndex] call script index', indexInfo);
  10806. var DateTimeRange=null;
  10807. if (this.Data && this.Data.Data.length>0)
  10808. {
  10809. var start=this.Data.Data[0];
  10810. var end=this.Data.Data[this.Data.Data.length-1];
  10811. DateTimeRange=
  10812. {
  10813. Start:{Date:start.Date, Time: start.Time},
  10814. End:{Date:end.Date, Time: end.Time},
  10815. }
  10816. }
  10817. var option=
  10818. {
  10819. HQDataType:this.DataType,
  10820. Symbol:indexInfo.Symbol,
  10821. Name:'',
  10822. Right:this.Right, //复权
  10823. Period:indexInfo.PeriodID, //周期
  10824. Data:null,
  10825. SourceData:null,
  10826. Callback:(outVar,job, symbolData)=> {
  10827. this.RecvScriptIndexData(outVar,job,symbolData);
  10828. this.Execute.RunNextJob();
  10829. },
  10830. CallbackParam:indexInfo,
  10831. Async:true,
  10832. MaxRequestDataCount:this.MaxRequestDataCount+30*2,
  10833. MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
  10834. Arguments:indexInfo.Args,
  10835. //Condition:this.Condition,
  10836. IsBeforeData:this.IsBeforeData,
  10837. NetworkFilter:this.NetworkFilter,
  10838. IsApiPeriod:this.IsApiPeriod,
  10839. KLineRange:DateTimeRange //K线数据范围
  10840. };
  10841. //执行脚本
  10842. var run=JSComplier.Execute(indexInfo.SytemIndex.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
  10843. }
  10844. this.RecvMemberScriptIndexData=function(outVar,indexInfo,symbolData)
  10845. {
  10846. JSConsole.Complier.Log('[JSSymbolData::RecvMemberScriptIndexData] ', outVar, indexInfo, symbolData);
  10847. var kLine=symbolData.Data.Data;
  10848. var aryOutVar=outVar;
  10849. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10850. var member=indexInfo.Job.Member;
  10851. var objName=member.Object.Name;
  10852. var propertyName=member.Property.Name;
  10853. var memberValue={};
  10854. if (this.Execute.VarTable.has(objName))
  10855. memberValue=this.Execute.VarTable.get(objName);
  10856. else
  10857. this.Execute.VarTable.set(objName, memberValue);
  10858. //保存所有的指标数据, 下面用到了就可以不用算了
  10859. for(var i in data)
  10860. {
  10861. var key=outVar[i].Name;
  10862. if (indexInfo.Period) key+='#'+indexInfo.Period; //带周期的变量
  10863. memberValue[key]=data[i].Data;
  10864. }
  10865. }
  10866. this.RecvScriptIndexData=function(outVar,indexInfo,symbolData)
  10867. {
  10868. var key=this.GenerateScriptIndexKey(indexInfo);
  10869. JSConsole.Complier.Log('[JSSymbolData::RecvScriptIndexData] ', outVar, indexInfo, symbolData, key);
  10870. var kLine=symbolData.Data.Data;
  10871. var aryOutVar=outVar;
  10872. if (indexInfo.Out)
  10873. {
  10874. for(var i=0;i<outVar.length; ++i)
  10875. {
  10876. var item=outVar[i];
  10877. if (item.Name==indexInfo.Out)
  10878. {
  10879. aryOutVar=[item];
  10880. break;
  10881. }
  10882. }
  10883. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10884. this.ScriptIndexOutData.set(key,data[0].Data);
  10885. }
  10886. else if (IFrameSplitOperator.IsPlusNumber(indexInfo.OutIndex))
  10887. {
  10888. var index=indexInfo.OutIndex-1;
  10889. aryOutVar=[outVar[index]];
  10890. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10891. this.ScriptIndexOutData.set(key,data[0].Data);
  10892. }
  10893. else
  10894. {
  10895. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10896. var result={ __Type__:"Object" };
  10897. for(var i in data)
  10898. {
  10899. var item=data[i];
  10900. result[item.Name]=item.Data;
  10901. }
  10902. this.ScriptIndexOutData.set(key,result);
  10903. }
  10904. }
  10905. this.RecvDynamicScriptIndexData=function(outVar,indexInfo,symbolData)
  10906. {
  10907. JSConsole.Complier.Log('[JSSymbolData::RecvDynamicScriptIndexData] ', outVar, indexInfo, symbolData);
  10908. var kLine=symbolData.Data.Data;
  10909. var aryOutVar=outVar;
  10910. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10911. var objName=indexInfo.Name;
  10912. var memberValue={};
  10913. if (this.Execute.VarTable.has(objName))
  10914. memberValue=this.Execute.VarTable.get(objName);
  10915. else
  10916. this.Execute.VarTable.set(objName, memberValue);
  10917. var strValue="";
  10918. for(var i=0; i<indexInfo.Args.length; ++i)
  10919. {
  10920. var item=indexInfo.Args[i];
  10921. if (item.IsDefault===false)
  10922. {
  10923. if (strValue.length>0) strValue+=",";
  10924. strValue+=`${item.Value}`;
  10925. }
  10926. }
  10927. var strArgs=`(${strValue})`;
  10928. //保存所有的指标数据, 下面用到了就可以不用算了
  10929. for(var i=0; i<data.length; ++i)
  10930. {
  10931. var key=`${outVar[i].Name}#${strArgs}`;
  10932. if (indexInfo.Period) key+='#'+indexInfo.Period; //带周期的变量
  10933. memberValue[key]=data[i].Data;
  10934. }
  10935. }
  10936. //key= (代码,周期),指标(参数) => 输出
  10937. this.GenerateScriptIndexKey=function(indexInfo)
  10938. {
  10939. var indexParam='';
  10940. var args=indexInfo.Args;
  10941. for(var i in args)
  10942. {
  10943. if (indexParam.length>0) indexParam+=',';
  10944. var item=args[i];
  10945. indexParam+=item.Value.toString();
  10946. }
  10947. var out="ALL";
  10948. if (indexInfo.Out) out=indexInfo.Out;
  10949. else if (IFrameSplitOperator.IsPlusNumber(indexInfo.OutIndex)) out=`Out[${indexInfo.OutIndex-1}]`;
  10950. var key=`(${indexInfo.Symbol},${indexInfo.PeriodID}), ${indexInfo.Name}(${indexParam})=>${out}`;
  10951. return key;
  10952. }
  10953. this.ExecuteScriptIndexError=function(error,indexInfo)
  10954. {
  10955. var token=indexInfo.Job.Token;
  10956. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标执行错误 : ${error} `);
  10957. }
  10958. this.GetScriptIndexOutData=function(args,node, funcName)
  10959. {
  10960. var indexInfo={ PeriodID:this.Period };
  10961. if (!this.ReadSymbolArgumentValue(args[0],indexInfo)) //读取代码
  10962. this.Execute.ThrowUnexpectedNode(node,`${funcName}() 股票代码错误: ${indexInfo.Error}`);
  10963. if (!this.ReadIndexFunctionValue(args[1],indexInfo)) //读取指标
  10964. this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标错误: ${indexInfo.Error}`);
  10965. if (funcName=="CALCSTOCKINDEX")
  10966. {
  10967. if (!this.ReadIndexFunctionOut(args[2],indexInfo)) //读取返回值索引
  10968. this.Execute.ThrowUnexpectedNode(node, `${funcName}() Error: ${indexInfo.Error}`);
  10969. }
  10970. var systemIndex=new JSIndexScript();
  10971. var systemItem=systemIndex.Get(indexInfo.Name);
  10972. if (!systemItem)
  10973. this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标错误: ${indexInfo.Name} 指标不存在`);
  10974. indexInfo.SytemIndex=systemItem; //系统指标
  10975. if (!this.ReadIndexArgumentValue(args,indexInfo))
  10976. this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标参数错误: ${indexInfo.Error}`);
  10977. var key=this.GenerateScriptIndexKey(indexInfo);
  10978. if (!this.ScriptIndexOutData.has(key)) return null;
  10979. return this.ScriptIndexOutData.get(key);
  10980. }
  10981. this.JsonDataToHistoryData=function(data)
  10982. {
  10983. var list = data.data;
  10984. var aryDayData=new Array();
  10985. var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7;
  10986. var up = 8, down = 9, stop = 10, unchanged = 11;
  10987. for (var i = 0; i < list.length; ++i)
  10988. {
  10989. var item = new JSCommonData.HistoryData();
  10990. item.Date = list[i][date];
  10991. item.Open = list[i][open];
  10992. item.YClose = list[i][yclose];
  10993. item.Close = list[i][close];
  10994. item.High = list[i][high];
  10995. item.Low = list[i][low];
  10996. item.Vol = list[i][vol]; //原始单位股
  10997. item.Amount = list[i][amount];
  10998. if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除
  10999. //上涨 下跌家数
  11000. if (list[i].length > up) item.Up = list[i][up];
  11001. if (list[i].length > down) item.Down = list[i][down];
  11002. if (list[i].length > stop) item.Stop = list[i][stop];
  11003. if (list[i].length > unchanged) item.Unchanged = list[i][unchanged];
  11004. aryDayData.push(item);
  11005. }
  11006. return aryDayData;
  11007. }
  11008. this.JsonDataToMinuteHistoryData=function(data)
  11009. {
  11010. var list = data.data;
  11011. var aryDayData=new Array();
  11012. var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, time = 8;
  11013. for (var i = 0; i < list.length; ++i)
  11014. {
  11015. let item = new JSCommonData.HistoryData();
  11016. item.Date = list[i][date];
  11017. item.Open = list[i][open];
  11018. item.YClose = list[i][yclose];
  11019. item.Close = list[i][close];
  11020. item.High = list[i][high];
  11021. item.Low = list[i][low];
  11022. item.Vol = list[i][vol]; //原始单位股
  11023. item.Amount = list[i][amount];
  11024. item.Time=list[i][time];
  11025. // if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除
  11026. aryDayData.push(item);
  11027. }
  11028. // 无效数据处理
  11029. for(let i = 0; i < aryDayData.length; ++i)
  11030. {
  11031. var minData = aryDayData[i];
  11032. if (minData == null) coninue;
  11033. if (isNaN(minData.Open) || minData.Open <= 0 || isNaN(minData.High) || minData.High <= 0 || isNaN(minData.Low) || minData.Low <= 0
  11034. || isNaN(minData.Close) || minData.Close <= 0 || isNaN(minData.YClose) || minData.YClose <= 0)
  11035. {
  11036. if (i == 0)
  11037. {
  11038. if (minData.YClose > 0)
  11039. {
  11040. minData.Open = minData.YClose;
  11041. minData.High = minData.YClose;
  11042. minData.Low = minData.YClose;
  11043. minData.Close = minData.YClose;
  11044. }
  11045. }
  11046. else // 用前一个有效数据填充
  11047. {
  11048. for(let j = i-1; j >= 0; --j)
  11049. {
  11050. var minData2 = aryDayData[j];
  11051. if (minData2 == null) coninue;
  11052. if (minData2.Open > 0 && minData2.High > 0 && minData2.Low > 0 && minData2.Close > 0)
  11053. {
  11054. if (minData.YClose <= 0) minData.YClose = minData2.Close;
  11055. minData.Open = minData2.Open;
  11056. minData.High = minData2.High;
  11057. minData.Low = minData2.Low;
  11058. minData.Close = minData2.Close;
  11059. break;
  11060. }
  11061. }
  11062. }
  11063. }
  11064. }
  11065. return aryDayData;
  11066. }
  11067. //API 返回数据 转化为array[]
  11068. this.JsonDataToMinuteData = function (data)
  11069. {
  11070. var aryMinuteData = new Array();
  11071. for (var i in data.stock[0].minute)
  11072. {
  11073. var jsData = data.stock[0].minute[i];
  11074. var item = new JSCommonData.MinuteData();
  11075. item.Close = jsData.price;
  11076. item.Open = jsData.open;
  11077. item.High = jsData.high;
  11078. item.Low = jsData.low;
  11079. item.Vol = jsData.vol; //股
  11080. item.Amount = jsData.amount;
  11081. if (i == 0) //第1个数据 写死9:25
  11082. item.DateTime = data.stock[0].date.toString() + " 0925";
  11083. else
  11084. item.DateTime = data.stock[0].date.toString() + " " + jsData.time.toString();
  11085. item.Date = data.stock[0].date;
  11086. item.Time = jsData.time;
  11087. item.Increate = jsData.increate;
  11088. item.Risefall = jsData.risefall;
  11089. item.AvPrice = jsData.avprice;
  11090. aryMinuteData[i] = item;
  11091. }
  11092. return aryMinuteData;
  11093. }
  11094. //CODELIKE 模糊股票代码
  11095. this.CODELIKE=function(value)
  11096. {
  11097. if (this.Symbol.indexOf(value)==0) return 1;
  11098. return 0;
  11099. }
  11100. this.NAMELIKE = function (value)
  11101. {
  11102. if (this.Name && this.Name.indexOf(value) == 0) return 1;
  11103. return 0;
  11104. }
  11105. /*
  11106. SETCODE 市场类型
  11107. 0:深圳 1:上海,47:中金所期货 28:郑州商品 29:大连商品 30:上海商品,27:香港指数 31:香港主板,48:香港创业板...
  11108. */
  11109. this.SETCODE=function()
  11110. {
  11111. if (this.Symbol.indexOf('.sh')) return 1;
  11112. if (this.Symbol.indexOf('.sz')) return 0;
  11113. return 0;
  11114. }
  11115. this.GetSymbol = function () { return this.Symbol; }
  11116. this.GetName = function () { return this.Name; }
  11117. this.TIME=function()
  11118. {
  11119. var result = [];
  11120. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11121. for(let i in this.Data.Data)
  11122. {
  11123. var item=this.Data.Data[i];
  11124. if (this.IsNumber(item.Time))
  11125. result[i]=item.Time;
  11126. else
  11127. result[i]=0;
  11128. }
  11129. return result;
  11130. }
  11131. this.DATE = function ()
  11132. {
  11133. var result = [];
  11134. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11135. for (let i in this.Data.Data)
  11136. {
  11137. var item = this.Data.Data[i];
  11138. result[i] = item.Date - 19000000;;
  11139. }
  11140. return result;
  11141. }
  11142. /*
  11143. 取得该周期的时分秒,适用于日线以下周期.
  11144. 用法: TIME2
  11145. 函数返回有效值范围为(000000-235959)
  11146. */
  11147. this.TIME2=function()
  11148. {
  11149. var result=[];
  11150. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11151. for(let i=0;i<this.Data.Data.length;++i)
  11152. {
  11153. var item=this.Data.Data[i];
  11154. if (this.IsNumber(item.Time))
  11155. result[i]=item.Time*100;
  11156. else
  11157. result[i]=0;
  11158. }
  11159. return result;
  11160. }
  11161. this.DateTime=function()
  11162. {
  11163. var result=[];
  11164. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11165. var isKLineMinute=ChartData.IsMinutePeriod(this.Period, true);
  11166. for(var i=0;i<this.Data.Data.length;++i)
  11167. {
  11168. var item=this.Data.Data[i];
  11169. if (isKLineMinute)
  11170. {
  11171. result[i]=item.Date*10000+item.Time;
  11172. }
  11173. else
  11174. {
  11175. result[i]=item.Date;
  11176. }
  11177. }
  11178. return result;
  11179. }
  11180. this.YEAR = function ()
  11181. {
  11182. var result = [];
  11183. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11184. for (let i in this.Data.Data)
  11185. {
  11186. var item = this.Data.Data[i];
  11187. if (this.IsNumber(item.Date))
  11188. result[i] = parseInt(item.Date / 10000);
  11189. else
  11190. result[i] = null;
  11191. }
  11192. return result;
  11193. }
  11194. this.MONTH = function ()
  11195. {
  11196. var result = [];
  11197. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11198. for (let i in this.Data.Data)
  11199. {
  11200. var item = this.Data.Data[i];
  11201. if (this.IsNumber(item.Date))
  11202. result[i] = parseInt(item.Date % 10000 / 100);
  11203. else
  11204. result[i] = null;
  11205. }
  11206. return result;
  11207. }
  11208. //星期 1-7
  11209. this.WEEK = function ()
  11210. {
  11211. var result = [];
  11212. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11213. var tempDate = new Date();
  11214. for (let i in this.Data.Data)
  11215. {
  11216. var item = this.Data.Data[i];
  11217. result[i] = null;
  11218. if (!this.IsNumber(item.Date)) continue;
  11219. var year = parseInt(item.Date / 10000);
  11220. var month = parseInt(item.Date % 10000 / 100);
  11221. var day = item.Date % 100;
  11222. tempDate.setFullYear(year, month - 1, day);
  11223. result[i] = tempDate.getDay();
  11224. }
  11225. return result;
  11226. }
  11227. /*
  11228. 取得该周期的日期离今天的天数.
  11229. 用法: DAYSTOTODAY
  11230. */
  11231. this.DAYSTOTODAY=function()
  11232. {
  11233. var result=[];
  11234. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11235. var nowDate=new Date();
  11236. var endDate=new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate());
  11237. for(let i=0; i<this.Data.Data.length; ++i)
  11238. {
  11239. var item=this.Data.Data[i];
  11240. result[i]=null;
  11241. if (!this.IsNumber(item.Date)) continue;
  11242. var year=parseInt(item.Date/10000);
  11243. var month=parseInt(item.Date%10000/100);
  11244. var day=item.Date%100;
  11245. var beginDate=new Date(year,month-1,day);
  11246. var diffDays = Math.ceil((endDate - beginDate)/(24*60*60*1000));
  11247. result[i]=diffDays;
  11248. }
  11249. return result;
  11250. }
  11251. /*
  11252. 取得该周是年内第几个周.
  11253. 用法:WEEKOFYEAR
  11254. */
  11255. this.WEEKOFYEAR=function()
  11256. {
  11257. var result=[];
  11258. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11259. for(let i in this.Data.Data)
  11260. {
  11261. var item=this.Data.Data[i];
  11262. result[i]=null;
  11263. if (!this.IsNumber(item.Date)) continue;
  11264. var year=parseInt(item.Date/10000);
  11265. var month=parseInt(item.Date%10000/100);
  11266. var day=item.Date%100;
  11267. var endDate=new Date(year,month-1,day);
  11268. var beginDate=new Date(year,0,1);
  11269. var diffDays = Math.ceil((endDate - beginDate)/(24*60*60*1000));
  11270. diffDays+=((beginDate.getDay() + 1) - 1);
  11271. var week = Math.ceil(diffDays/7);
  11272. var value=week;
  11273. result[i]=value;
  11274. }
  11275. return result;
  11276. }
  11277. this.GetYearWeek=function(endDate)
  11278. {
  11279. var beginDate = new Date(endDate.getFullYear(), 0, 1);
  11280. //星期从0-6,0代表星期天,6代表星期六
  11281. var endWeek = endDate.getDay();
  11282. if (endWeek == 0) endWeek = 7;
  11283. var beginWeek = beginDate.getDay();
  11284. if (beginWeek == 0) beginWeek = 7;
  11285. //计算两个日期的天数差
  11286. var millisDiff = endDate.getTime() - beginDate.getTime();
  11287. var dayDiff = Math.floor(( millisDiff + (beginWeek - endWeek) * (24 * 60 * 60 * 1000)) / 86400000);
  11288. return Math.ceil(dayDiff / 7) + 1;
  11289. }
  11290. this.REFDATE = function (data, date)
  11291. {
  11292. var result = null;
  11293. var findDate=null;
  11294. if (Array.isArray(date))
  11295. {
  11296. if (date.length>0) findDate=date[date.length-1];
  11297. }
  11298. else if (this.IsNumber(date))
  11299. {
  11300. findDate=date;
  11301. }
  11302. if (findDate==null) return null;
  11303. if (findDate<5000000) findDate+=19000000;
  11304. var index = null;
  11305. for (let i in this.Data.Data) //查找日期对应的索引
  11306. {
  11307. if (this.Data.Data[i].Date == findDate)
  11308. {
  11309. index = parseInt(i);
  11310. break;
  11311. }
  11312. }
  11313. if (index == null || index >= data.length) return null;
  11314. return data[index];
  11315. }
  11316. //用法:结果从0到11,依次分别是1/5/15/30/60分钟,日/周/月,多分钟,多日,季,年
  11317. this.PERIOD=function()
  11318. {
  11319. //Period周期 0=日线 1=周线 2=月线 3=年线 9=季线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟
  11320. const PERIOD_MAP=[5,6,7,11, 0,1,2,3,4,5, 9];
  11321. if (this.Period >= 0 && this.Period <= PERIOD_MAP.length - 1)
  11322. return PERIOD_MAP[this.Period];
  11323. return this.Period;
  11324. }
  11325. this.GetDrawNull = function ()
  11326. {
  11327. var result = [];
  11328. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  11329. for (let i in this.Data.Data)
  11330. {
  11331. result[i] = null;
  11332. }
  11333. return result;
  11334. }
  11335. this.HOUR=function()
  11336. {
  11337. var result=[];
  11338. if (!this.Data || !this.Data.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return result;
  11339. for(var i=0;i<this.Data.Data.length;++i)
  11340. {
  11341. var item=this.Data.Data[i];
  11342. result[i]=0;
  11343. if (IFrameSplitOperator.IsNumber(item.Time)) result[i]=parseInt(item.Time/100);
  11344. }
  11345. return result;
  11346. }
  11347. this.MINUTE=function()
  11348. {
  11349. var result=[];
  11350. if (!this.Data || !this.Data.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return result;
  11351. for(var i=0;i<this.Data.Data.length;++i)
  11352. {
  11353. var item=this.Data.Data[i];
  11354. result[i]=0;
  11355. if (IFrameSplitOperator.IsNumber(item.Time)) result[i]=item.Time%100;
  11356. }
  11357. return result;
  11358. }
  11359. }
  11360. //是否有是有效的数字
  11361. JSSymbolData.prototype.IsNumber = function (value)
  11362. {
  11363. if (value == null) return false;
  11364. if (isNaN(value)) return false;
  11365. return true;
  11366. }
  11367. JSSymbolData.prototype.IsDivideNumber = function (value)
  11368. {
  11369. if (value == null) return false;
  11370. if (isNaN(value)) return false;
  11371. if (value == 0) return false;
  11372. return true;
  11373. }
  11374. JSSymbolData.prototype.JsonDataToFinance = function (data)
  11375. {
  11376. var financeData;
  11377. for (let i = 1; i <= 4; ++i)
  11378. {
  11379. switch (i)
  11380. {
  11381. case 1:
  11382. var finance = data.finance1;
  11383. var announcement = data.announcement1;
  11384. break;
  11385. case 2:
  11386. var finance = data.finance2;
  11387. var announcement = data.announcement2;
  11388. break;
  11389. case 3:
  11390. var finance = data.finance3;
  11391. var announcement = data.announcement3;
  11392. break;
  11393. case 4:
  11394. var finance = data.finance4;
  11395. var announcement = data.announcement4;
  11396. break;
  11397. default:
  11398. break;
  11399. }
  11400. if (!finance || !announcement || !this.IsNumber(announcement.year) || !this.IsNumber(announcement.quarter)) continue;
  11401. if (financeData) //如果存在1天公布多个报告期数据 只取最新的一个公告期数据
  11402. {
  11403. if (financeData.Announcement.year < announcement.year)
  11404. financeData = { Date: data.date, Finance: finance, Announcement: announcement };
  11405. }
  11406. else
  11407. {
  11408. financeData = { Date: data.date, Finance: finance, Announcement: announcement };
  11409. }
  11410. }
  11411. return financeData;
  11412. }
  11413. var JS_EXECUTE_DEBUG_LOG=false;
  11414. var JS_EXECUTE_JOB_ID=
  11415. {
  11416. JOB_DOWNLOAD_SYMBOL_DATA:1, //下载股票的K线数据
  11417. JOB_DOWNLOAD_INDEX_DATA:2, //下载大盘的K线数据
  11418. JOB_DOWNLOAD_SYMBOL_LATEST_DATA:3, //最新的股票行情数据
  11419. JOB_DOWNLOAD_INDEX_INCREASE_DATA: 4, //涨跌股票个数统计数据
  11420. JOB_DOWNLOAD_VOLR_DATA: 5, //5日量比均量下载量比数据
  11421. JOB_DOWNLOAD_OTHER_SYMBOL_DATA:9, //下载其他股票的K线数据
  11422. JOB_DOWNLOAD_FINVALUE:301, //引用专业财务数据 FINVALUE(ID),ID为数据编号
  11423. JOB_DOWNLOAD_FINONE:302, //引用指定年和月日的某类型的财务数据 FINONE(ID,Y,MMDD),ID为数据编号,Y和MMDD表示年和月日.
  11424. JOB_DOWNLOAD_FINANCE:303, //FINANCE(ID) 基础财务数据
  11425. JOB_DOWNLOAD_GPJYVALUE:304, //引用股票交易类数据 GPJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据,TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
  11426. JOB_DOWNLOAD_VARIANT:305, //CAPITAL , TOTALCAPITAL, EXCHANGE
  11427. JOB_DOWNLOAD_SCJYVALUE:306, //引用市场总的交易类数据.SCJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据,TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
  11428. 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...个数据
  11429. 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...个数据
  11430. JOB_DOWNLOAD_BKJYVALUE:309, //BKJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据(取1或2),TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理;2表示没有数据则为0.
  11431. 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...个数据
  11432. JOB_CUSTOM_FUNCTION_DATA:6000, //自定义函数
  11433. JOB_CUSTOM_VARIANT_DATA:6001, //自定义变量
  11434. JOB_CUSTOM_DATA_FUNCTION:6002, //自定义数据函数
  11435. JOB_DOWNLOAD_MARGIN_BALANCE: 1000, //融资融券余额
  11436. JOB_DOWNLOAD_MARGIN_RATE: 1001, //融资占比
  11437. JOB_DOWNLOAD_MARGIN_BUY_BALANCE: 1010, //买入信息-融资余额
  11438. JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: 1011, //买入信息-买入额
  11439. JOB_DOWNLOAD_MARGIN_BUY_REPAY: 1012, //买入信息-偿还额
  11440. JOB_DOWNLOAD_MARGIN_BUY_NET: 1013, //买入信息-融资净买入
  11441. JOB_DOWNLOAD_MARGIN_SELL_BALANCE: 1020, //卖出信息-融券余量
  11442. JOB_DOWNLOAD_MARGIN_SELL_VOLUME: 1021, //卖出信息-卖出量
  11443. JOB_DOWNLOAD_MARGIN_SELL_REPAY: 1022, //卖出信息-偿还量
  11444. JOB_DOWNLOAD_MARGIN_SELL_NET: 1023, //卖出信息-融券净卖出
  11445. JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: 2000, //负面新闻统计
  11446. JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: 2001, //机构调研
  11447. JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: 2002, //互动易
  11448. JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: 2003, //股东增持
  11449. JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: 2004, //股东减持
  11450. JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: 2005, //信托持股
  11451. JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: 2006, //大宗交易
  11452. JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: 2007, //官网新闻
  11453. JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: 2008, //高管要闻
  11454. JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: 2009, //股权质押
  11455. JOB_DOWNLOAD_CUSTOM_API_DATA: 30000, //自定义数据
  11456. //调用其他脚本指标
  11457. //KDJ.K , KDJ.K#WEEK
  11458. //STKINDI('600000.sh','MA.MA1#WEEK',5,10,20,30,60,120);
  11459. JOB_EXECUTE_INDEX:30010,
  11460. JOB_RUN_SCRIPT:10000, //执行脚本
  11461. //融资融券
  11462. GetMarginJobID: function (value)
  11463. {
  11464. let dataMap = new Map([
  11465. [1, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE], //MARGIN(1) 融资融券余额
  11466. [2, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE], //MARGIN(2) 融资占比
  11467. [3, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE], //MARGIN(3) 买入信息-融资余额
  11468. [4, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT], //MARGIN(4) 买入信息-买入额
  11469. [5, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY], //MARGIN(5) 买入信息-偿还额
  11470. [6, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET], //MARGIN(6) 买入信息-融资净买入
  11471. [7, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE], //MARGIN(7) 卖出信息-融券余量
  11472. [8, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME], //MARGIN(8) 卖出信息-卖出量
  11473. [9, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY], //MARGIN(9) 卖出信息-偿还量
  11474. [10, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET], //MARGIN(10) 卖出信息-融券净卖出
  11475. ]);
  11476. if (dataMap.has(value)) return dataMap.get(value);
  11477. return null;
  11478. },
  11479. GetNewsAnalysisID: function (value)
  11480. {
  11481. let dataMap = new Map([
  11482. [1, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE], //NEWS(1) 负面新闻统计
  11483. [2, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH], //NEWS(2) 机构调研统计
  11484. [3, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT], //NEWS(3) 互动易
  11485. [4, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE], //NEWS(4) 股东增持
  11486. [5, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2], //NEWS(5) 股东减持
  11487. [6, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER], //NEWS(6) 信托持股
  11488. [7, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING], //NEWS(7) 大宗交易
  11489. [8, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS], //NEWS(8) 官网新闻
  11490. [9, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS], //NEWS(9) 高管要闻
  11491. [10, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE], //NEWS(10) 股权质押
  11492. ]);
  11493. if (dataMap.has(value)) return dataMap.get(value);
  11494. return null;
  11495. }
  11496. };
  11497. //专业财务数据
  11498. var JS_ARRAY_PROFESSIONAL_FINANCE=
  11499. [
  11500. {
  11501. Name:"GPJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE,
  11502. Explain:"股票交易类数据GPJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetGPJYValue", ArgCount:3
  11503. },
  11504. {
  11505. Name:"GPJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYONE,
  11506. Explain:"股票交易类数据GPJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetGPJYOne", ArgCount:4
  11507. },
  11508. {
  11509. Name:"SCJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE,
  11510. Explain:"市场交易类数据SCJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetSCJYValue",ArgCount:3
  11511. },
  11512. {
  11513. Name:"SCJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYONE,
  11514. Explain:"市场交易类数据SCJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetSCJYOne",ArgCount:4
  11515. },
  11516. {
  11517. Name:"BKJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE,
  11518. Explain:"板块交易类数据BKJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetBKJYValue",ArgCount:3
  11519. },
  11520. {
  11521. Name:"BKJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYONE,
  11522. Explain:"板块交易类数据BKJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetBKJYOne",ArgCount:4
  11523. },
  11524. {
  11525. Name:"FINVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE,
  11526. Explain:"财务数据FINVALUE(ID)", FuncName:"JSSymbolData::GetFinValue",ArgCount:1
  11527. },
  11528. {
  11529. Name:"FINONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE,
  11530. Explain:"财务数据FINONE(ID,Y,MMDD)", FuncName:"JSSymbolData::GetFinOne",ArgCount:3
  11531. }
  11532. ];
  11533. function JSExecute(ast,option)
  11534. {
  11535. this.AST=ast; //语法树
  11536. this.ErrorHandler=new ErrorHandler();
  11537. this.VarTable=new Map(); //变量表
  11538. this.VarDrawTable=new Map(); //绘图变量表
  11539. this.OutVarTable=new Array(); //输出变量
  11540. this.Arguments=[];
  11541. //脚本自动变量表, 只读
  11542. this.ConstVarTable=new Map([
  11543. //个股数据
  11544. ['CLOSE', null], ['VOL', null], ['OPEN', null], ['HIGH', null], ['LOW', null], ['AMOUNT', null], ['AMO', null],
  11545. ['C', null], ['V', null], ['O', null], ['H', null], ['L', null],
  11546. ['VOLR', null],
  11547. ['VOLINSTK',null], ["OPI",null], //持仓量
  11548. ["QHJSJ",null], ["SETTLE",null], //结算价
  11549. ["ZSTJJ",null], //分时图均价线,对于分时图周期指标有效.
  11550. ["ISEQUAL",null], ["ISUP",null],["ISDOWN"], //ISUP=收阳 ISEQUAL=平盘 ISDOWN=收阴
  11551. //日期类
  11552. ['DATE', null], ['YEAR', null], ['MONTH', null], ['PERIOD', null], ['WEEK', null],['WEEKDAY',null],["TIME",null],["DATETIME",null],["TIME2",null],
  11553. ["WEEKOFYEAR", null],["DAYSTOTODAY", null],
  11554. ["HOUR",null],["MINUTE",null],
  11555. //大盘数据
  11556. ['INDEXA',null],['INDEXC',null],['INDEXH',null],['INDEXL',null],['INDEXO',null],['INDEXV',null],
  11557. ['INDEXADV', null], ['INDEXDEC', null],
  11558. ['FROMOPEN',null], //已开盘有多长分钟
  11559. ['TOTALFZNUM', null], //该品种的每天的总交易分钟数.
  11560. ['CURRBARSCOUNT', null], //到最后交易日的周期数
  11561. ['TOTALBARSCOUNT',null],
  11562. ['ISLASTBAR', null], //判断是否为最后一个周期
  11563. ['BARSTATUS',null], //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置.
  11564. ["BARPOS", null], //返回从第一根K线开始到当前的周期数
  11565. ["TOTALCAPITAL",null], //总股本
  11566. ['CAPITAL', null], //流通股本(手)
  11567. ['EXCHANGE', null], //换手率
  11568. ['SETCODE', null], //市场类型
  11569. ['CODE', null], //品种代码
  11570. ['STKNAME', null], //品种名称
  11571. ["TQFLAG",null], //TQFLAG 当前的复权状态,0:无复权 1:前复权 2:后复权
  11572. ['HYBLOCK', null], //所属行业板块
  11573. ['DYBLOCK', null], //所属地域板块
  11574. ['GNBLOCK', null], //所属概念
  11575. ["FGBLOCK",null], //所属风格板块
  11576. ["ZSBLOCK",null], //所属指数板块
  11577. ["ZHBLOCK",null], //所属组合板块
  11578. ["ZDBLOCK",null], //所属自定义板块
  11579. ["HYZSCODE",null],
  11580. ["GNBLOCKNUM",null], //所属概念板块的个数
  11581. ["FGBLOCKNUM",null], //所属风格板块的个数
  11582. ["ZSBLOCKNUM",null], //所属指数板块的个数
  11583. ["ZHBLOCKNUM",null], //所属组合板块的个数
  11584. ["ZDBLOCKNUM",null], //所属自定义板块的个数
  11585. ["HYSYL",null], //指数市盈率或个股所属行业的市盈率
  11586. ["HYSJL",null], //指数市净率或个股所属行业的市净率
  11587. ['DRAWNULL', null],
  11588. ["NULL",null],
  11589. ["MACHINEDATE",null],["MACHINETIME",null],["MACHINEWEEK",null],
  11590. ["DYNA_NOW",null], //DYNA_NOW 现价 DYNAINFO(7) 即时行情数据 没有现价时(比如在开盘前),返回昨收盘价
  11591. ["DYNA_ZAF",null], //DYNA_ZAF 涨幅 DYNAINFO(14) 即时行情数据(沪深京早盘竞价期间使用匹配价的涨幅) 转换成幅度需要乘100
  11592. ["DYNA_LB", null], //DYNA_LB DYNAINFO(17) 量比 即时行情数据
  11593. ["DYNA_ZAS",null], //DYNA_ZAS DYNAINFO(24) 返回涨速 报价界面行情数据 转换成幅度需要乘100
  11594. ["SELLVOL", null], //返回内盘,即DYNAINFO(22) 即时行情数据
  11595. ["BUYVOL", null], //返回外盘,即DYNAINFO(21) 即时行情数据
  11596. ['LARGEINTRDVOL', null], //逐笔买入大单成交量,相当于L2_VOL(0,0)+L2_VOL(1,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11597. ['LARGEOUTTRDVOL', null], //逐笔卖出大单成交量,相当于L2_VOL(0,1)+L2_VOL(1,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11598. ["TRADENUM", null], //逐笔成交总单数,沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11599. ["TRADEINNUM", null], //逐笔买入成交单数,相当于L2_VOLNUM(0,0)+L2_VOLNUM(1,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11600. ["TRADEOUTNUM", null], //逐笔卖出成交单数,相当于L2_VOLNUM(0,1)+L2_VOLNUM(1,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11601. ["LARGETRDINNUM", null], //逐笔买入大单成交单数,相当于L2_VOLNUM(0,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11602. ["LARGETRDOUTNUM", null], //逐笔卖出大单成交单数,相当于L2_VOLNUM(0,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11603. ["CUR_BUYORDER", null], //总委买量,序列数据,专业版等(资金流向功能)沪深京品种行情专用
  11604. ["CUR_SELLORDER", null], //总委卖量,序列数据,专业版等(资金流向功能)沪深京品种行情专用
  11605. ["ACTINVOL", null], //主动买成交量,相当于L2_VOL(0,2)+L2_VOL(1,2)+L2_VOL(2,2)+L2_VOL(3,2),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11606. ["ACTOUTVOL", null], //主动卖成交量,相当于L2_VOL(0,3)+L2_VOL(1,3)+L2_VOL(2,3)+L2_VOL(3,3),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11607. ["BIDORDERVOL", null], //累计总有效委买量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委买量-累计总有效撤买量=总买+总成交量
  11608. ["BIDCANCELVOL", null], //累计总有效撤买量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委买量-累计总有效撤买量=总买+总成交量
  11609. ["AVGBIDPX", null], //专业版等(资金流向功能)沪深京品种行情专用:最新委买均价
  11610. ["OFFERORDERVOL", null], //累计总有效委卖量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委卖量-累计总有效撤卖量=总卖+总成交量
  11611. ["OFFERCANCELVOL", null], //累计总有效撤卖量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委卖量-累计总有效撤卖量=总卖+总成交量
  11612. ["AVGOFFERPX", null], //专业版等(资金流向功能)沪深京品种行情专用:最新委卖均价
  11613. ]);
  11614. this.SymbolData=new JSSymbolData(this.AST,option,this);
  11615. this.Algorithm = new JSAlgorithm(this.ErrorHandler, this.SymbolData);
  11616. this.Draw = new JSDraw(this.ErrorHandler, this.SymbolData);
  11617. this.JobList=[]; //执行的任务队列
  11618. this.UpdateUICallback=null; //回调
  11619. this.CallbackParam=null;
  11620. this.Interrupt={ Exit:false }; //中断信息
  11621. if (option)
  11622. {
  11623. if (option.Callback) this.UpdateUICallback=option.Callback;
  11624. if (option.CallbackParam) this.CallbackParam=option.CallbackParam;
  11625. if (option.Arguments) this.Arguments=option.Arguments;
  11626. }
  11627. this.Execute=function()
  11628. {
  11629. JSConsole.Complier.Log('[JSExecute::Execute] JobList', this.JobList);
  11630. this.RunNextJob();
  11631. }
  11632. this.RunNextJob=function()
  11633. {
  11634. if (this.JobList.length<=0) return;
  11635. var jobItem=this.JobList.shift();
  11636. switch (jobItem.ID)
  11637. {
  11638. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA:
  11639. return this.SymbolData.GetSymbolData();
  11640. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA:
  11641. return this.SymbolData.GetIndexData();
  11642. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA:
  11643. return this.SymbolData.GetIndexIncreaseData(jobItem);
  11644. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA:
  11645. return this.SymbolData.GetLatestData(jobItem);
  11646. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA: //量比
  11647. return this.SymbolData.GetVolRateData(jobItem);
  11648. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA: //指定股票数据
  11649. return this.SymbolData.GetOtherSymbolData(jobItem);
  11650. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE:
  11651. return this.SymbolData.GetFinance(jobItem);
  11652. //专业财务数据
  11653. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE:
  11654. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE:
  11655. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE:
  11656. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYONE:
  11657. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE:
  11658. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYONE:
  11659. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE:
  11660. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYONE:
  11661. return this.SymbolData.GetProFinance(jobItem);
  11662. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT: //CAPITAL, TOTALCAPITAL
  11663. return this.SymbolData.GetVariantData(jobItem);
  11664. case JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA:
  11665. return this.SymbolData.GetCustomVariantData(jobItem);
  11666. case JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA:
  11667. return this.SymbolData.GetCustomFunctionData(jobItem);
  11668. case JS_EXECUTE_JOB_ID.JOB_CUSTOM_DATA_FUNCTION:
  11669. return this.SymbolData.GetCustomFunctionDataV2(jobItem);
  11670. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE:
  11671. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE:
  11672. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
  11673. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
  11674. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
  11675. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
  11676. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
  11677. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
  11678. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
  11679. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
  11680. return this.SymbolData.GetMarginData(jobItem.ID);
  11681. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: //负面新闻
  11682. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: //机构调研
  11683. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: //互动易
  11684. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: //股东增持
  11685. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: //股东减持
  11686. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: //信托持股
  11687. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: //大宗交易
  11688. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: //官网新闻
  11689. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: //高管要闻
  11690. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: //股权质押
  11691. return this.SymbolData.GetNewsAnalysisData(jobItem.ID);
  11692. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA:
  11693. return this.SymbolData.DownloadCustomAPIData(jobItem);
  11694. case JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX:
  11695. return this.SymbolData.CallScriptIndex(jobItem, this.VarTable);
  11696. case JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT:
  11697. return this.Run();
  11698. }
  11699. }
  11700. this.ReadSymbolData=function(name,node)
  11701. {
  11702. switch(name)
  11703. {
  11704. case 'CLOSE':
  11705. case 'C':
  11706. case 'VOL':
  11707. case 'V':
  11708. case 'OPEN':
  11709. case 'O':
  11710. case 'HIGH':
  11711. case 'H':
  11712. case 'LOW':
  11713. case 'L':
  11714. case 'AMOUNT':
  11715. case "OPI":
  11716. case 'VOLINSTK':
  11717. case "SETTLE":
  11718. case "QHJSJ":
  11719. case "ZSTJJ":
  11720. case "ISEQUAL": //平盘
  11721. case "ISUP": //收阳
  11722. case "ISDOWN": //收阴
  11723. return this.SymbolData.GetSymbolCacheData(name);
  11724. case 'VOLR':
  11725. return this.SymbolData.GetVolRateCacheData(node);
  11726. //大盘数据
  11727. case 'INDEXA':
  11728. case 'INDEXC':
  11729. case 'INDEXH':
  11730. case 'INDEXO':
  11731. case 'INDEXV':
  11732. case 'INDEXL':
  11733. case 'INDEXADV':
  11734. case 'INDEXDEC':
  11735. return this.SymbolData.GetIndexCacheData(name);
  11736. case 'CURRBARSCOUNT':
  11737. return this.SymbolData.GetCurrBarsCount();
  11738. case "BARPOS":
  11739. return this.SymbolData.GetBarPos();
  11740. case "TOTALBARSCOUNT":
  11741. return this.SymbolData.GetTotalBarsCount();
  11742. case "TOTALFZNUM":
  11743. return this.SymbolData.GetTotalTradeMinuteCount();
  11744. case 'ISLASTBAR':
  11745. return this.SymbolData.GetIsLastBar();
  11746. case "BARSTATUS":
  11747. return this.SymbolData.GetBarStatus();
  11748. case "TOTALCAPITAL":
  11749. case 'CAPITAL':
  11750. case 'EXCHANGE':
  11751. case "HYBLOCK":
  11752. case "DYBLOCK":
  11753. case "GNBLOCK":
  11754. case "FGBLOCK":
  11755. case "ZSBLOCK":
  11756. case "ZHBLOCK":
  11757. case "ZDBLOCK":
  11758. case "HYZSCODE":
  11759. case "GNBLOCKNUM":
  11760. case "FGBLOCKNUM":
  11761. case "ZSBLOCKNUM":
  11762. case "ZHBLOCKNUM":
  11763. case "ZDBLOCKNUM":
  11764. case "HYSYL":
  11765. case "HYSJL":
  11766. case 'FROMOPEN':
  11767. case "LARGEINTRDVOL":
  11768. case "LARGEOUTTRDVOL":
  11769. case "TRADENUM":
  11770. case "TRADEINNUM":
  11771. case "TRADEOUTNUM":
  11772. case "LARGETRDINNUM":
  11773. case "LARGETRDOUTNUM":
  11774. case "CUR_BUYORDER":
  11775. case "CUR_SELLORDER":
  11776. case "ACTINVOL":
  11777. case "ACTOUTVOL":
  11778. case "BIDORDERVOL":
  11779. case "BIDCANCELVOL":
  11780. case "AVGBIDPX":
  11781. case "OFFERORDERVOL":
  11782. case "OFFERCANCELVOL":
  11783. case "AVGOFFERPX":
  11784. return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node });
  11785. case 'SETCODE':
  11786. return this.SymbolData.SETCODE();
  11787. case 'CODE':
  11788. return this.SymbolData.GetSymbol();
  11789. case 'STKNAME':
  11790. return this.SymbolData.GetName();
  11791. case 'TIME':
  11792. return this.SymbolData.TIME();
  11793. case "TIME2":
  11794. return this.SymbolData.TIME2();
  11795. case 'DATE':
  11796. return this.SymbolData.DATE();
  11797. case "DATETIME":
  11798. return this.SymbolData.DateTime();
  11799. case 'YEAR':
  11800. return this.SymbolData.YEAR();
  11801. case 'MONTH':
  11802. return this.SymbolData.MONTH();
  11803. case 'WEEK':
  11804. case "WEEKDAY":
  11805. return this.SymbolData.WEEK();
  11806. case 'PERIOD':
  11807. return this.SymbolData.PERIOD();
  11808. case 'DRAWNULL':
  11809. case "NULL":
  11810. return this.SymbolData.GetDrawNull();
  11811. case "HOUR":
  11812. return this.SymbolData.HOUR();
  11813. case "MINUTE":
  11814. return this.SymbolData.MINUTE();
  11815. case "TQFLAG":
  11816. return this.SymbolData.Right;
  11817. case "MACHINEDATE":
  11818. {
  11819. var now=new Date();
  11820. return (now.getFullYear()*10000+(now.getMonth()*1)*100+now.getDate())-19000000;
  11821. }
  11822. case "MACHINETIME":
  11823. {
  11824. var now=new Date();
  11825. return now.getHours()*10000+(now.getMinutes()*1)*100+now.getSeconds();
  11826. }
  11827. case "MACHINEWEEK":
  11828. {
  11829. var now=new Date();
  11830. return now.getDay();
  11831. }
  11832. case "WEEKOFYEAR":
  11833. return this.SymbolData.WEEKOFYEAR();
  11834. case "DAYSTOTODAY":
  11835. return this.SymbolData.DAYSTOTODAY();
  11836. case "DYNA_NOW":
  11837. case "DYNA_ZAF":
  11838. case "DYNA_LB":
  11839. case "DYNA_ZAS":
  11840. case "SELLVOL":
  11841. case "BUYVOL":
  11842. return this.SymbolData.GetDynaCacheData(name);
  11843. default:
  11844. this.ThrowUnexpectedNode(node, '变量'+name+'不存在', name);
  11845. }
  11846. }
  11847. this.ReadCustomVariant=function(name,node)
  11848. {
  11849. return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node });
  11850. }
  11851. //读取变量
  11852. this.ReadVariable=function(name,node)
  11853. {
  11854. if (this.ConstVarTable.has(name))
  11855. {
  11856. let data=this.ConstVarTable.get(name);
  11857. if (data==null) //动态加载,用到再加载
  11858. {
  11859. data=this.ReadSymbolData(name,node);
  11860. this.ConstVarTable.set(name,data);
  11861. }
  11862. return data;
  11863. }
  11864. if (g_JSComplierResource.IsCustomVariant(name)) return this.ReadCustomVariant(name,node); //读取自定义变量
  11865. if (this.VarTable.has(name)) return this.VarTable.get(name);
  11866. if (name.indexOf("COLOR")==0)
  11867. {
  11868. var colorValue=JSComplier.ColorVarToRGB(name);
  11869. if (colorValue) return colorValue;
  11870. }
  11871. this.ThrowUnexpectedNode(node, '变量'+name+'不存在');
  11872. return null;
  11873. }
  11874. this.ReadMemberVariable = function (node)
  11875. {
  11876. var obj = node.Object;
  11877. var member = node.Property;
  11878. let maiObj;
  11879. if (obj.Type == Syntax.BinaryExpression || obj.Type == Syntax.LogicalExpression)
  11880. maiObj = this.VisitBinaryExpression(obj);
  11881. else if (obj.Type == Syntax.CallExpression)
  11882. maiObj = this.VisitCallExpression(obj);
  11883. else
  11884. maiObj = this.GetNodeValue(obj);
  11885. if (!maiObj) return null;
  11886. var value = maiObj[member.Name];
  11887. if (value) return value;
  11888. return null;
  11889. }
  11890. //单数据转成数组 个数和历史数据一致
  11891. this.SingleDataToArrayData = function (value)
  11892. {
  11893. let count = this.SymbolData.Data.Data.length;
  11894. let result = [];
  11895. for (let i = 0; i < count; ++i)
  11896. {
  11897. result[i] = value;
  11898. }
  11899. return result;
  11900. }
  11901. this.RunAST=function()
  11902. {
  11903. //预定义的变量
  11904. for(var i=0; i<this.Arguments.length; ++i)
  11905. {
  11906. var item =this.Arguments[i];
  11907. this.VarTable.set(item.Name,item.Value);
  11908. }
  11909. if (!this.AST) this.ThrowError();
  11910. if (!this.AST.Body) this.ThrowError();
  11911. for(var i=0;i<this.AST.Body.length; ++i)
  11912. {
  11913. var item =this.AST.Body[i];
  11914. this.VisitNode(item);
  11915. //输出变量
  11916. if (item.Type==Syntax.ExpressionStatement && item.Expression)
  11917. {
  11918. if (item.Expression.Type==Syntax.AssignmentExpression && item.Expression.Operator==':' && item.Expression.Left)
  11919. {
  11920. let assignmentItem=item.Expression;
  11921. let varName=assignmentItem.Left.Name;
  11922. let outVar=this.VarTable.get(varName);
  11923. if (this.VarDrawTable.has(varName)) //绘图函数赋值
  11924. {
  11925. let draw=this.VarDrawTable.get(varName);
  11926. this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
  11927. }
  11928. else
  11929. {
  11930. var type=0;
  11931. if (!Array.isArray(outVar))
  11932. {
  11933. if (typeof (outVar) == 'string')
  11934. {
  11935. var floatValue=parseFloat(outVar);
  11936. if (IFrameSplitOperator.IsNumber(floatValue))
  11937. {
  11938. outVar=this.SingleDataToArrayData(floatValue);
  11939. }
  11940. else
  11941. {
  11942. outVar=this.SingleDataToArrayData(outVar);
  11943. type=1001;
  11944. }
  11945. }
  11946. else outVar = this.SingleDataToArrayData(outVar);
  11947. }
  11948. this.OutVarTable.push({Name:varName, Data:outVar,Type:type});
  11949. }
  11950. }
  11951. else if (item.Expression.Type==Syntax.CallExpression)
  11952. {
  11953. let callItem=item.Expression;
  11954. if (this.Draw.IsDrawFunction(callItem.Callee.Name))
  11955. {
  11956. let draw=callItem.Draw;
  11957. draw.Name=callItem.Callee.Name;
  11958. this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
  11959. }
  11960. else if (callItem.Callee.Name==="IFC" && callItem.Draw)
  11961. {
  11962. let draw=callItem.Draw;
  11963. draw.Name=draw.DrawType;
  11964. this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
  11965. }
  11966. else
  11967. {
  11968. let outVar=callItem.Out;
  11969. varName=`__temp_c_${callItem.Callee.Name}_${i}__`;
  11970. var type=0;
  11971. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11972. this.OutVarTable.push({Name:varName, Data:outVar,Type:type,NoneName:true});
  11973. }
  11974. }
  11975. else if (item.Expression.Type==Syntax.Identifier)
  11976. {
  11977. let varName=item.Expression.Name;
  11978. let outVar=this.ReadVariable(varName,item.Expression);
  11979. var type=0;
  11980. if (!Array.isArray(outVar))
  11981. {
  11982. if (typeof(outVar)=='string') outVar=this.SingleDataToArrayData(parseFloat(outVar));
  11983. else outVar=this.SingleDataToArrayData(outVar);
  11984. }
  11985. varName="__temp_i_"+i+"__";
  11986. this.OutVarTable.push({Name:varName, Data:outVar, Type:type, NoneName:true});
  11987. }
  11988. else if (item.Expression.Type==Syntax.Literal) //常量
  11989. {
  11990. let outVar=item.Expression.Value;
  11991. if (IFrameSplitOperator.IsString(outVar) && outVar.indexOf("$")>0)
  11992. outVar=this.SymbolData.GetOtherSymolCacheData({ Literal:outVar });
  11993. varName="__temp_li_"+i+"__";
  11994. var type=0;
  11995. this.OutVarTable.push({Name:varName, Data:outVar, Type:type, NoneName:true});
  11996. }
  11997. else if (item.Expression.Type==Syntax.BinaryExpression)
  11998. {
  11999. var varName="__temp_b_"+i+"__";
  12000. let outVar=item.Expression.Out;
  12001. var type=0;
  12002. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  12003. this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
  12004. }
  12005. else if (item.Expression.Type==Syntax.LogicalExpression) //逻辑语句 如 T1 AND T2
  12006. {
  12007. var varName="__temp_l_"+i+"__";
  12008. let outVar=item.Expression.Out;
  12009. var type=0;
  12010. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  12011. this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
  12012. }
  12013. else if (item.Expression.Type==Syntax.UnaryExpression)
  12014. {
  12015. var varName="__temp_u_"+i+"__";
  12016. var varInfo={ };
  12017. if (this.ReadUnaryExpression(item.Expression, varInfo))
  12018. {
  12019. var type=0;
  12020. this.OutVarTable.push({Name:varName, Data:varInfo.OutVar,Type:type, NoneName:true});
  12021. }
  12022. }
  12023. else if (item.Expression.Type==Syntax.MemberExpression) //MA.MA2
  12024. {
  12025. var outVar=this.ReadMemberVariable(item.Expression);
  12026. if (outVar)
  12027. {
  12028. var type=0;
  12029. var varName="__temp_di_"+i+"__";
  12030. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  12031. this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
  12032. }
  12033. }
  12034. else if (item.Expression.Type==Syntax.SequenceExpression)
  12035. {
  12036. var varName;
  12037. var draw;
  12038. var color, upColor, downColor, stickType;
  12039. var lineWidth;
  12040. var colorStick=false;
  12041. var pointDot=false;
  12042. var upDownDot=false;
  12043. var circleDot=false;
  12044. var lineStick=false;
  12045. var isDotLine=false;
  12046. var stick=false;
  12047. var volStick=false;
  12048. var lineArea=false;
  12049. var stepLine=false;
  12050. var isShow = true;
  12051. var isExData = false;
  12052. var isOverlayLine = false; //叠加线
  12053. var isSingleLine=false; //独立线段
  12054. var isNoneName=false;
  12055. var isShowTitle=true;
  12056. //显示在位置之上,对于DRAWTEXT和DRAWNUMBER等函数有用,放在语句的最后面(不能与LINETHICK等函数共用),比如:
  12057. //DRAWNUMBER(CLOSE>OPEN,HIGH,CLOSE),DRAWABOVE;
  12058. var isDrawAbove=false;
  12059. //VALIGN0,VALIGN1,VALIGN2 设置文字垂直对齐方式(上中下)
  12060. //ALIGN0,ALIGN1,ALIGN2 设置文字水平对齐方式(左中右)
  12061. var drawAlign=-1, drawVAlign=-1;
  12062. var fontSize=-1;
  12063. var bgConfig=null;
  12064. var vLineConfig=null;
  12065. var xOffset=null, yOffset=null;
  12066. var lineDash=null;
  12067. for(var j=0 ; j<item.Expression.Expression.length; ++j)
  12068. {
  12069. let itemExpression=item.Expression.Expression[j];
  12070. if (itemExpression.Type==Syntax.AssignmentExpression && itemExpression.Operator==':' && itemExpression.Left)
  12071. {
  12072. if (j==0)
  12073. {
  12074. varName = itemExpression.Left.Name;
  12075. let varValue = this.VarTable.get(varName);
  12076. if (this.VarDrawTable.has(varName)) //绘图函数赋值
  12077. {
  12078. draw=this.VarDrawTable.get(varName);
  12079. }
  12080. else if (!Array.isArray(varValue))
  12081. {
  12082. varValue = this.SingleDataToArrayData(varValue);
  12083. this.VarTable.set(varName, varValue); //把常量放到变量表里
  12084. }
  12085. }
  12086. }
  12087. else if (itemExpression.Type==Syntax.Identifier)
  12088. {
  12089. let value=itemExpression.Name;
  12090. if (value==='COLORSTICK') colorStick=true;
  12091. else if (value==='POINTDOT') pointDot=true;
  12092. else if (value=="UPDOWNDOT") upDownDot=true;
  12093. else if (value==='CIRCLEDOT') circleDot=true;
  12094. else if (value == 'DOTLINE') isDotLine = true;
  12095. else if (value==='LINESTICK') lineStick=true;
  12096. else if (value==='STICK') stick=true;
  12097. else if (value==='VOLSTICK') volStick=true;
  12098. else if (value=="LINEAREA") lineArea=true;
  12099. else if (value=="STEPLINE") stepLine=true;
  12100. else if (value==="DRAWABOVE") isDrawAbove=true;
  12101. else if (value==="SINGLELINE") isSingleLine=true;
  12102. else if (value.indexOf('COLOR')==0) color=value;
  12103. else if (value.indexOf("RGBX")==0 && value.length==10) color=value; //RGBX+“RRGGBB”
  12104. else if (value.indexOf('LINETHICK')==0) lineWidth=value;
  12105. else if (value=="ALIGN0") drawAlign=0;
  12106. else if (value=="ALIGN1") drawAlign=1;
  12107. else if (value=="ALIGN2") drawAlign=2;
  12108. else if (value=="VALIGN0") drawVAlign=0;
  12109. else if (value=="VALIGN1") drawVAlign=1;
  12110. else if (value=="VALIGN2") drawVAlign=2;
  12111. else if (value.indexOf('NODRAW') == 0) isShow = false;
  12112. else if (value.indexOf('EXDATA') == 0) isExData = true; //扩展数据, 不显示再图形里面
  12113. else if (value.indexOf('LINEOVERLAY') == 0) isOverlayLine = true;
  12114. else if (value.indexOf("NOTEXT")==0 || value.indexOf("NOTITLE")==0) isShowTitle=false; //标题不显示
  12115. else if (value.indexOf("FONTSIZE")==0)
  12116. {
  12117. var strFontSize=value.replace("FONTSIZE","");
  12118. fontSize=parseInt(strFontSize);
  12119. }
  12120. else
  12121. {
  12122. if (j==0)
  12123. {
  12124. varName=itemExpression.Name;
  12125. let varValue=this.ReadVariable(varName,itemExpression);
  12126. if (!Array.isArray(varValue)) varValue=this.SingleDataToArrayData(varValue);
  12127. varName="__temp_si_"+i+"__";
  12128. isNoneName=true;
  12129. this.VarTable.set(varName,varValue); //放到变量表里
  12130. }
  12131. }
  12132. }
  12133. else if (itemExpression.Type == Syntax.Literal) //常量
  12134. {
  12135. if (j==0)
  12136. {
  12137. let aryValue = this.SingleDataToArrayData(itemExpression.Value);
  12138. varName = itemExpression.Value.toString();
  12139. this.VarTable.set(varName, aryValue); //把常量放到变量表里
  12140. }
  12141. }
  12142. else if (itemExpression.Type==Syntax.CallExpression)
  12143. {
  12144. if (j==0)
  12145. {
  12146. if (this.Draw.IsDrawFunction(itemExpression.Callee.Name))
  12147. {
  12148. draw=itemExpression.Draw;
  12149. draw.Name=itemExpression.Callee.Name;
  12150. }
  12151. else
  12152. {
  12153. let varValue=itemExpression.Out;
  12154. varName=`__temp_sc_${itemExpression.Callee.Name}_${i}__`;
  12155. isNoneName=true;
  12156. this.VarTable.set(varName,varValue);
  12157. }
  12158. }
  12159. else
  12160. {
  12161. if (itemExpression.Callee.Name=="RGB" || itemExpression.Callee.Name=="RGBA")
  12162. {
  12163. color=itemExpression.Out;
  12164. }
  12165. else if (itemExpression.Callee.Name=="UPCOLOR")
  12166. {
  12167. upColor=itemExpression.Out;
  12168. }
  12169. else if (itemExpression.Callee.Name=="DOWNCOLOR")
  12170. {
  12171. downColor=itemExpression.Out;
  12172. }
  12173. else if (itemExpression.Callee.Name=="STICKTYPE")
  12174. {
  12175. stickType=itemExpression.Out;
  12176. }
  12177. else if (itemExpression.Callee.Name=="XMOVE")
  12178. {
  12179. xOffset=itemExpression.Out;
  12180. }
  12181. else if (itemExpression.Callee.Name=="YMOVE")
  12182. {
  12183. yOffset=itemExpression.Out;
  12184. }
  12185. else if (itemExpression.Callee.Name=="LINEDASH")
  12186. {
  12187. if (IFrameSplitOperator.IsNonEmptyArray(itemExpression.Out))
  12188. lineDash=itemExpression.Out.slice();
  12189. }
  12190. else if (itemExpression.Callee.Name=="SOUND")
  12191. {
  12192. var event=this.GetSoundEvent();
  12193. if (event)
  12194. {
  12195. }
  12196. varName=null;
  12197. }
  12198. else if (itemExpression.Callee.Name=="ICON")
  12199. {
  12200. let drawCond=this.VarTable.get(varName);
  12201. if (drawCond)
  12202. {
  12203. draw=this.GetOutIconData(drawCond,itemExpression.Draw);
  12204. if (draw) draw.Name=itemExpression.Callee.Name;
  12205. }
  12206. varName=null;
  12207. }
  12208. else if (itemExpression.Callee.Name=="BACKGROUND")
  12209. {
  12210. bgConfig=itemExpression.Draw;
  12211. varName=null;
  12212. }
  12213. else if (itemExpression.Callee.Name=="CKLINE")
  12214. {
  12215. vLineConfig=itemExpression.Draw;
  12216. varName=null;
  12217. }
  12218. }
  12219. }
  12220. else if (itemExpression.Type==Syntax.BinaryExpression)
  12221. {
  12222. if (j==0)
  12223. {
  12224. varName="__temp_sb_"+i+"__";
  12225. let aryValue=itemExpression.Out;
  12226. isNoneName=true;
  12227. this.VarTable.set(varName,aryValue);
  12228. }
  12229. }
  12230. else if (itemExpression.Type==Syntax.UnaryExpression)
  12231. {
  12232. if (j==0)
  12233. {
  12234. varName="__temp_su_"+i+"__";
  12235. var varInfo={ };
  12236. if (this.ReadUnaryExpression(itemExpression, varInfo))
  12237. {
  12238. isNoneName=true;
  12239. this.VarTable.set(varName,varInfo.OutVar);
  12240. }
  12241. }
  12242. }
  12243. else if (itemExpression.Type==Syntax.MemberExpression) //"MA.MA2"(5,12,29), COLORRED;
  12244. {
  12245. if (j==0)
  12246. {
  12247. var outVar=this.ReadMemberVariable(itemExpression);
  12248. if (outVar)
  12249. {
  12250. if (!Array.isArray(outVar)) varValue=this.SingleDataToArrayData(outVar);
  12251. isNoneName=true;
  12252. varName="__temp_di_"+i+"__";
  12253. this.VarTable.set(varName,outVar); //把常量放到变量表里
  12254. }
  12255. }
  12256. }
  12257. }
  12258. if (pointDot && varName) //圆点
  12259. {
  12260. let outVar=this.VarTable.get(varName);
  12261. let value={Name:varName, Data:outVar, Radius:g_JSChartResource.POINTDOT.Radius, Type:3};
  12262. if (color) value.Color=color;
  12263. if (lineWidth) value.LineWidth = lineWidth;
  12264. this.OutVarTable.push(value);
  12265. }
  12266. else if (circleDot && varName) //圆点
  12267. {
  12268. let outVar=this.VarTable.get(varName);
  12269. let value={Name:varName, Data:outVar, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3};
  12270. if (color) value.Color=color;
  12271. if (lineWidth) value.LineWidth = lineWidth;
  12272. this.OutVarTable.push(value);
  12273. }
  12274. else if (upDownDot && varName) //彩色点
  12275. {
  12276. let outVar=this.VarTable.get(varName);
  12277. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  12278. let value={Name:varName, Data:outVar, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3, UpDownDot:true };
  12279. if (color) value.Color=color;
  12280. if (upColor) value.UpColor=upColor;
  12281. if (downColor) value.DownColor=downColor;
  12282. if (lineWidth) value.LineWidth=lineWidth;
  12283. this.OutVarTable.push(value);
  12284. }
  12285. else if (lineStick && varName) //LINESTICK 同时画出柱状线和指标线
  12286. {
  12287. let outVar=this.VarTable.get(varName);
  12288. let value={Name:varName, Data:outVar, Type:4};
  12289. if (color) value.Color=color;
  12290. if (lineWidth) value.LineWidth=lineWidth;
  12291. this.OutVarTable.push(value);
  12292. }
  12293. else if (stick && varName) //STICK 画柱状线
  12294. {
  12295. let outVar=this.VarTable.get(varName);
  12296. let value={Name:varName, Data:outVar, Type:5};
  12297. if (color) value.Color=color;
  12298. if (lineWidth) value.LineWidth=lineWidth;
  12299. this.OutVarTable.push(value);
  12300. }
  12301. else if (volStick && varName) //VOLSTICK 画彩色柱状线
  12302. {
  12303. let outVar=this.VarTable.get(varName);
  12304. let value={Name:varName, Data:outVar, Type:6};
  12305. if (color) value.Color=color;
  12306. if (upColor) value.UpColor=upColor;
  12307. if (downColor) value.DownColor=downColor;
  12308. if (IFrameSplitOperator.IsNumber(stickType)) value.StickType=stickType;
  12309. this.OutVarTable.push(value);
  12310. }
  12311. else if (lineArea && varName) //LINEAREA 面积
  12312. {
  12313. let outVar=this.VarTable.get(varName);
  12314. let value={Name:varName, Data:outVar, Type:9};
  12315. if (color) value.Color=color;
  12316. if (upColor) value.UpColor=upColor;
  12317. if (downColor) value.DownColor=downColor;
  12318. if (lineWidth) value.LineWidth=lineWidth;
  12319. this.OutVarTable.push(value);
  12320. }
  12321. else if (colorStick && varName) //CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子
  12322. {
  12323. let outVar=this.VarTable.get(varName);
  12324. let value={Name:varName, Data:outVar, Color:color, Type:2};
  12325. if (lineWidth) value.LineWidth=lineWidth;
  12326. if (color) value.Color=color;
  12327. if (upColor) value.UpColor=upColor;
  12328. if (downColor) value.DownColor=downColor;
  12329. this.OutVarTable.push(value);
  12330. }
  12331. else if (varName && color && !draw)
  12332. {
  12333. let outVar=this.VarTable.get(varName);
  12334. let value={Name:varName, Data:outVar, Color:color, Type:0};
  12335. if (lineWidth) value.LineWidth=lineWidth;
  12336. if (isShow == false) value.IsShow = false;
  12337. if (isExData == true) value.IsExData = true;
  12338. if (IFrameSplitOperator.IsBool(isDotLine)) value.IsDotLine = isDotLine;
  12339. if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) value.LineDash=lineDash;
  12340. if (isOverlayLine == true) value.IsOverlayLine = true;
  12341. if (isSingleLine == true) value.IsSingleLine = true;
  12342. if (isNoneName==true) value.NoneName=true;
  12343. if (isShowTitle==false) value.IsShowTitle=false;
  12344. if (stepLine==true) value.Type=7;
  12345. this.OutVarTable.push(value);
  12346. }
  12347. else if (draw) //绘图函数
  12348. {
  12349. var outVar = { Name: draw.Name, Draw: draw, Type: 1 };
  12350. if (color) outVar.Color = color;
  12351. if (IFrameSplitOperator.IsBool(isDotLine)) outVar.IsDotLine=isDotLine;
  12352. if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) outVar.LineDash=lineDash;
  12353. if (lineWidth) outVar.LineWidth = lineWidth;
  12354. if (isDrawAbove) outVar.IsDrawAbove=true;
  12355. if (drawAlign>=0) outVar.DrawAlign=drawAlign;
  12356. if (drawVAlign>=0) outVar.DrawVAlign=drawVAlign;
  12357. if (fontSize>0) outVar.DrawFontSize=fontSize;
  12358. if (bgConfig) outVar.Background=bgConfig;
  12359. if (vLineConfig) outVar.VerticalLine=vLineConfig;
  12360. if (IFrameSplitOperator.IsNumber(xOffset)) outVar.XOffset=xOffset;
  12361. if (IFrameSplitOperator.IsNumber(yOffset)) outVar.YOffset=yOffset;
  12362. this.OutVarTable.push(outVar);
  12363. }
  12364. else if (varName)
  12365. {
  12366. let outVar = this.VarTable.get(varName);
  12367. let value = { Name: varName, Data: outVar, Type: 0 };
  12368. if (color) value.Color = color;
  12369. if (lineWidth) value.LineWidth = lineWidth;
  12370. if (isShow == false) value.IsShow = false;
  12371. if (isExData == true) value.IsExData = true;
  12372. if (isDotLine == true) value.IsDotLine = true;
  12373. if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) value.LineDash=lineDash;
  12374. if (isOverlayLine == true) value.IsOverlayLine = true;
  12375. if (isSingleLine == true) value.IsSingleLine = true;
  12376. if (isShowTitle==false) value.IsShowTitle=false;
  12377. if (stepLine==true) value.Type=7;
  12378. this.OutVarTable.push(value);
  12379. }
  12380. }
  12381. }
  12382. if (this.Interrupt && this.Interrupt.Exit)
  12383. {
  12384. JSConsole.Complier.Log('[JSExecute::RunAST] Interrupt', this.Interrupt); //中断退出
  12385. break;
  12386. }
  12387. }
  12388. JSConsole.Complier.Log('[JSExecute::RunAST]', this.VarTable);
  12389. return this.OutVarTable;
  12390. }
  12391. this.ReadUnaryExpression=function(item, varInfo)
  12392. {
  12393. var argument=item.Argument;
  12394. var outVar=null;
  12395. if (argument.Type==Syntax.Literal)
  12396. {
  12397. outVar=argument.Value;
  12398. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  12399. }
  12400. else if (argument.Type==Syntax.Identifier)
  12401. {
  12402. var varName=argument.Name;
  12403. outVar=this.ReadVariable(varName,item.Expression);
  12404. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  12405. }
  12406. else if (argument.Type==Syntax.BinaryExpression)
  12407. {
  12408. outVar=argument.Out;
  12409. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  12410. }
  12411. else if (argument.Type==Syntax.CallExpression)
  12412. {
  12413. var callItem=argument;
  12414. if (this.Draw.IsDrawFunction(callItem.Callee.Name) )
  12415. {
  12416. return false;
  12417. }
  12418. else if (callItem.Callee.Name==="IFC" && callItem.Draw)
  12419. {
  12420. return false;
  12421. }
  12422. else
  12423. {
  12424. outVar=callItem.Out;
  12425. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  12426. }
  12427. }
  12428. else
  12429. {
  12430. return false;
  12431. }
  12432. if (item.Operator=='-')
  12433. {
  12434. if (outVar) outVar=this.Algorithm.Subtract(0,outVar);
  12435. }
  12436. varInfo.OutVar=outVar;
  12437. return true;
  12438. }
  12439. this.GetOutIconData=function(cond, iconDraw)
  12440. {
  12441. if (Array.isArray(cond))
  12442. {
  12443. for(var i=0; i<cond.length && i<iconDraw.DrawData.length; ++i)
  12444. {
  12445. var item=cond[i];
  12446. if (item<=0) iconDraw.DrawData[i]=null;
  12447. }
  12448. return iconDraw;
  12449. }
  12450. if (cond) return iconDraw;
  12451. return null;
  12452. }
  12453. this.GetSoundEvent=function()
  12454. {
  12455. if (!this.GetEventCallback) return null;
  12456. return this.GetEventCallback(JSCHART_EVENT_ID.ON_PLAY_SOUND);
  12457. }
  12458. this.Run=function()
  12459. {
  12460. let data=this.RunAST();//执行脚本
  12461. JSConsole.Complier.Log('[JSComplier.Run] execute finish', data);
  12462. if (this.UpdateUICallback)
  12463. {
  12464. JSConsole.Complier.Log('[JSComplier.Run] invoke UpdateUICallback.');
  12465. if (this.CallbackParam && this.CallbackParam.Job && this.CallbackParam.Job.ID==JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX)
  12466. {
  12467. this.UpdateUICallback(data,this.CallbackParam, this.SymbolData);
  12468. }
  12469. else
  12470. {
  12471. if (this.CallbackParam && this.CallbackParam.Self && this.CallbackParam.Self.ClassName==='ScriptIndexConsole') this.CallbackParam.JSExecute=this;
  12472. if (this.IsUsePageData==true) this.CallbackParam.Self.IsUsePageData=true;
  12473. this.UpdateUICallback(data,this.CallbackParam);
  12474. }
  12475. }
  12476. }
  12477. this.VisitNode=function(node)
  12478. {
  12479. switch(node.Type)
  12480. {
  12481. case Syntax.SequenceExpression:
  12482. this.VisitSequenceExpression(node);
  12483. break;
  12484. case Syntax.ExpressionStatement:
  12485. this.VisitNode(node.Expression);
  12486. break;
  12487. case Syntax.AssignmentExpression:
  12488. this.VisitAssignmentExpression(node);
  12489. break;
  12490. case Syntax.BinaryExpression:
  12491. case Syntax.LogicalExpression:
  12492. this.VisitBinaryExpression(node);
  12493. break;
  12494. case Syntax.CallExpression:
  12495. this.VisitCallExpression(node);
  12496. break;
  12497. case Syntax.UnaryExpression:
  12498. this.VisitUnaryExpression(node);
  12499. break;
  12500. }
  12501. }
  12502. this.VisitSequenceExpression=function(node)
  12503. {
  12504. for(let i in node.Expression)
  12505. {
  12506. let item =node.Expression[i];
  12507. this.VisitNode(item);
  12508. }
  12509. }
  12510. this.VisitUnaryExpression=function(node)
  12511. {
  12512. if (node.Operator=='-')
  12513. {
  12514. var tempValue=this.GetNodeValueEx(node.Argument);
  12515. var value=this.Algorithm.Subtract(0,tempValue);
  12516. }
  12517. else
  12518. {
  12519. var value=node.Argument.Value;
  12520. }
  12521. return value;
  12522. }
  12523. this.GetDynamicScriptIndex=function(node, args)
  12524. {
  12525. var dynamicName=node.Callee.Value;
  12526. var aryValue=dynamicName.split(".");
  12527. if (aryValue.length!=2)
  12528. {
  12529. this.ThrowUnexpectedNode(node,`调用指标格式'${dynamicName}'错误`);
  12530. }
  12531. var name=aryValue[0];
  12532. var outName=aryValue[1];
  12533. var period=null;
  12534. var pos=outName.indexOf('#');
  12535. if (pos!=-1)
  12536. {
  12537. period=outName.slice(pos+1); //周期
  12538. outName=outName.slice(0,pos);
  12539. }
  12540. var strValue="";
  12541. for(var i=0; i<args.length; ++i)
  12542. {
  12543. var value=args[i];
  12544. if (strValue.length>0) strValue+=",";
  12545. strValue+=`${value}`;
  12546. }
  12547. var strArgs=`(${strValue})`;
  12548. var key=`${outName}#${strArgs}`;
  12549. if (period) key+=`#${period}`;
  12550. if (!this.VarTable.has(name)) return null;
  12551. var indexData=this.VarTable.get(name);
  12552. var value=indexData[key];
  12553. return value;
  12554. }
  12555. //函数调用
  12556. this.VisitCallExpression=function(node)
  12557. {
  12558. let funcName=node.Callee.Name;
  12559. let args=[];
  12560. for(let i=0; i<node.Arguments.length; ++i)
  12561. {
  12562. let item=node.Arguments[i];
  12563. let value;
  12564. if (funcName==="IFC" && i>=1)
  12565. break; //IFC先处理第1个条件参数
  12566. if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
  12567. value=this.VisitBinaryExpression(item);
  12568. else if (item.Type==Syntax.CallExpression)
  12569. value=this.VisitCallExpression(item);
  12570. else
  12571. value=this.GetNodeValue(item);
  12572. args.push(value);
  12573. }
  12574. if (node.Callee.Type==Syntax.Literal) //指标调用'MA.MA1'(6,12,18)
  12575. {
  12576. node.Out=[];
  12577. node.Draw=null;
  12578. var data=this.GetDynamicScriptIndex(node, args);
  12579. if (data) node.Out=data;
  12580. return node.Out;
  12581. }
  12582. if (funcName==="IFC")
  12583. {
  12584. //IFC(X,A,B)若X不为0则执行A,否则执行B.IFC与IF函数的区别:根据X的值来选择性执行A、B表达式.
  12585. var bResult=this.Algorithm.IFC(args[0]);
  12586. var item=bResult? node.Arguments[1] : node.Arguments[2];
  12587. var value;
  12588. if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
  12589. value=this.VisitBinaryExpression(item);
  12590. else if (item.Type==Syntax.CallExpression)
  12591. value=this.VisitCallExpression(item);
  12592. else
  12593. value=this.GetNodeValue(item);
  12594. node.Out=value;
  12595. if (item.Draw) node.Draw=item.Draw;
  12596. return node.Out;
  12597. }
  12598. //if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitCallExpression]' , funcName, '(', args.toString() ,')');
  12599. if (g_JSComplierResource.IsCustomFunction(funcName)) //自定义函数
  12600. {
  12601. var data=this.Algorithm.CallCustomFunction(funcName, args, this.SymbolData, node);
  12602. node.Out=[];
  12603. node.Draw=null;
  12604. if (data)
  12605. {
  12606. if (data.Out) node.Out=data.Out;
  12607. if (data.Draw) node.Draw=data.Draw;
  12608. }
  12609. return node.Out;
  12610. }
  12611. if (g_JSComplierResource.IsCustomDataFunction(funcName))
  12612. {
  12613. var functionInfo=g_JSComplierResource.CustomDataFunction.Data.get(funcName);
  12614. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:functionInfo.ArgCount, Node:node } );
  12615. node.Draw=null;
  12616. return node.Out;
  12617. }
  12618. switch(funcName)
  12619. {
  12620. case 'DYNAINFO': //行情最新数据
  12621. node.Out=this.SymbolData.GetLatestCacheData(args[0]);
  12622. break;
  12623. case 'STICKLINE':
  12624. node.Draw=this.Draw.STICKLINE(args[0],args[1],args[2],args[3],args[4]);
  12625. node.Out=[];
  12626. break;
  12627. case 'DRAWTEXT':
  12628. node.Draw=this.Draw.DRAWTEXT(args[0],args[1],args[2]);
  12629. node.Out=[];
  12630. break;
  12631. case 'SUPERDRAWTEXT':
  12632. node.Draw = this.Draw.SUPERDRAWTEXT(args[0], args[1], args[2], args[3], args[4]);
  12633. node.Out = [];
  12634. break;
  12635. case 'DRAWTEXT_FIX':
  12636. node.Draw=this.Draw.DRAWTEXT_FIX(args[0],args[1],args[2],args[3],args[4]);
  12637. node.Out=[];
  12638. break;
  12639. case "DRAWNUMBER_FIX":
  12640. node.Draw=this.Draw.DRAWNUMBER_FIX(args[0],args[1],args[2],args[3],args[4],args[5]);
  12641. node.Out=[];
  12642. break;
  12643. case 'DRAWICON':
  12644. node.Draw = this.Draw.DRAWICON(args[0], args[1], args[2], args[3]);
  12645. node.Out = [];
  12646. break;
  12647. case "ICON":
  12648. node.Draw=this.Draw.ICON(args[0],args[1]);
  12649. node.Out=[];
  12650. break;
  12651. case "BACKGROUND":
  12652. node.Draw=this.Draw.BACKGROUND(args[0],args[1],args[2],args[3],args[4],args[5]);
  12653. node.Out=[];
  12654. break;
  12655. case "CKLINE":
  12656. node.Draw=this.Draw.CKLINE(args[0],args[1],args[2],args[3],args[4]);
  12657. node.Out=[];
  12658. break;
  12659. case 'DRAWLINE':
  12660. node.Draw=this.Draw.DRAWLINE(args[0],args[1],args[2],args[3],args[4]);
  12661. node.Out=node.Draw.DrawData;
  12662. break;
  12663. case 'DRAWBAND':
  12664. node.Draw=this.Draw.DRAWBAND(args[0],args[1],args[2],args[3]);
  12665. node.Out=[];
  12666. break;
  12667. case 'DRAWKLINE':
  12668. case "DRAWKLINE1":
  12669. node.Draw = this.Draw.DRAWKLINE(args[0], args[1], args[2], args[3]);
  12670. node.Out = [];
  12671. break;
  12672. case 'DRAWKLINE_IF':
  12673. node.Draw = this.Draw.DRAWKLINE_IF(args[0], args[1], args[2], args[3], args[4]);
  12674. node.Out = [];
  12675. break;
  12676. case "DRAWCOLORKLINE":
  12677. node.Draw=this.Draw.DRAWCOLORKLINE(args[0],args[1],args[2]);
  12678. node.Out=[];
  12679. break;
  12680. case 'PLOYLINE':
  12681. case 'POLYLINE':
  12682. node.Draw = this.Draw.POLYLINE(args[0], args[1]);
  12683. node.Out = node.Draw.DrawData;
  12684. break;
  12685. case 'DRAWNUMBER':
  12686. node.Draw = this.Draw.DRAWNUMBER(args[0], args[1], args[2], args[3]);
  12687. node.Out = node.Draw.DrawData.Value;
  12688. break;
  12689. case 'RGB':
  12690. node.Out = this.Draw.RGB(args[0], args[1], args[2]);
  12691. break;
  12692. case 'RGBA':
  12693. node.Out = this.Draw.RGBA(args[0], args[1], args[2],args[3]);
  12694. break;
  12695. case "UPCOLOR":
  12696. node.Out=this.Draw.UPCOLOR(args[0]);
  12697. break;
  12698. case "DOWNCOLOR":
  12699. node.Out=this.Draw.DOWNCOLOR(args[0]);
  12700. break;
  12701. case "STICKTYPE":
  12702. node.Out=this.Draw.STICKTYPE(args[0]);
  12703. break;
  12704. case "XMOVE":
  12705. node.Out=this.Draw.XMOVE(args[0]);
  12706. break;
  12707. case "YMOVE":
  12708. node.Out=this.Draw.YMOVE(args[0]);
  12709. break;
  12710. case "LINEDASH":
  12711. node.Out=this.Draw.LINEDASH(args);
  12712. break;
  12713. case 'PARTLINE':
  12714. node.Draw=this.Draw.PARTLINE(args);
  12715. node.Out=[];
  12716. break;
  12717. case 'DRAWRECTREL':
  12718. node.Draw = this.Draw.DRAWRECTREL(args[0], args[1], args[2], args[3], args[4]);
  12719. node.Out = [];
  12720. break;
  12721. case "DRAWTEXTREL":
  12722. node.Draw=this.Draw.DRAWTEXTREL(args[0],args[1],args[2]);
  12723. node.Out=[];
  12724. break;
  12725. case "DRAWTEXTABS":
  12726. node.Draw=this.Draw.DRAWTEXTABS(args[0],args[1],args[2]);
  12727. node.Out=[];
  12728. break;
  12729. case 'DRAWGBK':
  12730. node.Draw=this.Draw.DRAWGBK(args[0],args[1],args[2],args[3]);
  12731. node.Out=[];
  12732. break;
  12733. case 'DRAWGBK2':
  12734. node.Draw=this.Draw.DRAWGBK2(args[0],args[1],args[2],args[3]);
  12735. node.Out=[];
  12736. break;
  12737. case "DRAWGBK_DIV":
  12738. node.Draw=this.Draw.DRAWGBK_DIV(args[0],args[1],args[2],args[3],args[4]);
  12739. node.Out=[];
  12740. break;
  12741. case 'CODELIKE':
  12742. node.Out=this.SymbolData.CODELIKE(args[0]);
  12743. break;
  12744. case 'NAMELIKE':
  12745. case "NAMEINCLUDE":
  12746. node.Out = this.SymbolData.NAMELIKE(args[1]);
  12747. break;
  12748. case 'REFDATE':
  12749. node.Out = this.SymbolData.REFDATE(args[0], args[1]);
  12750. break;
  12751. case 'FINANCE':
  12752. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } );
  12753. break;
  12754. case "FINVALUE":
  12755. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } );
  12756. break;
  12757. case "FINONE":
  12758. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } );
  12759. break;
  12760. case "GPJYVALUE":
  12761. case "SCJYVALUE":
  12762. case "BKJYVALUE":
  12763. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } );
  12764. break;
  12765. case "GPJYONE":
  12766. case "SCJYONE":
  12767. case "BKJYONE":
  12768. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:4, Node:node } );
  12769. break;
  12770. case "MARGIN":
  12771. node.Out = this.SymbolData.GetMarginCacheData(args[0], node);
  12772. break;
  12773. case "NEWS":
  12774. node.Out = this.SymbolData.GetNewsAnalysisCacheData(args[0], node);
  12775. break;
  12776. case 'UPCOUNT':
  12777. case 'DOWNCOUNT':
  12778. node.Out = this.SymbolData.GetIndexIncreaseCacheData(funcName, args[0], node);
  12779. break;
  12780. case 'LOADAPIDATA':
  12781. node.Out = this.SymbolData.GetCustomApiData(args);
  12782. break;
  12783. case "STKINDI":
  12784. case "CALCSTOCKINDEX":
  12785. node.Out=this.SymbolData.GetScriptIndexOutData(args,node,funcName);
  12786. break;
  12787. case 'CLOSE':
  12788. case 'C':
  12789. case 'VOL':
  12790. case 'V':
  12791. case 'OPEN':
  12792. case 'O':
  12793. case 'HIGH':
  12794. case 'H':
  12795. case 'LOW':
  12796. case 'L':
  12797. case 'AMOUNT':
  12798. case 'AMO':
  12799. node.Out=this.SymbolData.GetOtherSymolCacheData( {FunctionName:funcName, Args:args} );
  12800. break;
  12801. case "INBLOCK":
  12802. node.Out=this.SymbolData.IsInBlock(args[0],node);
  12803. break;
  12804. case "SYSPARAM":
  12805. node.Out=this.SymbolData.SysParam(args[0], this);
  12806. break;
  12807. case "TESTSKIP":
  12808. var bExit=this.Algorithm.TESTSKIP(args[0],node);
  12809. node.Out=null;
  12810. if (bExit)
  12811. {
  12812. this.Interrupt.Exit=true;
  12813. if (node && node.Marker)
  12814. {
  12815. var marker=node.Marker;
  12816. this.Interrupt.Line=marker.Line;
  12817. this.Interrupt.Index=marker.Index;
  12818. this.Interrupt.Column=marker.Column;
  12819. }
  12820. }
  12821. break;
  12822. default:
  12823. node.Out=this.Algorithm.CallFunction(funcName, args,node);
  12824. break;
  12825. }
  12826. return node.Out;
  12827. }
  12828. //赋值
  12829. this.VisitAssignmentExpression=function(node)
  12830. {
  12831. let left=node.Left;
  12832. if (left.Type!=Syntax.Identifier) this.ThrowUnexpectedNode(node);
  12833. let varName=left.Name;
  12834. let right=node.Right;
  12835. let value=null,drawValue=null;
  12836. if (right.Type==Syntax.BinaryExpression || right.Type==Syntax.LogicalExpression)
  12837. value=this.VisitBinaryExpression(right);
  12838. else if (right.Type==Syntax.CallExpression)
  12839. {
  12840. value=this.VisitCallExpression(right);
  12841. if (right.Draw) drawValue=right.Draw;
  12842. }
  12843. else if (right.Type==Syntax.Literal)
  12844. {
  12845. value=right.Value;
  12846. if (IFrameSplitOperator.IsString(value) && right.Value.indexOf("$")>0)
  12847. value=this.SymbolData.GetOtherSymolCacheData( {Literal:value} );
  12848. }
  12849. else if (right.Type==Syntax.Identifier) //右值是变量
  12850. value=this.ReadVariable(right.Name,right);
  12851. else if (right.Type == Syntax.MemberExpression)
  12852. value = this.ReadMemberVariable(right);
  12853. else if (right.Type==Syntax.UnaryExpression)
  12854. value=this.VisitUnaryExpression(right);
  12855. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitAssignmentExpression]' , varName, ' = ',value);
  12856. if (drawValue) this.VarDrawTable.set(varName, drawValue);
  12857. this.VarTable.set(varName,value);
  12858. }
  12859. //逻辑运算
  12860. this.VisitBinaryExpression=function(node)
  12861. {
  12862. let stack=[];
  12863. stack.push(node);
  12864. let temp=null;
  12865. while(stack.length!=0)
  12866. {
  12867. temp=stack[stack.length-1];
  12868. if (temp.Left && node!=temp.Left && node!=temp.Right)
  12869. {
  12870. stack.push(temp.Left);
  12871. }
  12872. else if (temp.Right && node!=temp.Right)
  12873. {
  12874. stack.push(temp.Right);
  12875. }
  12876. else
  12877. {
  12878. let value=stack.pop();
  12879. if (value.Type==Syntax.BinaryExpression) //只遍历操作符就可以
  12880. {
  12881. let leftValue=this.GetNodeValue(value.Left);
  12882. let rightValue=this.GetNodeValue(value.Right);
  12883. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue);
  12884. value.Out=null; //保存中间值
  12885. switch(value.Operator)
  12886. {
  12887. case '-':
  12888. value.Out=this.Algorithm.Subtract(leftValue,rightValue);
  12889. break;
  12890. case '*':
  12891. value.Out=this.Algorithm.Multiply(leftValue,rightValue);
  12892. break;
  12893. case '/':
  12894. value.Out=this.Algorithm.Divide(leftValue,rightValue)
  12895. break;
  12896. case '+':
  12897. value.Out=this.Algorithm.Add(leftValue,rightValue);
  12898. break;
  12899. case '>':
  12900. value.Out=this.Algorithm.GT(leftValue,rightValue);
  12901. break;
  12902. case '>=':
  12903. value.Out=this.Algorithm.GTE(leftValue,rightValue);
  12904. break;
  12905. case '<':
  12906. value.Out=this.Algorithm.LT(leftValue,rightValue);
  12907. break;
  12908. case '<=':
  12909. value.Out=this.Algorithm.LTE(leftValue,rightValue);
  12910. break;
  12911. case '==':
  12912. case '=':
  12913. value.Out=this.Algorithm.EQ(leftValue,rightValue);
  12914. break;
  12915. case '!=':
  12916. case '<>':
  12917. value.Out = this.Algorithm.NEQ(leftValue, rightValue);
  12918. break;
  12919. }
  12920. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value);
  12921. }
  12922. else if (value.Type==Syntax.LogicalExpression)
  12923. {
  12924. let leftValue=this.GetNodeValue(value.Left);
  12925. let rightValue=this.GetNodeValue(value.Right);
  12926. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue);
  12927. value.Out=null; //保存中间值
  12928. switch(value.Operator)
  12929. {
  12930. case '&&':
  12931. case 'AND':
  12932. value.Out=this.Algorithm.And(leftValue,rightValue);
  12933. break;
  12934. case '||':
  12935. case 'OR':
  12936. value.Out=this.Algorithm.Or(leftValue,rightValue);
  12937. break;
  12938. }
  12939. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value);
  12940. }
  12941. node=temp;
  12942. }
  12943. }
  12944. return node.Out;
  12945. }
  12946. //获取节点值,BinaryExpression,LogicalExpression会重新计算
  12947. this.GetNodeValueEx=function(item)
  12948. {
  12949. var value=null;
  12950. if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
  12951. value=this.VisitBinaryExpression(item);
  12952. else if (item.Type==Syntax.CallExpression)
  12953. value=this.VisitCallExpression(item);
  12954. else
  12955. value=this.GetNodeValue(item);
  12956. return value;
  12957. }
  12958. this.GetNodeValue=function(node)
  12959. {
  12960. switch(node.Type)
  12961. {
  12962. case Syntax.Literal: //数字
  12963. return node.Value;
  12964. case Syntax.UnaryExpression:
  12965. var value=this.VisitUnaryExpression(node);
  12966. return value;
  12967. case Syntax.Identifier:
  12968. var value=this.ReadVariable(node.Name,node);
  12969. return value;
  12970. case Syntax.BinaryExpression:
  12971. case Syntax.LogicalExpression:
  12972. return node.Out;
  12973. case Syntax.CallExpression:
  12974. return this.VisitCallExpression(node);
  12975. case Syntax.MemberExpression:
  12976. return this.ReadMemberVariable(node);
  12977. default:
  12978. this.ThrowUnexpectedNode(node);
  12979. }
  12980. }
  12981. this.ThrowUnexpectedNode=function(node,message)
  12982. {
  12983. let marker=node.Marker;
  12984. let msg=message || "执行异常";
  12985. return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
  12986. }
  12987. this.ThrowError=function()
  12988. {
  12989. }
  12990. }
  12991. //对外导出类
  12992. function JSComplier()
  12993. {
  12994. }
  12995. //词法分析
  12996. JSComplier.Tokenize=function(code)
  12997. {
  12998. JSConsole.Complier.Log('[JSComplier.Tokenize]', code);
  12999. let tokenizer=new Tokenizer(code);
  13000. let tokens=[];
  13001. try
  13002. {
  13003. while(true)
  13004. {
  13005. let token=tokenizer.GetNextToken();
  13006. if (!token) break;
  13007. tokens.push(token);
  13008. }
  13009. }
  13010. catch(e)
  13011. {
  13012. }
  13013. return tokens;
  13014. }
  13015. //语法解析 生成抽象语法树(Abstract Syntax Tree)
  13016. JSComplier.Parse=function(code)
  13017. {
  13018. JSConsole.Complier.Log('[JSComplier.Parse]',code);
  13019. let parser=new JSParser(code);
  13020. parser.Initialize();
  13021. let program=parser.ParseScript();
  13022. let ast=program;
  13023. return ast;
  13024. }
  13025. //颜色转rgb
  13026. JSComplier.ColorVarToRGB=function(colorName)
  13027. {
  13028. let COLOR_MAP=new Map(
  13029. [
  13030. ['COLORBLACK','rgb(0,0,0)'],
  13031. ['COLORBLUE','rgb(18,95,216)'],
  13032. ['COLORGREEN','rgb(25,158,0)'],
  13033. ['COLORCYAN','rgb(0,255,198)'],
  13034. ['COLORRED','rgb(238,21,21)'],
  13035. ['COLORMAGENTA','rgb(255,0,222)'],
  13036. ['COLORBROWN','rgb(149,94,15)'],
  13037. ['COLORLIGRAY','rgb(218,218,218)'], //画淡灰色
  13038. ['COLORGRAY','rgb(133,133,133)'], //画深灰色
  13039. ['COLORLIBLUE','rgb(94,204,255)'], //淡蓝色
  13040. ['COLORLIGREEN','rgb(183,255,190)'], //淡绿色
  13041. ['COLORLICYAN','rgb(154,255,242)'], //淡青色
  13042. ['COLORLIRED','rgb(255,172,172)'], //淡红色
  13043. ['COLORLIMAGENTA','rgb(255,145,241)'], //淡洋红色
  13044. ['COLORWHITE','rgb(255,255,255)'], //白色
  13045. ['COLORYELLOW','rgb(255,198,0)']
  13046. ]);
  13047. if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName);
  13048. //COLOR 自定义色
  13049. //格式为COLOR+“BBGGRR”:BB、GG、RR表示蓝色、绿色和红色的分量,每种颜色的取值范围是00-FF,采用了16进制。
  13050. //例如:MA5:MA(CLOSE,5),COLOR00FFFF表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。
  13051. if (colorName.indexOf('COLOR')==0)
  13052. {
  13053. var strColor=colorName.substr(5);
  13054. if (strColor.length!=6) return null;
  13055. var value=strColor.substr(0,2);
  13056. var b=parseInt(value,16);
  13057. value=strColor.substr(2,2);
  13058. var g=parseInt(value,16);
  13059. value=strColor.substr(4,2);
  13060. var r=parseInt(value,16);
  13061. return `rgb(${r},${g},${b})`;
  13062. }
  13063. //格式为RGBX+“RRGGBB”:RR、GG、BB表示红色、绿色和的蓝色分量,每种颜色的取值范围是00-FF,采用了16进制。
  13064. //例如:MA5:MA(CLOSE,5),RGBXFFFF00表示纯红色与纯绿色的混合色:RGBX008080表示淡蓝色和淡绿色的混合色。
  13065. if (colorName.indexOf("RGBX")==0)
  13066. {
  13067. var strColor=colorName.substr(4);
  13068. if (strColor.length!=6) return null;
  13069. var value=strColor.substr(0,2);
  13070. var r=parseInt(value,16);
  13071. value=strColor.substr(2,2);
  13072. var g=parseInt(value,16);
  13073. value=strColor.substr(4,2);
  13074. var b=parseInt(value,16);
  13075. return `rgb(${r},${g},${b})`;
  13076. }
  13077. return null;
  13078. }
  13079. /*
  13080. 执行
  13081. option.Symbol=股票代码
  13082. option.Name=股票名称
  13083. option.Data=这个股票的ChartData
  13084. option.Right=复权
  13085. option.MaxRequestDataCount=请求数据的最大个数
  13086. */
  13087. JSComplier.Execute=function(code,option,errorCallback)
  13088. {
  13089. //异步调用
  13090. var asyncExecute= function()
  13091. {
  13092. try
  13093. {
  13094. JSConsole.Complier.Log('[JSComplier.Execute] code ',code);
  13095. JSConsole.Complier.Log('[JSComplier.Execute] parser .....');
  13096. let parser=new JSParser(code);
  13097. parser.Initialize();
  13098. let program=parser.ParseScript();
  13099. let ast=program;
  13100. JSConsole.Complier.Log('[JSComplier.Execute] parser finish.', ast);
  13101. JSConsole.Complier.Log('[JSComplier.Execute] execute .....');
  13102. let execute=new JSExecute(ast,option);
  13103. execute.JobList=parser.Node.GetDataJobList();
  13104. execute.JobList.push({ID:JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT});
  13105. let result=execute.Execute();
  13106. }catch(error)
  13107. {
  13108. JSConsole.Complier.Log(error);
  13109. if (errorCallback) errorCallback(error);
  13110. }
  13111. }
  13112. asyncExecute();
  13113. JSConsole.Complier.Log('[JSComplier.Execute] async execute.');
  13114. }
  13115. JSComplier.SetDomain = function (domain, cacheDomain)
  13116. {
  13117. if (domain) g_JSComplierResource.Domain = domain;
  13118. if (cacheDomain) g_JSComplierResource.CacheDomain = cacheDomain;
  13119. }
  13120. JSComplier.AddFunction=function(obj) //添加函数 { Name:函数名, Description:描述信息, IsDownload:是否需要下载数据, Invoke:函数执行(可选) }
  13121. {
  13122. if (!obj || !obj.Name) return;
  13123. var ID=obj.Name.toUpperCase();
  13124. g_JSComplierResource.CustomFunction.Data.set(ID, obj);
  13125. }
  13126. JSComplier.AddVariant=function(obj) //{ Name:变量名, Description:描述信息 }
  13127. {
  13128. if (!obj || !obj.Name) return;
  13129. var ID=obj.Name.toUpperCase();
  13130. g_JSComplierResource.CustomVariant.Data.set(ID, obj);
  13131. }
  13132. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  13133. //
  13134. //数据下载
  13135. function DownloadFinanceData(obj)
  13136. {
  13137. this.Url=obj.Url;
  13138. this.RealtimeUrl=obj.RealtimeUrl;
  13139. this.Job=obj.Job;
  13140. this.Symbol=obj.Symbol;
  13141. this.Args=obj.Args;
  13142. this.DataKey=obj.DataKey;
  13143. this.RecvCallback=obj.Callback;
  13144. this.ErrorCallback=obj.ErrorCallback;
  13145. this.Download=function()
  13146. {
  13147. var id=this.Args[0];
  13148. switch(id)
  13149. {
  13150. case 1: //FINANCE(1) 总股本(随时间可能有变化) 股
  13151. case 7: //FINANCE(7) 流通股本(随时间可能有变化) 股
  13152. case "EXCHANGE": //换手率
  13153. this.DownloadHistoryData(id);
  13154. break;
  13155. case 9: //FINANCE(9) 资产负债率
  13156. case 18: //FINANCE(18) 每股公积金
  13157. case 30: //FINANCE(30) 净利润
  13158. case 32: //FINANCE(32) 每股未分配利润
  13159. case 33: //FINANCE(33) 每股收益(折算为全年收益),对于沪深品种有效
  13160. case 34: //FINANCE(34) 每股净资产
  13161. case 38: //FINANCE(38) 每股收益(最近一期季报)
  13162. case 40: //FINANCE(40) 流通市值
  13163. case 41: //FINANCE(41) 总市值
  13164. case 42: //FINANCE(42) 上市的天数
  13165. case 43: //FINANCE(43) 利润同比
  13166. case "CAPITAL":
  13167. case "TOTALCAPITAL":
  13168. //定制
  13169. case 100: //股东人数
  13170. this.DownloadRealtimeData(id);
  13171. break;
  13172. default:
  13173. this.DownloadRealtimeData(id);
  13174. break;
  13175. }
  13176. }
  13177. //最新一期数据
  13178. this.DownloadRealtimeData=function(id)
  13179. {
  13180. var self=this;
  13181. var fieldList=this.GetFieldList();
  13182. if (!fieldList)
  13183. {
  13184. if (this.Job.FunctionName2) message=`${this.Job.FunctionName2} can't support.`;
  13185. else if (this.Job.FunctionName) message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
  13186. else message=`${this.Args[0]} can't support.`;
  13187. this.ErrorCallback(message);
  13188. self.RecvCallback(null, self.Job, self.DataKey);
  13189. return;
  13190. }
  13191. //请求数据
  13192. JSNetwork.HttpRequest({
  13193. url: this.RealtimeUrl,
  13194. data:
  13195. {
  13196. "field": fieldList,
  13197. "symbol": [this.Symbol],
  13198. "condition":[ ] ,
  13199. "start": 0,
  13200. "end": 10
  13201. },
  13202. method: 'POST',
  13203. dataType: "json",
  13204. async:true,
  13205. success: function (recvData)
  13206. {
  13207. var data=self.RealtimeDataToHQChartData(recvData.data);
  13208. self.RecvCallback(data, self.Job, self.DataKey);
  13209. }
  13210. });
  13211. }
  13212. //历史数据
  13213. this.DownloadHistoryData=function(id)
  13214. {
  13215. var self=this;
  13216. var fieldList=this.GetFieldList();
  13217. if (!fieldList)
  13218. {
  13219. message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
  13220. this.ErrorCallback(message);
  13221. self.RecvCallback(null, self.Job, self.DataKey);
  13222. return;
  13223. }
  13224. //请求数据
  13225. JSNetwork.HttpRequest({
  13226. url: this.Url,
  13227. data:
  13228. {
  13229. "field": fieldList,
  13230. "symbol": [this.Symbol],
  13231. "condition":[ ] ,
  13232. "start": 0,
  13233. "end": 200
  13234. },
  13235. method: 'POST',
  13236. dataType: "json",
  13237. async:true,
  13238. success: function (recvData)
  13239. {
  13240. var data=self.ToHQChartData(recvData.data);
  13241. if (data) //排序
  13242. data.sort(function (a, b) { return (a.Date - b.Date) });
  13243. self.RecvCallback(data, self.Job, self.DataKey);
  13244. }
  13245. });
  13246. }
  13247. this.GetFieldList=function()
  13248. {
  13249. var id=this.Args[0];
  13250. switch(id)
  13251. {
  13252. case 1:
  13253. return ["capital.total", "capital.date"];
  13254. case 7:
  13255. return ["capital.a", "capital.date"];
  13256. case "EXCHANGE":
  13257. return ["capital.a", "capital.date"];
  13258. case 9:
  13259. return ["finance.peruprofit","symbol","date"];
  13260. case 18:
  13261. return ["finance.percreserve","symbol","date"];
  13262. case 30:
  13263. return ["finance.nprofit","symbol","date"];
  13264. case 32:
  13265. return ["finance.peruprofit","symbol","date"];
  13266. case 33:
  13267. return ["finance.persearning","symbol","date"];
  13268. case 34:
  13269. return ["finance.pernetasset","symbol","date"];
  13270. case 38:
  13271. return ["finance.persearning","symbol","date"];
  13272. case 40:
  13273. return ["capital.a", "capital.date","symbol","date", "price"];
  13274. case 41:
  13275. return ["capital.total", "capital.date","symbol","date","price"];
  13276. case "CAPITAL":
  13277. return ["capital.a", "capital.date","symbol","date"];
  13278. case "TOTALCAPITAL":
  13279. return ["capital.total", "capital.date","symbol","date"];
  13280. case 42:
  13281. return ["company.releasedate","symbol","date"];
  13282. case 43:
  13283. return ["dividendyield","symbol","date"];
  13284. case 100:
  13285. return ["shareholder","symbol","date"]
  13286. default:
  13287. return null;
  13288. }
  13289. }
  13290. //最新报告期数据
  13291. this.RealtimeDataToHQChartData=function(recvData,id)
  13292. {
  13293. if (!recvData.stock || recvData.stock.length!=1) return null;
  13294. var stock=recvData.stock[0];
  13295. var id=this.Args[0];
  13296. var date=stock.date;
  13297. switch(id)
  13298. {
  13299. case 9:
  13300. if (!stock.finance) return null;
  13301. return { Date:date, Value:stock.finance.peruprofit };
  13302. case 18:
  13303. if (!stock.finance) return null;
  13304. return { Date:date, Value:stock.finance.percreserve };
  13305. case 30:
  13306. if (!stock.finance) return null;
  13307. return { Date:date, Value:stock.finance.nprofit };
  13308. case 32:
  13309. if (!stock.finance) return null;
  13310. return { Date:date, Value:stock.finance.peruprofit };
  13311. case 33:
  13312. if (!stock.finance) return null;
  13313. return { Date:date, Value:stock.finance.persearning };
  13314. case 34:
  13315. if (!stock.finance) return null;
  13316. return { Date:date, Value:stock.finance.pernetasset };
  13317. case 38:
  13318. if (!stock.finance) return null;
  13319. return { Date:date, Value:stock.finance.persearning };
  13320. case 40: //FINANCE(40) 流通市值
  13321. if (!stock.capital) return null;
  13322. return { Date:date, Value:stock.capital.a*stock.price }; //流通股*最新价格
  13323. case 41: //FINANCE(41) 总市值
  13324. if (!stock.capital) return null;
  13325. return { Date:date, Value:stock.capital.total*stock.price }; //总股本*最新价格
  13326. case 42: //FINANCE(42) 上市的天数
  13327. if (!stock.company) return null;
  13328. {
  13329. var releaseDate=stock.company.releasedate;
  13330. var year=parseInt(releaseDate/10000);
  13331. var month=parseInt((releaseDate%10000)/100);
  13332. var day=releaseDate%100;
  13333. var firstDate=new Date(year, month-1, day);
  13334. var nowDate=new Date();
  13335. var days=parseInt((nowDate.getTime()-firstDate.getTime())/(1000 * 60 * 60 * 24));
  13336. return { Date:date, Value:days+1 };
  13337. }
  13338. case 43:
  13339. if (!stock.dividendyield) return null;
  13340. return { Date:date, Value:stock.dividendyield.quarter4 };
  13341. case 100:
  13342. if (!stock.shareholder) return null;
  13343. return { Date:date, Value:stock.shareholder.count };
  13344. case "CAPITAL":
  13345. if (!stock.capital) return null;
  13346. return { Date:date, Value:stock.capital.a/100 }; //当前流通股本 手
  13347. case "TOTALCAPITAL":
  13348. if (!stock.capital) return null;
  13349. return { Date:date, Value:stock.capital.total/100 }; //当前流通股本 手
  13350. }
  13351. }
  13352. //历史数据转
  13353. this.ToHQChartData=function(recvData)
  13354. {
  13355. if (!recvData.stock || recvData.stock.length!=1) return null;
  13356. var aryData=[];
  13357. var setDate=new Set(); //有重复数据 去掉
  13358. var stock=recvData.stock[0];
  13359. var id=this.Args[0];
  13360. for(var i in stock.stockday)
  13361. {
  13362. var item=stock.stockday[i];
  13363. var hqchartItem=this.ToHQChartItemData(item,id);
  13364. if (hqchartItem && !setDate.has(hqchartItem.Date))
  13365. {
  13366. aryData.push(hqchartItem);
  13367. setDate.add(hqchartItem.Date);
  13368. }
  13369. }
  13370. return aryData;
  13371. }
  13372. this.ToHQChartItemData=function(item, id)
  13373. {
  13374. if (!item) return null;
  13375. var date=item.date;
  13376. switch(id)
  13377. {
  13378. case 1:
  13379. if (!item.capital) return null;
  13380. return { Date:date, Value:item.capital.total };
  13381. case 7:
  13382. case "EXCHANGE": //换手率 历史流通股本
  13383. if (!item.capital) return null;
  13384. return { Date:date, Value:item.capital.a };
  13385. default:
  13386. return null;
  13387. }
  13388. }
  13389. }
  13390. function DownloadGroupData(obj)
  13391. {
  13392. this.Url=obj.Url;
  13393. this.RealtimeUrl=obj.RealtimeUrl;
  13394. this.Job=obj.Job;
  13395. this.Symbol=obj.Symbol;
  13396. this.Args=obj.Args;
  13397. this.DataKey=obj.DataKey;
  13398. this.RecvCallback=obj.Callback;
  13399. this.ErrorCallback=obj.ErrorCallback;
  13400. this.Download=function()
  13401. {
  13402. var varName=this.Args[0];
  13403. switch(varName)
  13404. {
  13405. case "HYBLOCK":
  13406. case "DYBLOCK":
  13407. case "GNBLOCK":
  13408. this.DownloadGroupName(varName);
  13409. break;
  13410. }
  13411. }
  13412. this.DownloadGroupName=function(blockType)
  13413. {
  13414. var self=this;
  13415. var field=["name","symbol"];
  13416. if (blockType=="HYBLOCK") field.push("industry");
  13417. else if (blockType=="DYBLOCK") field.push("region");
  13418. else if (blockType=="GNBLOCK") field.push("concept");
  13419. JSNetwork.HttpRequest({
  13420. url: self.RealtimeUrl,
  13421. data:
  13422. {
  13423. "field": field,
  13424. "symbol": [this.Symbol]
  13425. },
  13426. method:"post",
  13427. dataType: "json",
  13428. async:true,
  13429. success: function (recvData)
  13430. {
  13431. var data=self.RecvGroupName(recvData.data);
  13432. self.RecvCallback(data, self.Job, self.DataKey, 1);
  13433. },
  13434. error: function(request)
  13435. {
  13436. self.ErrorCallback(request);
  13437. }
  13438. });
  13439. }
  13440. this.RecvGroupName=function(recvData)
  13441. {
  13442. if (!recvData.stock || recvData.stock.length!=1) return null;
  13443. var stock=recvData.stock[0];
  13444. var varName=this.Args[0];
  13445. var value=null;
  13446. if (varName=="HYBLOCK")
  13447. {
  13448. var industry=stock.industry;
  13449. if (!industry) return null;
  13450. var value;
  13451. for(var i in industry)
  13452. {
  13453. var item=industry[i];
  13454. value=item.name;
  13455. }
  13456. }
  13457. else if (varName=="DYBLOCK")
  13458. {
  13459. var region=stock.region;
  13460. if (!region) return null;
  13461. for(var i in region)
  13462. {
  13463. var item=region[i];
  13464. value=item.name;
  13465. }
  13466. }
  13467. else if (varName=="GNBLOCK")
  13468. {
  13469. var concept=stock.concept;
  13470. if (!concept) return null;
  13471. value="";
  13472. for(var i in concept)
  13473. {
  13474. var item=concept[i];
  13475. if (value.length>0) value+=' ';
  13476. value+=item.name;
  13477. }
  13478. }
  13479. return { Value:value };
  13480. }
  13481. }
  13482. /* 测试例子
  13483. var code1='VARHIGH:IF(VAR1<=REF(HH,-1),REF(H,BARSLAST(VAR1>=REF(HH,1))),DRAWNULL),COLORYELLOW;';
  13484. var code2='VAR1=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);';
  13485. var code3='mm1=1-2*-9+20;';
  13486. JSConsole.Complier.Log(code1+code2)
  13487. var tokens=JSComplier.Tokenize(code1+code2);
  13488. var ast=JSComplier.Parse(code2+code1);
  13489. JSConsole.Complier.Log(ast);
  13490. */
  13491. var JSCommonComplier=
  13492. {
  13493. JSComplier: JSComplier,
  13494. g_JSComplierResource: g_JSComplierResource,
  13495. };
  13496. export
  13497. {
  13498. JSCommonComplier,
  13499. ErrorHandler,
  13500. JSComplier,
  13501. JSParser,
  13502. Syntax,
  13503. JS_EXECUTE_JOB_ID,
  13504. g_JSComplierResource,
  13505. };
  13506. /*
  13507. module.exports =
  13508. {
  13509. JSCommonComplier:
  13510. {
  13511. JSComplier: JSComplier,
  13512. g_JSComplierResource: g_JSComplierResource,
  13513. },
  13514. //单个类导出
  13515. JSCommonComplier_ErrorHandler: ErrorHandler,
  13516. JSCommonComplier_JSComplier:JSComplier,
  13517. JSCommonComplier_JSParser:JSParser,
  13518. JSCommonComplier_Syntax:Syntax,
  13519. JS_EXECUTE_JOB_ID:JS_EXECUTE_JOB_ID,
  13520. g_JSComplierResource:g_JSComplierResource,
  13521. };
  13522. */