123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341 |
- if (!window.console || !window.console.log || !window.console.error) {
- window.console = { log: function(x) { myalert(x) }, error: function(x) { myalert(x) } };
- }
- function array_diff(arr1, arr2) {
- var diff = [];
- for (var i = 0; i < arr1.length; i++) {
- if (!in_array(arr2, arr1[i])) {
- diff.push(arr1[i]);
- }
- }
- return diff;
- }
- function array_equal(arr1, arr2) {
- if (is_array(arr1) && is_array(arr2)) {
- if (arr1.length != arr2.length) return false;
- for (var i = 0; i < arr1.length; i++) {
- if (!array_equal(arr1[i], arr2[i])) {
- return false;
- }
- }
- return true;
- } else {
- return arr1 == arr2;
- }
- }
- function in_array(arr, value) {
- for (var i = 0; i < arr.length; i++) {
- if (array_equal(arr[i], value)) return true;
- }
- return false;
- }
- //*没有用到
- // function playmusic(url) {
- // var id = "__music__embed__player__";
- // var obj = document.getElementById(id);
- // url = __baseurl__ + "js/music/" + encodeURI(url);
- // if (obj == null) {
- // var oDiv = document.createElement("DIV");
- // oDiv.id = id;
- // oDiv.style.position = "absolute";
- // oDiv.style.width = "1px";
- // oDiv.style.height = "1px";
- // oDiv.style.top = "-2000px";
- // document.body.appendChild(oDiv);
- // obj = oDiv;
- // }
- // if (url.match(new RegExp("\\.wav$", 'ig'))) {
- // playwav(obj, url);
- // } else {
- // playmp3swf(obj, url);
- // }
- // }
- function isIE() {
- var ua = navigator.userAgent.toLowerCase();
- var s;
- if (ua.match(new RegExp("msie\\s+([\\d.]+)", "ig"))) {
- return true;
- }
- return false;
- }
- // function playwav(obj, url) {
- // var html;
- // if (isIE()) {
- // html = '<embed name="music" height="1px" width="1px" src="' + url + '" />';
- // } else {
- // html = '<audio height="1px" width="1px" autoplay="true">';
- // html += '<source name="music" src="' + url + '" type="audio/x-wav" />';
- // html += '</audio>';
- // }
- // obj.innerHTML = html;
- // }
- // function playmp3swf(obj, url) {
- // var url = escape(url);
- // var html = '<embed type="application/x-shockwave-flash" wmode="transparent" ' + 'src="' + __baseurl__ + 'js/audio-player.swf" flashvars="audioUrl=' + url + '&autoPlay=true" height="1px" width="1px"></embed>';
- // obj.innerHTML = html;
- // }
- function myalert(text) {
- if (__javascript_debug__) {
- //alert(text);
- }
- }
- function GetText(value, unit) {
- if (unit < 1) {
- unit = -Math.floor(Math.log(unit) / Math.LN10);
- var text = FormatNumber(value, unit);
- } else if (unit == 1) {
- var text = Math.floor(value) + ".0";
- } else {
- var text = value;
- }
- return text;
- }
- function triggerKeydown(code) {
- var e = jQuery.Event("keydown");
- e.keyCode = code;
- $(document).trigger(e);
- }
- /*
- function Alert(obj, showFunction)
- {
- var str = "";
- var key;
- if (typeof showFunction == "undefined")
- {
- showFunction = true;
- }
- if (typeof obj == 'object')
- {
- for (key in obj)
- {
- if (typeof key == 'string')
- {
- if (typeof obj[key] == 'function')
- {
- if (showFunction)
- {
- str += key +" => (\n "+Alert(obj[key])+"\n)\n";
- }
- } else {
- str += key +" => (\n "+Alert(obj[key])+"\n)\n";
- }
- }
- }
- return str;
- } else {
- if (typeof obj === "undefined")
- {
- return "undefined";
- } else if (obj === null) {
- return "null";
- } else {
- return obj.toString();
- }
- }
- }
- */
- /*没有用到
- function url_concat(base, str)
- {
- var last = base.charAt(base.length - 1);
- if (base.indexOf("?") != -1)
- {
- if(last != "?") {
- return base + "&" + str;
- } else {
- return base + str;
- }
- } else {
- return base + "?" + str;
- }
- }*/
- //controller里面作为判断
- function is_undefined(obj) {
- return typeof obj === "undefined";
- }
- //object copy复制一份数据
- function object_copy(obj, copy_array) {
- var newobj = {};
- if (is_array(obj)) {
- if (copy_array) {
- return array_copy(obj);
- } else {
- return obj;
- }
- }
- if (typeof obj == 'object') {
- for (var key in obj) {
- newobj[key] = object_copy(obj[key]);
- }
- } else {
- return obj;
- }
- return newobj;
- }
- //深度拷贝
- function array_copy(arr) {
- var copy = new Array(arr.length);
- for (var i = 0; i < arr.length; i++) {
- if (is_array(arr[i])) {
- copy[i] = array_copy(arr[i]);
- } else {
- copy[i] = arr[i];
- }
- }
- return copy;
- }
- //判断是否是数组
- function is_array(a) {
- return Object.prototype.toString.call(a) === "[object Array]";
- }
- function ClassExtend(sub, base) {
- //before:
- //alert("before");
- //alert(Alert(oparnet.prototype));
- for (var property in base.prototype) {
- sub.prototype[property] = base.prototype[property];
- }
- sub.prototype.constructor = sub;
- //获得基类
- sub.__parent = base;
- if (!base.__sub) {
- base.__sub = [];
- }
- //保存继承它的子类
- base.__sub.push(sub);
- }
- function ClassNew(classname) {
- var args = Array.prototype.slice.call(arguments, 1);
- var _this = this;
- function F() {
- _this.parent = classname.apply(_this, args);
- return _this.parent;
- }
- F.prototype = classname.prototype;
- return new F();
- }
- function getClassName(obj) {
- var str = obj.constructor.toString();
- var regexp = new RegExp("function(\\s+)([^\\(]+)", "ig");
- str = regexp.exec(str);
- return $.trim(str[2]);
- }
- function sup(_this) {
- var args = Array.prototype.slice.call(arguments, 1);
- if (_this.constructor && _this.constructor.__parent) {
- if (typeof _this.__counter === 'undefined') {
- // It has not... perform the initilization
- _this.__counter = 0;
- }
- _this.__counter++;
- if (_this.__counter > 1) //不是第一次调用继承
- {
- var _parent = _this.constructor.__parent;
- for (var i = 1; i < _this.__counter; i++) {
- _parent = _parent.__parent;
- }
- args.unshift(_parent);
- ClassNew.apply(_this, args);
- } else {
- args.unshift(_this.constructor.__parent);
- ClassNew.apply(_this, args);
- }
- }
- }
- function Point(x, y, z) {
- this.x = x;
- this.y = y;
- if (z !== undefined || z !== null) {
- this.z = z;
- }
- }
- function FormatNumber(srcStr, nAfterDot) {
- var nten = Math.pow(10, nAfterDot);
- srcStr = Math.round(parseFloat(srcStr) * nten) / nten;
- srcStr = srcStr.toString();
- var arr = srcStr.split(".");
- if (arr[1] == null) {
- return srcStr + "." + bulidZero(nAfterDot);
- }
- if (arr[1].length < nAfterDot) {
- var offset = nAfterDot - arr[1].length;
- srcStr += bulidZero(offset);
- }
- return srcStr;
- }
- function bulidZero(num) {
- var srcStr = '';
- for (var i = 0; i < num; i++) {
- srcStr += "0";
- }
- return srcStr;
- }
- function array_copy1d(arr) {
- var copy = new Array(arr.length);
- for (var i = 0; i < arr.length; i++) {
- copy[i] = arr[i];
- }
- return copy;
- }
- function array_copy2d(arr) {
- var copy = new Array(arr.length);
- for (var i = 0; i < arr.length; i++) {
- var len = arr[i].length;
- copy[i] = new Array(len);
- for (var j = 0; j < len; j++) {
- copy[i][j] = arr[i][j];
- }
- }
- return copy;
- }
- //得到最大最小值
- function minmax(data, start_index, end_index) {
- if (!start_index) start_index = 0;
- if (!end_index) end_index = data.length - 1;
- if (is_array(data[start_index])) {
- return _minmax2d(data, start_index, end_index);
- } else {
- return _minmax1d(data, start_index, end_index);
- }
- }
- //辅助minmax
- function _minmax2d(data, start_index, end_index) {
- var max = -Infinity;
- var min = Infinity;
- var maxIndex="";
- var minIndex="";
- for (var i = start_index; i <= end_index; i++) {
- for (var j = 0; j < data[i].length; j++) {
- if (data[i][j] >= max) {
- max = data[i][j];
- maxIndex=[i,j];
- }
- if (data[i][j] < min){
- min = data[i][j];
- minIndex=[i,j]
- }
- }
- }
- return [min, max,minIndex,maxIndex];
- }
- //辅助minmax
- function _minmax1d(data, start_index, end_index) {
- var max = -Infinity;
- var min = Infinity;
- var maxIndex="";
- var minIndex="";
- for (var i = start_index; i <= end_index; i++) {
- if (data[i] >= max) {
- max = data[i];
- maxIndex=i;
- }
- if (data[i] < min) {
- min = data[i];
- minIndex=i;
- }
- }
- return [min, max,minIndex,maxIndex];
- }
- //画行
- function drawRow(ctx, point, len, color, width) {
- var x = point.x;
- var y = point.y;
- if (isNaN(y)) {
- debug("draw row y nan");
- }
- ctx.beginPath();
- if (width) ctx.lineWidth = width;
- if (color) ctx.strokeStyle = color;
- ctx.moveTo(x, y + 0.5);
- ctx.lineTo(x + len, y + 0.5);
- ctx.closePath();
- ctx.stroke();
- }
- //画列
- function drawCol(ctx, point, len, color, width) {
- var x = point.x;
- var y = point.y;
- ctx.beginPath();
- if (width) ctx.lineWidth = width;
- if (color) ctx.strokeStyle = color;
- ctx.moveTo(x + 0.5, y);
- ctx.lineTo(x + 0.5, y + len);
- ctx.closePath();
- ctx.stroke();
- }
- //时间转换成日期格式
- function timeToDate(time, format, timezone) {
- if (!format) format = "Y-m-d H:i:s";
- if (!timezone) timezone = 0;
- var date = new Date();
- if (format.indexOf(".") == -1) // time no msecond
- {
- time *= 1000;
- }
- time += (date.getTimezoneOffset() + timezone * 60) * 60 * 1000;
- date.setTime(time);
- var y = date.getFullYear();
- var m = date.getMonth() + 1;
- var d = date.getDate();
- var h = date.getHours();
- var i = date.getMinutes();
- var s = date.getSeconds();
- var u = date.getMilliseconds();
- format = time_replace(format, "Y", y);
- format = time_replace(format, "m", m);
- format = time_replace(format, "d", d);
- format = time_replace(format, "H", h);
- format = time_replace(format, "i", i);
- format = time_replace(format, "s", s);
- format = time_replace(format, "u", u, 3);
- return format;
- }
- //时间标准模式
- function formatTime(time, p) {
- var conf = Config.getInstance()
- var unit = conf.Global.xunit[p]
- if (unit) {
- unit = unit * 60;
- return Math.floor(time / unit) * unit
- }
- return time
- }
- //formatTime 辅助函数
- function time_replace(format, search, n, zero_number) {
- if (typeof zero_number === "undefined") {
- zero_number = 2;
- }
- if (n < 10) n = padingZero(n, zero_number) + n;
- return format.replace(search, n);
- }
- //time_replace 辅助函数
- function padingZero(n, zero_number) {
- if (n < 0) {
- return n;
- }
- var zn = zero_number - 1;
- if (n > 0) {
- var zero_current_num = Math.floor(Math.log(n) / Math.LN10) + 1;
- zn = zero_number - zero_current_num;
- }
- var zero = "";
- for (var i = 0; i < zn; i++) {
- zero += "0";
- }
- return zero;
- }
- //在k线图上写内容
- function writeText(ctx, point, text, color, font) {
- //console.log(window.do_drawText);
- if (isIPhone() && window.do_drawText) {
- //手机内容设置
- text = text.toString();
- if (color) ctx.strokeStyle = color;
- do_drawText.call(ctx, text, point.x, point.y - 10, 9);
- } //电脑内容设置
- else if (ctx.fillText) {
- if (color) ctx.fillStyle = color;
- if (font) { ctx.font = font; } else { ctx.font = "normal small-caps normal 1.1em Arial" }
- ctx.fillText(text, point.x, point.y);
- } else {
- if (color) ctx.strokeStyle = color;
- if (font) { ctx.font = font; } else { ctx.font = "normal small-caps normal 1.1em Arial" }
- ctx.strokeText(text, point.x, point.y);
- }
- }
- /*
- * 画带箭头的虚线
- */
- function drawWithArrowheads(x1,y1,x2,y2,ctx){
- // arbitrary styling
- ctx.strokeStyle="#ff6600";
- ctx.fillStyle="#ff6600";
- ctx.lineWidth=1;
- // draw the line
- ctx.beginPath();
- ctx.moveTo(x1,y1);
- ctx.lineTo(x2,y2);
- ctx.stroke();
- // draw the starting arrowhead
- var startRadians=Math.atan((y2-y1)/(x2-x1));
- startRadians+=((x2>x1)?-90:90)*Math.PI/180;
- this.drawArrowhead(ctx,x1,y1,startRadians);
- // draw the ending arrowhead
- var endRadians=Math.atan((y2-y1)/(x2-x1));
- endRadians+=((x2>x1)?90:-90)*Math.PI/180;
- drawArrowhead(ctx,x2,y2,endRadians);
- }
- function drawArrowhead(ctx,x,y,radians){
- ctx.save();
- ctx.beginPath();
- ctx.translate(x,y);
- ctx.rotate(radians);
- ctx.moveTo(0,0);
- ctx.lineTo(3,10);
- ctx.lineTo(-3,10);
- ctx.closePath();
- ctx.restore();
- ctx.fill();
- }
- /*
- * 画虚线
- *
- */
- function drawDashLine(context,x1,y1,x2,y2,pattern)
- {
- pattern = pattern === undefined ? 5 : pattern;
- //得到斜边的总长度
- // calculate the delta x and delta y
- var dx = (x2 - x1);
- var dy = (y2 - y1);
- var distance = Math.floor(Math.sqrt(dx*dx + dy*dy));
- var dashlineInteveral = (pattern <= 0) ? distance : (distance/pattern);
- var deltay = (dy/distance) * pattern;
- var deltax = (dx/distance) * pattern;
- // draw dash line
- context.beginPath();
- context.lineWidth=0.7;
- context.strokeStyle="#333";
- for(var dl=0; dl<dashlineInteveral; dl++) {
- if(dl%2) {
- context.lineTo(x1 + dl*deltax, y1 + dl*deltay);
- } else {
- context.moveTo(x1 + dl*deltax, y1 + dl*deltay);
- }
- }
- context.stroke();
- }
- //画canvas层的分割线 折线
- function drawLever(ctx,x,y,color,width,heigh){
- ctx.beginPath();
- ctx.strokeStyle = color;
- //设置路径起点坐标
- ctx.moveTo(x, y);
- //定义中间点坐标1
- ctx.lineTo(x+width, y);
- //定义中间点坐标2
- ctx.lineTo(x+width, y-heigh);
- //按照绘制路径顺序连接各个坐标点
- ctx.stroke();
- //关闭绘制路径
- ctx.closePath();
- }
- //画线
- function drawLine(ctx, X, Y, color, width) {
- ctx.beginPath();
- if (width) ctx.lineWidth = width;
- if (color) ctx.strokeStyle = color;
- ctx.moveTo(X[0], Y[0]);
- var prevx = X[0];
- var prevy = Y[0];
- for (var i = 1; i < X.length; i++) {
- if (prevx == X[i] && prevy == Y[i]) {
- continue;
- }
- prevx = X[i];
- prevy = Y[i];
- ctx.lineTo(X[i], Y[i]);
- }
- ctx.stroke();
- }
- //plotLine plot画线
- function plotLine(ctx, p1, p2, color, width) {
- ctx.beginPath();
- if (width) ctx.lineWidth = width;
- if (color) ctx.strokeStyle = color;
- ctx.moveTo(p1.x, p1.y);
- ctx.lineTo(p2.x, p2.y);
- ctx.closePath();
- ctx.stroke();
- }
- //debug打印信息
- function debug(msg) {
- var d = $("#debug");
- if (d) {
- var time = (new Date()).getTime();
- var msecond = time % 1000;
- time = Math.floor(time / 1000);
- d.append(time + "(" + msecond + ")" + ": " + msg + "<br />");
- }
- }
- /*貌似没有用到
- function debugx(msg)
- {
- var d = $("#debugx");
- if (d)
- {
- var time = (new Date()).getTime();
- var msecond = time % 1000;
- time = Math.floor(time / 1000);
- d.append(time + "("+ msecond +")" + ": " + msg + "<br />");
- }
- }*/
- //得到当前时间
- function getTime() {
- return (new Date()).getTime();
- }
- /*/从小到大排列的数组 没有使用
- function find_first_big(arr, match)
- {
- //结束条件是:match >= arr[mid] && match <= arr[mid + 1], 也就是在 mid 和 mid + 1 的之间, 这样,mid + 1 就是first big
- var start = 0;
- var end = arr.length - 1;
- while (start <= end)
- {
- mid = Math.floor((end - start) / 2) + start;
- if (mid + 1 > arr.length -1) //越界了, 只有在 start == end 的时候会发生,这个时候 mid = arr.length - 1
- {
- if (arr.length > 1)
- {
- if (arr[mid -1] >= match) //判断一下前面一个数字
- {
- return mid - 1;
- }
- }
- return arr[mid] >= match ? mid : -1;
- }
- if (match >= arr[mid] && match <= arr[mid + 1]) {
- return match == arr[mid] ? mid : mid + 1;
- } else if (arr[mid] < match) {
- start = mid + 1;
- } else { //macth
- end = mid - 1
- }
- }
- return -1;
- }*/
- ////查找到第一个点
- function find_first_big_r(arr, match) {
- //结束条件是:match >= arr[mid - 1] && match <= arr[mid + 1], 也就是在 mid 和 mid + 1 的之间, 这样,mid + 1 就是first big
- var start = 0;
- var end = arr.length - 1;
- if (arr[end] > match) {
- return end;
- }
- while (start <= end) {
- mid = Math.floor((end - start) / 2) + start;
- if (mid - 1 < 0) //最多有两个数据 start = 0, end = 0, 1
- {
- if (arr.length > 1) {
- if (arr[1] >= match) {
- return 1;
- }
- }
- return arr[0] >= match ? 0 : -1;
- }
- if (match >= arr[mid] && match <= arr[mid - 1]) {
- return match == arr[mid] ? mid : mid - 1;
- } else if (arr[mid] < match) {
- end = mid - 1;
- } else { //macth
- start = mid + 1
- }
- }
- return -1;
- }
- ////判断兼容性 手机 pc的兼容性
- function check_textRender(canvas) {
- //判断是否是iPhone 或者 ipad
- if (isIPhone()) {
- return false;
- }
- if (!canvas.get(0).getContext) {
- return true;
- }
- var ctx = canvas.get(0).getContext('2d');
- // ctx.drawImage('static/img/klogo.png',this.width, this.height);
- if (typeof ctx.strokeText == 'function' || ctx.fillText == 'function') {
- return true
- } else {
- return false
- }
- }
- //判断是否是iPhone 或者 ipad
- function isIPhone() //如果是iPhone,那么采用js库绘制, 已知的bug
- {
- var agent = navigator.userAgent;
- //agent = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_3 like Mac OS X; zh-cn) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7E18 Safari/528.16";
- if (agent.toLowerCase().indexOf("iphone") >= 0 || agent.toLowerCase().indexOf("ipad") >= 0) {
- return true;
- }
- return false;
- }
- //初始化标志位 对于空值做处理
- function init_obj(obj, c, p, default_value) {
- if (typeof obj === "undefined") {
- obj = {};
- }
- if (typeof obj[c] === "undefined") {
- obj[c] = {};
- }
- if (typeof obj[c][p] === "undefined") {
- obj[c][p] = default_value;
- }
- return obj;
- }
- //判断是否为object类型
- function is_object(obj, key) {
- if (key) {
- if (typeof obj[key] == "object") {
- return true;
- }
- return false;
- }
- return (typeof obj == "object");
- }
- //FzmCookie cookie 内容
- FzmCookie = {};
- //FzmCookie读函数 从cookie拿数据
- FzmCookie.read = function(name) {
- var cookieValue = "",
- search = name + "=";
- if (document.cookie.length > 0) {
- offset = document.cookie.indexOf(search);
- if (offset != -1) {
- if (offset > 0) {
- //去除空格部分
- var myoffset = offset;
- while (myoffset > 0 && document.cookie.charAt(--myoffset) == ' ');
- if (myoffset > 0 && document.cookie.charAt(myoffset) != ';') {
- return '';
- }
- }
- offset += search.length;
- end = document.cookie.indexOf(";", offset);
- if (end == -1) {
- end = document.cookie.length;
- }
- cookieValue = unescape(document.cookie.substring(offset, end))
- }
- }
- return cookieValue;
- };
- //当前时间
- function now() {
- return (new Date()).getTime();
- }
- //写cookie
- FzmCookie.write = function(name, value, hours, path, domain, secure) {
- var expire = "";
- if (domain == null) {
- /*
- domain = document.domain;
- if (domain.indexOf(".") == -1) {
- domain = '';
- } else {
- domain = "." + domain;
- }
- domain = domain ? "; domain=" + domain : "";
- */
- }
- path = path ? path : "/";
- if (hours != null) {
- expire = new Date(now() + hours * 3600000);
- expire = "; expires=" + expire.toGMTString();
- }
- document.cookie = name + "=" + escape(value) + expire + domain + "; path=" + path + ";";
- };
- //
- FzmCookie.del = function(name, domain, path) {
- var expire = "";
- if (domain == null) {
- domain = domainName();
- if (domain.indexOf(".") == -1) {
- domain = '';
- } else {
- domain = "." + domain;
- }
- domain = domain ? "; domain=" + domain : "";
- }
- path = path ? path : "/";
- value = "";
- hours = "-10";
- if (hours != null) {
- expire = new Date(Fzm.clientTime() + hours * 3600000);
- expire = "; expires=" + expire.toGMTString();
- }
- document.cookie = name + "=" + escape(value) + expire + domain + "; path=" + path + ";";
- };
- //更新cookie
- FzmCookie.update = function(name, value, hours, path, domain, secure) {
- var v = Guidv4.get(name); //以guid中保存的值为准
- if (!v) v = FzmCookie.read(name);
- if (v == '') {
- v = value;
- }
- Guidv4.update(name, v);
- FzmCookie.write(name, v, hours, path, domain, secure);
- return v;
- };
- //设置plot_area基本样式
- function set_style(name) {
- var conf = Config.getInstance();
- if (!name) {
- name = conf.Global.style;
- } else {
- conf.Global.style = name;
- }
- conf.merge("Global.Candle.public", "Global.Candle." + name);
- conf.merge("Global.Grid.public", "Global.Grid." + name);
- //设置plot_area的背景颜色
- $(conf.Global.canvasID).css("background", conf.Global.Grid.public.bgColor);
-
- // $(conf.Global.canvasID).css("background-image","url('static/img/Klogo.png')");
- // $(conf.Global.canvasID).css("background-repeat","no-repeat");
- }
- /*//create_canvas创建canvas层 没有用
- function create_canvas()
- {
- //
- var conf = Config.getInstance();
- var count = conf.Global.maxCanvasCount;
- for (var i = 0; i < count; i++)
- {
- var id = conf.Global.canvasIDPerfix + i;
- var tmp = $("<canvas id='"+id+"'></canvas>");
- tmp.get(0).height = 1;
- $(conf.Global.canvasID).append(tmp);
- }
- }
- */
- //显示加载
- function show_loading() {
- var conf = Config.getInstance();
- var id = conf.Global.ajaxloadingID;
-
- var view = HTML5StockChartAPI.API.controller.view;
- var plotWidth = view.plotWidth;
- var offsetHeight = $("#plot_area").offset().top;
- var offsetWidth = $("#plot_area").offset().left;
- var plotHeight = view.plotHeight;
- $(id).css("top", offsetHeight + plotHeight / 2 - $(id).width() / 2);
- $(id).css("left", offsetWidth + plotWidth / 2 - $(id).width() / 2);
- $(id).show();
- $("#background").css("top", offsetHeight + plotHeight / 2 - $(id).width() / 2-130);
- $("#background").css("left", offsetWidth+ plotWidth / 2 - $(id).width() / 2-130 );
- // $(id).show();
- }
- //隐藏加载
- function hide_loading() {
- var conf = Config.getInstance();
- var id = conf.Global.ajaxloadingID;
- $(id).hide();
- }
- //原来是放了一个矩形框在那里显示内容,现在做成六边形输入框update by fangxiao from 2016/7/1 次方法主要是为了价格标线来设置的
- function writeTextOption(ctx, point, value, option) {
- if (option) {
- if (option.bg) {
- if(option.type=="price"){
- ctx.fillStyle = option.bg.fillcolor;
- ctx.fillRect(point.x+8,point.y-11,80,20);
- ctx.fill();
- }
- else{
- //画线
- //做个六边形
- ctx.strokeStyle = option.bg.color;
- //ctx.strokeRect(point.x, point.y - option.bg.height / 2, option.bg.width , option.bg.height);
- ctx.fillStyle = option.fillcolor;
- ctx.lineWidth = 0.6; //设置线宽
- var a = option.bg.width;
- var b = option.bg.width / 2 * 0.3; //左小测
- //ctx.strokeStyle=gradient;
- //console.log(point.x);
- //console.log(point.y);
- // ctx.strokeText(value, point.x+3,point.y+2.8,option.bg.width);
- //ctx.translate(point.x+option.bg.width/2,point.y);
- ctx.moveTo(point.x, point.y);//左边第一个点
- ctx.lineTo(point.x + b, point.y + option.bg.height / 2);//左上角第一个点
- ctx.lineTo(point.x + a - b, point.y + option.bg.height / 2);
- ctx.lineTo(point.x + a, point.y);
- ctx.lineTo(point.x + a - b, point.y - option.bg.height / 2);
- ctx.lineTo(point.x + b, point.y - option.bg.height / 2);
- ctx.lineTo(point.x, point.y);
- // ctx.fillText(text, point.x, point.y);
- ctx.closePath();
- ctx.stroke();
- ctx.fill();
- // ctx.fillRect(point.x, point.y - option.bg.height / 2, option.bg.width , option.bg.height);
- // point.y += option.bg.height / 2;
- }
- }
- if (option.unit < 1) {
- value = FormatNumber(value, -Math.floor(Math.log(option.unit) / Math.LN10));
- }
- }
- point.y += 5;
- point.x += 12;
- writeText(ctx, point, value, option.color, option.font);
- }
- //为了光标设置的样式
- function writeTextOptionFortoollist(ctx, point, value, option) {
- ctx.strokeStyle = "#000";
- //ctx.strokeRect(point.x, point.y - option.bg.height / 2, option.bg.width , option.bg.height);
- //ctx.fillStyle = "#000";
- ctx.lineWidth = 1; //设置线宽
- var a = option.bg.width;
- var b = option.bg.width / 2 * 0.3; //左小测
- //ctx.strokeStyle=gradient;
- //console.log(point.x);
- //console.log(point.y);
- ctx.strokeText(value, point.x + 3, point.y + 2.8, option.bg.width);
- //ctx.translate(point.x+option.bg.width/2,point.y);
- ctx.moveTo(point.x, point.y);
- ctx.lineTo(point.x + b, point.y + option.bg.height / 2);
- ctx.lineTo(point.x + a - b, point.y + option.bg.height / 2);
- ctx.lineTo(point.x + a, point.y);
- ctx.lineTo(point.x + a - b, point.y - option.bg.height / 2);
- ctx.lineTo(point.x + b, point.y - option.bg.height / 2);
- ctx.lineTo(point.x, point.y);
- // ctx.fillText(text, point.x, point.y);
- ctx.closePath();
- ctx.stroke();
- }
- //start 大, end 小的情况 二分法找寻value值位置
- function binsearch_r(arr, value, start, end) {
- if (typeof start === "undefined") {
- start = 0;
- }
- if (typeof end === "undefined") {
- end = arr.length - 1;
- }
- var mid;
- while (start <= end) {
- mid = parseInt((start + end) / 2);
- if (arr[mid] == value) {
- return mid;
- } else if (arr[mid] > value) {
- start = mid + 1;
- } else if (arr[mid] < value) {
- end = mid - 1;
- }
- }
- return -1;
- }
- //最后大于find最大的点的位置
- function find_last_little_r(x, find) {
- index = find_first_big_r(x, find); //第一个最大值点位置
- if (index == -1) //没有找到
- {
- if (x[0] <= find) {
- return 0;
- } else {
- return -1;
- }
- } else {
- if (x[index] == find) { //找寻到
- return index;
- } else {
- index++;
- if (index >= x.length) return -1;
- return index;
- }
- }
- }
- //找到相邻的find位置
- function find_near(x, find) {
- var index = find_first_big_r(x, find);
- if (index == -1) return 0;
- if (index < x.length - 1 && (x[index] - find > find - x[index + 1])) {
- index++;
- }
- return index;
- }
- //旋转得到的新坐标
- //point是在原来坐标系内的坐标
- //cta 是新坐标系旋转的角度
- //ab 是新坐标系的远点,在原来坐标系中的坐标
- function axis_translate(point, cta, ab) {
- var newpoint = {};
- newpoint.x = (point.x - ab.x) * Math.cos(cta) + (point.y - ab.y) * Math.sin(cta);
- newpoint.y = (ab.x - point.x) * Math.sin(cta) + (point.y - ab.y) * Math.cos(cta);
- return newpoint;
- }
- //获取flash版本
- function get_flash_version() {
- var UNDEF = "undefined",
- OBJECT = "object",
- SHOCKWAVE_FLASH = "Shockwave Flash",
- SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
- FLASH_MIME_TYPE = "application/x-shockwave-flash",
- EXPRESS_INSTALL_ID = "SWFObjectExprInst";
- var playerVersion = [0, 0, 0];
- var d = null;
- if (typeof navigator.plugins != UNDEF && typeof navigator.plugins[SHOCKWAVE_FLASH] == OBJECT) {
- d = navigator.plugins[SHOCKWAVE_FLASH].description;
- if (d && !(typeof navigator.mimeTypes != UNDEF && navigator.mimeTypes[FLASH_MIME_TYPE] && !navigator.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) {
- plugin = true;
- d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
- playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
- playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
- playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
- }
- } else if (typeof window.ActiveXObject != UNDEF) {
- try {
- var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
- if (a) { // a will return null when ActiveX is disabled
- d = a.GetVariable("$version");
- if (d) {
- ie = true; // cascaded feature detection for Internet Explorer
- d = d.split(" ")[1].split(",");
- playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
- }
- }
- } catch (e) {
- return playerVersion;
- }
- }
- return playerVersion;
- }
- //是否支持websocket
- function support_websocket() {
- var version = get_flash_version();
- if (version[0] >= 9) {
- return true;
- }
- if (window.WebSocket) {
- return true;
- }
- return false;
- }
- /*未使用
- function init_websocket()
- {
- if (window.WebSocket) {
- return true;
- }
- if (get_flash_version()[0] >= 9)
- {
- include(__baseurl__ + "js/swfobject.js");
- include(__baseurl__ + "js/web_socket.js");
- return true;
- }
- return false;
- }*/
- //设置宽度
- function set_width(obj, w) {
- if (typeof obj.get == "function" && obj.get(0)) {
- obj.get(0).width = w;
- obj.width(w);
- } else {
- obj.width = w;
- }
- }
- //设置高度
- function set_height(obj, h) {
- // if(h>1){
- // if(obj.attr('id')=="plot_canvas_00"||obj.attr('id')=="plot_canvas_01"||obj.attr('id')=="plot_canvas_02"){
- // h=h-60;
- // }
- // }
-
- if (typeof obj.get == "function" && obj.get(0)) {
- obj.get(0).height = h;
- obj.height(h);
- } else {
- obj.height = h;
- }
- }
- /*未使用
- function __indicator__name__change(obj)
- {
- indicator.load(indicator.tab, $(obj).val());
- }*/
- //从search位置开始
- function start_with(search, obj) {
- return obj.indexOf(search) == 0
- }
- //HTML5StockChartAPI函数
- function HTML5StockChartAPI(id) {
- this.isinit = false;
- this.id = id;
- this.tplParams = {};
- this.container = $("#" + this.id);
- // this.container.html( __tpl__base__ + __tpl__indwin__);
- this.config = Config.getInstance();
- //console.log(DataReaderTrendLine.getYminmax());
- this.option = {
- debug: __debug__,
- jsdebug: __javascript_debug__,
- datasource: __datasource__,
- datafile: __datafile__,
- pair: __symbol__list__,
- runtime_load: __runtime_load__,
- staticChat: __static__,
- startTime: __start_time__,
- "toolbar.isenable": false,
- plot_area: $("#plot_container"),
- ind: [this.config.mainName]
- };
- if (!this.read('model')) this.write("model", "active");
- var _this = this;
- if (window["FlashCanvas"]) {
- FlashCanvas.ready = function() {
- FlashCanvas.init();
- _this.init();
- }
- } else {
- $(document).ready(function() {
- _this.init();
- });
- }
- }
- HTML5StockChartAPI.prototype.setTPLParams = function(key, val) {
- this.tplParams[key] = val;
- }
- HTML5StockChartAPI.prototype.init = function() {
- if (this.isinit) {
- return;
- }
- this.isinit = true;
-
- this.controller = new Controller(this);
- if (!is_undefined(this.option["controller.staticChat"])) {
- this.controller.staticChat = this.option["controller.staticChat"];
- }
- //为了兼容以前的版本,添加了这个全局变量
- /*this.indicator = indicator = new WinAjax("indicator.add", "指标管理", 700, 500,this);
- this.indicator.createWindow("__indicator__");
- this.order = order = new WinAjax("order.order","订单",320,240,this);
- this.order.createWindow("__order__");*/
- //////////////////////////
- if (this.c && this.p) {
- this.setPair(this.c, this.p);
- }
- }
- HTML5StockChartAPI.prototype.destroyed=function(){
- this.isinit = false;
- this.controller.deinit();
- this.controller = null;
- }
- HTML5StockChartAPI.prototype.setStaticChart = function(isstatic) {
- //alert(typeof isstatic === "undefined");
- var p = (typeof isstatic === "undefined") ? true : isstatic;
- if (this.isinit) {
- this.controller.staticChat = p;
- } else {
- this.set("controller.staticChat", p);
- }
- }
- HTML5StockChartAPI.prototype.setSymbolList = function(pair) {
- return this.set("pair", pair);
- }
- HTML5StockChartAPI.prototype.setIndicatorConf = function(indicator) {
- if (typeof indicator !== "string") {
- indicator = indicator.join(":");
- }
- indicator = indicator.toLowerCase();
- this.write("ind", indicator);
- this.set("ind", indicator);
- // this.isinit=false;
- if (this.isinit) {
- window.location.reload();
- // this.isinit = false;
- // this.controller.deinit();
- // this.controller = null;
- // this.isinit = false;
- // this.init();
- }
- }
- HTML5StockChartAPI.prototype.initSignal = function() {
- var signal_id = this.read("signal");
- //固定一个策略
- if (signal_id < 4) {
- signal_id = 5;
- }
- if (signal_id) {
- this.config.Global.signal = signal_id;
- } else {
- signal_id = this.config.Global.signal;
- }
- return signal_id;
- }
- HTML5StockChartAPI.prototype.setModel = function(model) {
- this.write("model", model);
- this.config.Global.app_model = model;
- if (this.isinit) {
- window.location.href = "";
- }
- }
- HTML5StockChartAPI.prototype.setSignal = function(signal_id) {
- this.write("signal", signal_id);
- this.config.Global.signal = signal_id;
- if (this.isinit) {
- window.location.href = "";
- }
- }
- HTML5StockChartAPI.prototype.set = function(name, value) {
- this.option[name] = value;
- return this;
- }
- HTML5StockChartAPI.prototype.setPair = function(c, p) {
- this.c = c;
- this.p = p;
- if (!this.isinit) {
- return;
- }
- this.write("symbol", c);
- $.cookie("symbol",c);
- $.cookie("period",p)
- // sessionStorage.setItem('period',p);
- this.write("period", p);
-
- this.controller.set(this.c, this.p);
- if (typeof this.option["paircb"] === "function") {
- this.option["paircb"](this.c, this.p);
- }
- // console.log(DataReaderbdensity.prototype.getYminmax());
- }
- HTML5StockChartAPI.prototype.toolbarEnable = function() {
- this.set("toolbar.isenable", true);
- if (!this.isinit) {
- return;
- }
- this.controller.toolbar.enable();
- }
- HTML5StockChartAPI.prototype.toolbarDisable = function() {
- this.set("toolbar.isenable", false);
- $("#toolbar").hide();
- if (!this.isinit) {
- return;
- }
- this.controller.toolbar.disable();
- }
- HTML5StockChartAPI.prototype.read = function(name) {
- return FzmCookie.read(name);
- }
- HTML5StockChartAPI.prototype.write = function(name, data) {
- if (typeof data === "string") {
- return FzmCookie.write(name, data, 10000);
- }
- console.error("cookie write error");
- return false;
- }
- HTML5StockChartAPI.prototype.initInd = function(def) {
- var name = this.read("ind");
- if (!name) {
- name = def;
- }
- this.setInd(name);
- }
- HTML5StockChartAPI.prototype.setConfig = function(key, val) {
- return this.config.set(key, val);
- }
- HTML5StockChartAPI.prototype.setInd = function(name) {
- if (name == "tick_price" || name.indexOf("tick_source") === 0) {
- this.p = "TICK";
- } else {
- if (this.p == "TICK") {
- this.p = "H1";
- $.cookie('period','H1');
- // sessionStorage.setItem('period','H1');
- }
- }
- this.setIndicatorConf(name);
- }
- HTML5StockChartAPI.prototype.clearCookie = function() {
- this.write("period", "");
- $.cookie('period','H1');
- this.write("ind", "");
- }
- HTML5StockChartAPI.prototype.initPair = function(c, p, ignore) {
- var symbol = this.read("symbol");
- symbol = symbol ? symbol : c;
- var period = this.read("period");
- period = period ? period : p;
- if (period == ignore) {
- period = "H1";
- $.cookie('period','H1');
- }
- this.setPair(symbol, period);
- }
- //坐标轴的设计按照通用配置的形式来设计。
- //
- //输入:
- //
- //1. POINT(SCALE): 描点形式:需要,model读出的数据.
- //2. EXTEND(NOMAL): 扩展的方式,需要指定扩展对应的数据。
- //3. MIAN: 需要提供主图的数据
- //4. SCALE: 按照比例进行,这个需要提供的是最大值,最小值
- //
- //坐标值的密集阵值:一般指定多小像素内一个坐标,然后根据高度计算大概需要多少个坐标。
- //但是这个值不是精确的,而是有弹性的,为了计算一个最佳的坐标值。
- //
- //设计流程:
- //
- //首先是:[point 还是 scale]
- //
- //如果是scale 给出最大值,最小值 就可以进行计算了。调用 Axis_Scale
- //
- //如果是point: 那么闲判断主图有没有计算,如果没有计算,那么先计算主图。
- //
- //计算主图的过程是这样的:闲判断是否需要 扩展,如果需要扩展,那么
- //按照主图数据,进行扩展。这个时候,要知道主图是 p是多少。这样就可以扩展了。
- //
- //Axis_ExtendByMain
- //Axis_ExtendByTime
- //
- //主图扩展完成后(注意,这里要把Y的数据进行扩展,所以,要计算X的坐标,再计算Y的坐标),
- //那就计算扩展后主图的坐标。扩展完成后调用 Axis_Point, 进行描点处理。
- //
- //对于副图。
- //如果配置不是按照主图进行绘制的,那么直接报错。暂时不支持这样的情况。
- //
- //如果是按照主图进行扩展,那么
- //调用 Axis_ExtendByMain 扩展。
- //
- //最后调用 Axis_PointBYMain 获取坐标数据。
- //
- //
- //main 是主图坐标,因为附图可能和主图相关,所以要加这个值。
- //对于主图的坐标系,这个main值是null
- function Axis(main) {
- this.main = main;
- this.config = Config.getInstance();
- }
- Axis.POINT = 1;
- Axis.MAIN = 1 << 1;
- Axis.TIME = 1 << 2;
- Axis.BIG2SMALL = 1 << 3;
- Axis.BIG2BIG = 1 << 4;
- Axis.SCALE = 1 << 5;
- Axis.CUSTOM = 1 << 6;
- Axis.CUSTOM_DATA = 1 << 7;
- Axis.prototype.setViewConfig = function(viewconfig) {
- if (viewconfig) this.viewconfig = viewconfig;
- }
- Axis.prototype.setData = function(data) {
- if (data) {
- this.data = data;
- this.c = data.c;
- this.p = data.p;
- $.cookie('period',data.p);
- }
- }
- Axis.prototype.clearData = function() {
- this.data = null;
- this.viewconfig = null;
- }
- Axis.prototype.getData = function() {
- this.calc();
- var ret = { data: this.data, axis: this.viewconfig };
- return ret;
- }
- Axis.prototype.calc = function() {
- //viewconfig 按canvas的ID进行组织,主图默认在序号为 0 的配置里面
- //按照数据,现在刚刚传入的数据,每个图还是有关系的.我们要分离这样的关系。
- //
- //1. 读取每个 指标 计算坐标的标准配置
- //2. 获取最大最小指。
- //
- //计算主图
- var maxY = -Infinity;
- var maxX = -Infinity;
- var minX = Infinity;
- var minY = Infinity;
- for (var j = 0; j < this.viewconfig.plot.length; j++) {
- var name = this.viewconfig.plot[j];
- //判断是否参与计算
- var vc = this.config.Global.View[name];
- if (name != this.config.mainName && typeof vc["disable_axis_area"] !== 'undefined' && vc["disable_axis_area"]) {
- continue;
- }
- if (this.data[name].maxX > maxX) maxX = this.data[name].maxX;
- if (this.data[name].minX < minX) minX = this.data[name].minX;
- if (this.data[name].maxY > maxY) maxY = this.data[name].maxY;
- if (this.data[name].minY < minY) minY = this.data[name].minY;
- }
- this.viewconfig.x.max = maxX;
- this.viewconfig.x.min = minX;
- this.viewconfig.y.max = maxY;
- this.viewconfig.y.min = minY;
- if (this.main == null) {
- this.calcMain();
- this.main = this;
- }
- for (j = 0; j < this.viewconfig.plot.length; j++) {
- name = this.viewconfig.plot[j];
- if (name == this.config.mainName) continue;
- this.calcOne(name);
- }
- }
- Axis.prototype.calcOne = function(name) {
- this.getAxis(name, "x");
- this.getAxis(name, "y");
- }
- Axis.prototype.calcMain = function() {
- //下面的数据时扩展过的数据,这样。
- this.getAxisMainX();
- this.getAxis(this.config.mainName, "y");
- }
- Axis.prototype.getAxis = function(name, tag) {
- //tag 标记是 x 轴还是 y轴,取数据的时候用的到。
- var data = this.data[name][tag];
- if (!data || data.length == 0) return;
- var plot = this.viewconfig[tag]; //在tag下面的配置
- var axisconfig = this.config.Global.Axis[name][tag];
- var unit = this.data[name][tag + "unit"];
- if (axisconfig & Axis.POINT) {
- if (plot.axis) debug("plot axis has set.");
- var data = this.pointAxisValue(data, plot.beg, plot.end, this.viewconfig.one, plot.n, axisconfig);
- plot.axis = data.axis;
- plot.axis_option = {};
- plot.axis_option.style = axisconfig;
- plot.axis_option.unit = unit;
- this.viewconfig[tag] = plot;
- this.data[name][tag] = data.data;
- //描点,计算坐标轴的值
- } else if (axisconfig & Axis.MAIN) {
- //通过主图计算
- this.pointByMain(name); //这个不需要什么配置了
- //不需要生成什么坐标的信息,坐标在主图中生成。
- } else if (axisconfig & Axis.SCALE) {
- //通过比例进行计算,每个都要生成坐标的信息。
- if (!plot.axis) {
- //计算坐标轴的值[比例计算的坐标轴]
- var scalevalue = this.getScaleValue(plot.min, plot.max, unit, plot.n, axisconfig);
- var data = this.scaleAxisValue(data, scalevalue, plot.beg, plot.end, axisconfig);
- plot.axis = data.axis;
- plot.axis_option = {};
- plot.axis_option.style = axisconfig;
- plot.axis_option.unit = unit;
- this.viewconfig[tag] = plot;
- this.data[name][tag] = data.data;
- } else {
- if (axisconfig & Axis.CUSTOM) {
- this.data[name][tag] = this.customTranslate(name, data, plot.axis);
- } else {
- this.data[name][tag] = this.lineTranslate(data, plot.axis);
- }
- }
- }
- if (axisconfig & Axis.CUSTOM_DATA) {
- if (this.viewconfig.x.axis && this.viewconfig.y.axis) {
- for (var type in this.data[name].data) {
- this.data[name].data[type].x = this.lineTranslate(this.data[name].data[type].x, this.viewconfig.x.axis);
- this.data[name].data[type].y = this.lineTranslate(this.data[name].data[type].y, this.viewconfig.y.axis);
- }
- }
- }
- }
- Axis.prototype.customTranslate = function(name, data, axis) {
- var param = this.lineGetAxisParam(axis);
- if (!param) {
- return data;
- }
- var a = param[0];
- var b = param[1];
- if (name == "profit" || start_with("profit|", name)) {
- for (var i = 0; i < data.length; i++) {
- for (var j = 0; j < data[i].length; j++) {
- data[i][j][1] = a * data[i][j][1] + b;
- }
- }
- return data;
- } else if (name == "kshapetest" || start_with("kshapetest|", name)) {
- for (var i = 0; i < data.length; i++) {
- data[i][0] = a * data[i][0] + b;
- }
- return data;
- } else if (name == "fractals" || start_with("fractals|", name) || name == "advfractals" || start_with("advfractals|", name)) {
- for (var i = 0; i < data.length; i++) {
- data[i][1] = a * data[i][1] + b;
- }
- return data;
- } else if (name == "bolling_desity") {
- for (var i = 0; i < data.length; i++) {
- for (var j = 0; j < data[i].length; j += 2) {
- if (data[i][j] == -1) {
- continue;
- }
- data[i][j] = a * data[i][j] + b;
- }
- }
- return data;
- }
- if (name == "wdesity") {
- for (var i = 0; i < data.length; i++) {
- for (var j = 0; j < data[i].length; j++) {
- if (data[i][j] == 0) {
- data[i][j] = 0;
- continue;
- }
- data[i][j] = a * data[i][j] + b;
- }
- }
- return data;
- } else if (name == "trend_line") {
- //计算曲线的斜率
- var axis = this.viewconfig.y.axis;
- dy = -(axis[0].key - axis[1].key) / (axis[0].value - axis[1].value);
- dx = this.viewconfig.one;
- var group = {};
- for (i = 0; i < data.length; i++) {
- var g = data[i][4];
- if (g > 0) {
- if (typeof group[g] === "undefined") {
- group[g] = 0;
- } else {
- group[g] += 0;
- }
- } else {
- group[g] = 0;
- }
- //斜率
- data[i][1] = dy * (data[i][1] - data[i][0]) / dx
- //位置
- data[i][0] = a * data[i][0] + b + group[g];
- data[i][7] = a * data[i][7] + b + group[g];
- data[i][6] = this.main.axisMap[data[i][6]];
- }
- return data;
- }
- }
- //beg 是坐标的开始值,这里的data必须是一维数组。
- Axis.prototype.pointAxisValue = function(data, beg, end, one, n, axisconfig) {
- var index = 0;
- var j = 0;
- var data_axis = [];
- var axis = [];
- var total_pixel = beg - end;
- var plot_number = Math.ceil(total_pixel / one);
- if (n > plot_number) {
- var mod = 1;
- } else {
- var mod = Math.round(plot_number / n);
- }
- //这里还有的一个问题是:大坐标表示小数据,还是大坐标,表示大数据,默认是大坐标表示大数据
- if (axisconfig & Axis.BIG2SMALL) { //小的排在前面
- if (data.length > 1 && data[data.length - 1] < data[0]) data = data.reverse();
- }
- for (var i = 0; i < data.length; i++) {
- data_axis[i] = beg;
- if (i % mod == 0) {
- axis[j] = { key: beg, value: data[i] };
- j++;
- }
- beg -= one;
- }
- var ret = { data: data_axis, axis: axis };
- return ret;
- }
- Axis.prototype.scaleAxisValue = function(data, scalevalue, beg, end, axisconfig) {
- var data_axis = [];
- var axis = [];
- if (!scalevalue) {
- debug("error scalevalue.");
- return { data: [], axis: [] };
- }
- var n = scalevalue.length;
- //坐标大小问题,1. 大的坐标表示小的数字,2. 小的坐标表示大的数字
- if (axisconfig & Axis.BIG2SMALL) { //小的排在前面
- if (n > 1 && scalevalue[n - 1] < scalevalue[0]) {
- scalevalue = scalevalue.reverse();
- }
- } else { //Axis.BIG2BIG
- if (n > 1 && scalevalue[n - 1] > scalevalue[0]) {
- scalevalue = scalevalue.reverse();
- }
- }
- var one = Math.floor((beg - end) / (n - 1));
- var index = 0;
- while (beg >= end && index < n) {
- axis.push({ key: beg, value: scalevalue[index++] });
- beg -= one;
- }
- //下面开始转换数据,这里的data可以是一维,也可以是二维
- data = this.lineTranslate(data, axis);
- var ret = { data: data, axis: axis };
- return ret;
- }
- Axis.prototype.getXValue = function(x, mode, axis) {
- /*if (!axis) axis = this;
- var _axis = axis.viewconfig.x.axis; //从小到大排列
-
- */
- //查找x的值
- var current = null;
- var offset = null;
- var min = Infinity;
- for (var time in this.main.axisMap) {
- var pos = this.main.axisMap[time];
- if (typeof pos == "number") {
- offset = Math.abs(pos - x);
- if (offset < min) {
- min = offset;
- current = time;
- }
- }
- }
- return parseInt(current);
- //return this.getValue(x, _axis, mode);
- }
- Axis.prototype.getValue = function(key, axis, mode) {
- if (typeof axis === "undefined") return false;
- var index = this.findNear(axis, key);
- if (mode == PlotGrid.NEAR) {
- return axis[index].value;
- } else if (mode == PlotGrid.INTERPOLATION) {
- return this.getInterpolation(key, index, axis);
- }
- return false;
- }
- Axis.prototype.getInterpolation = function(find, index, axis) {
- //寻找两个差值点:
- var newaxis = [];
- var start, end;
- if (axis.length <= 1) {
- return axis[index].value;
- }
- if (index == 0) {
- start = 0;
- end = 1;
- } else if (index == axis.length - 1) {
- start = axis.length - 2;
- end = axis.length - 1;
- } else {
- if (axis[index].key > find) {
- start = index;
- end = index + 1;
- } else {
- start = index - 1;
- end = index;
- }
- }
- newaxis.push({ key: axis[start].value, value: axis[start].key });
- newaxis.push({ key: axis[end].value, value: axis[end].key });
- return this.lineTranslate(find, newaxis, true);
- }
- Axis.prototype.findNear = function(axis, find) {
- for (var i = 0; i < axis.length; i++) {
- if (axis[i].key < find) { // find 在 i 和 i - 1 之间
- if (i == 0) return 0;
- if (find - axis[i].key < axis[i - 1].key - find) {
- return i;
- } else {
- return i - 1;
- }
- }
- }
- return axis.length - 1;
- }
- Axis.prototype.getYValue = function(y, mode, axis) {
- if (!axis) axis = this;
- var _axis = axis.viewconfig.y.axis; //从小到大排列
- return this.getValue(y, _axis, mode);
- }
- Axis.prototype.getX = function(data) {
- return this.lineTranslate(data, this.viewconfig.x.axis);
- }
- Axis.prototype.getY = function(data) {
- return this.lineTranslate(data, this.viewconfig.y.axis);
- }
- Axis.prototype.lineTranslate = function(data, axis, noround) {
- if (axis.length == 0) return data;
- if (axis.length == 1) {
- var a = 0;
- var b = axis[0].key;
- } else {
- var a = (axis[0].key - axis[axis.length - 1].key) / (axis[0].value - axis[axis.length - 1].value);
- var b = axis[0].key - a * axis[0].value;
- }
- var is1d = is_array(data);
- var is2d = is_array(data[0]);
- if (is1d) {
- for (var i = 0; i < data.length; i++) {
- if (is2d) {
- for (var j = 0; j < data[i].length; j++) {
- data[i][j] = Math.round(a * data[i][j] + b);
- }
- } else {
- data[i] = Math.round(a * data[i] + b);
- }
- }
- } else {
- if (noround) {
- data = a * data + b;
- } else {
- data = Math.round(a * data + b);
- }
- }
- return data;
- }
- Axis.prototype.lineGetAxisParam = function(axis) {
- if (axis.length == 0) return false;
- if (axis.length == 1) {
- var a = 0;
- var b = axis[0].key;
- } else {
- var a = (axis[0].key - axis[axis.length - 1].key) / (axis[0].value - axis[axis.length - 1].value);
- var b = axis[0].key - a * axis[0].value;
- }
- return [a, b];
- }
- Axis.prototype.getScaleValue = function(start, end, unit, n, axis_style) {
- //浮动:这个n是建议的数目
- var number = Math.ceil((end - start) / unit) / n;
- if (number <= 0) {
- if (start == end) {
- var vals = [start];
- return this.standarAxisValue(vals, start, end, axis_style);
- }
- return null;
- }
- var closest;
- if (number <= 1) {
- closest = unit;
- } else {
- var low = Math.pow(10, Math.floor(Math.log(number) / Math.LN10));
- var high = low * 10;
- var i = 0;
- if (low >= 10) {
- if (axis_style & Axis.TIME) {
- var lookup = [1, 1.5, 2, 3.0, 4.5, 6.0, 10];
- } else {
- var lookup = [1, 1.5, 2, 2.5, 4, 5, 8, 10];
- }
- for (i = 0; i < lookup.length; i++) {
- lookup[i] *= low;
- }
- } else {
- if (axis_style & Axis.TIME) {
- var lookup = [1, 2, 3, 4, 6, 10];
- } else {
- var lookup = [1, 2, 4, 5, 8, 10];
- }
- }
- var min_value = Number.MAX_VALUE;
- var min_index = 0;
- for (i = 0; i < lookup.length; i++) {
- var tmp = Math.abs(lookup[i] - number);
- if (min_value > tmp) {
- min_value = tmp;
- min_index = i;
- }
- }
- var closest = unit * lookup[min_index];
- }
- var minindex = Math.floor(start / closest);
- var maxindex = Math.ceil(end / closest);
- vals = [];
- for (var j = minindex; j <= maxindex; j++) {
- vals.push(j * closest);
- }
- return this.standarAxisValue(vals, start, end, axis_style);
- }
- Axis.prototype.standarAxisValue = function(axis, beg, end, axis_style) {
- var abeg = axis[0];
- var aend = axis[axis.length - 1];
- var delta = 0;
- if (axis_style & Axis.FIX_BEG) {
- delta = abeg - beg;
- } else if (axis_style & Axis.FIX_END) {
- delta = aend - end;
- }
- for (var i = 0; i < axis.length; i++) {
- axis[i] -= delta;
- }
- //下面开始计算坐标的值
- return axis;
- }
- Axis.prototype.getAxisMainX = function() {
- //计算之前复制一份:
- var x = this.data[this.config.mainName].x;
- this.getAxis(this.config.mainName, "x");
- //这个是X轴坐标的映射,其他的坐标要靠这个来计算。
- this.axisMap = {};
- for (var i = 0; i < x.length; i++) {
- this.axisMap[x[i]] = this.data[this.config.mainName].x[i];
- }
- //这样时间和坐标成了一一对应
- }
- Axis.prototype.pointByMain = function(name) {
- //这里主要去除一些毛刺数据,所以统一又处理了一次。
- //这个部分,以后如果要调节性能,还要进行修改。
- var x = [];
- var y = [];
- var index = 0;
- var data = this.data[name];
- for (var i = 0; i < data.x.length; i++) {
- var item = this.main.axisMap[data.x[i]];
- if (item) {
- //查找到坐标,那么就采用这个坐标
- x[index] = item;
- y[index] = data.y[i];
- index++;
- } else {
- if (typeof item === "undefined") {
- continue;
- } else {
- x[index] = item;
- y[index] = data.y[i];
- index++;
- }
- }
- }
- this.data[name].x = x;
- this.data[name].y = y;
- }
- //配置画图的属性
- //1. 类映射
- //绘制图形的时候,是根据绘图的名称,来绘制的。
- //main 是主图,这个是固定的名字。
- //其他的是指标图,用各自的名字。每个画图对象通过两个方面来控制。
- //1. 是数据读取部分,我们把缓存在内存的数据看成是一个数据库,这个读取
- //虽然是千篇一律,但是还是有规律可循。
- //
- //2. 是数据的显示控制,我们会根据plotset的情况,最后转换成坐标的值。通过
- //这个坐标的值,来绘制不同的图形。
- //
- //3. 还有一个对象控制数据保存的过程。比如,数据下载怎么处理,
- // 下载后怎么保存,新数据怎么处理,新数据怎么保存等问题。
- // 处理读写数据的模块应该是要和 数据更新模块分离的。
- //
- //update by fangxiao from 2016/6/29 17:17
- function Config() {
- //浏览器测试
- this.getBrowserInfo();
- this.name = "Config";
- this.mainName = "main";
- this.main = { reader: DataReaderCandle, writer: DataWriterCandle, plot: PlotCandle, data: DataReader.EXTEND, downdata: 1, newdata: 1 };
- //扩展数据。必须有扩展的接口。否则会直接忽略这个选项。
- //通过主图读取数据,主图会传入一个时间范围,然后通过函数读取数据,通过主图扩展数据
- this.volumes = { reader: DataReadervolumes, writer: DataWriter, plot: Plotvolumes };
- this.volumes2 = { reader: DataReadervolumes2, writer: DataWriter, plot: Plotvolumes2 };
- // console.log(""+DataReadervolumes.getYminmax);
- this.ma = { reader: DataReaderIndicatorsMa, writer: null, plot: PlotLine };
- this.macd = { reader: DataReaderIndicatorsMacd, writer: null, plot: PlotMacd };
- this.bolling = { reader: DataReaderIndicatorsBolling, writer: null, plot: PlotBolling };
- this.kdj = { reader: DataReaderIndicatorsKDJ, writer: null, plot: PlotBolling };
- //this.order = {reader:DataReaderIndicatorsOrder,write:null,plot:PlotOrder};
- this.Global = {};
- //这个DataWriter 的基类处理通用的读写。
- this.Global.downloadCount = 600;
- this.Global.maxStoreChunk = 20; // store max = 5 * this.Global.downloadCount
- this.Global.lowMark = 300;
- this.Global.Interval = 20;
- this.Global.newDisable = false;
- this.Global.boxwidth = 1;
- this.Global.trend_line_selected = [];
- this.Global.xunit = {
- // YMD:1440,
- //S5:1/12,
- M1: 1,
- M2: 2,
- M3: 3,
- M3: 4,
- M5: 5,
- M15: 15,
- M30: 30,
- H1: 60,
- H2: 120,
- H4: 240,
- D1: 1440,
- W1: 10080,
- MN1: 4320
- };
- this.Global.styleName = { "hx": "中国经典", "mt": "MT4" };
- //时间选择坐标的时间格式
- this.Global.timeformat = {
- YMD: "Y-m-d",
- TICK: "i:s.u",
- //S5:"m-d H:i:s",
- M1: "m-d H:i",
- M2: "m-d H:i",
- M3: "m-d H:i",
- M5: "m-d H:i",
- M15: "m-d H:i",
- M30: "m-d H:i",
- H1: "m-d H:i",
- H2: "m-d H:i",
- H4: "m-d H:i",
- D1: "m-d",
- W1: "m-d",
- MN1: "m-d"
- };
- this.Global.ajaxloadingID = "#loading";
- this.Global.yunit = {};
- this.Global.yunit.default_value = 0.00001;
- this.Global.maxstep = 1 * 3600; //最大没有数据的时间
- this.Global.maxCanvasCount = 8;
- this.Global.forcePoll = true;
- if (!this.Global.forcePoll && support_websocket()) {
- this.Global.modelName = ModelShortWS;
- this.Global.WSHost = __broadcast_server_active__;
- this.Global.WSPort = "2003";
- this.Global.pingTime = 5; //如果5s没有数据,就ping一下
- this.Global.maxNOData = 10; //如果10s内都没有数据, 那么就close掉。//最好是ping time 的整数倍。也就是 10s 以上
- } else {
- this.Global.modelName = ModelShortPoll;
- }
- if (FzmCookie.read('model') == 'passive_mode') {
- this.Global.modelName = ModelNode;
- }
- this.Global.viewName = View;
- this.Global.canvasID = "#plot_area";
- this.Global.canvasIDPerfix = "plot_canvas_";
- this.Global.PollInterval = 3000; //30ms 判断一次
- this.Global.maxConnectAliveTime = 12; //轮询的链接最多存活的时间
- this.Global.DataAPIDB ="https://kdata.fxee.com/kdata?datafile=" + __datafile__;
- if (__dbreset__) {
- this.Global.DataAPIDB += "&dbreset=" + __dbreset__
- }
- this.Global.DataAPIUpload = "static.php?datafile=" + __datafile__;
- if (__dbreset__) {
- this.Global.DataAPIUpload += "&dbreset=" + __dbreset__
- }
- if (__datasource__ == "db") {
- this.Global.DataAPI = this.Global.DataAPIDB; //一定要加上这个callbac=?否则json无法调用
- } else if (__datasource__ == "upload") {
- this.Global.DataAPI = this.Global.DataAPIUpload; //一定要加上这个callbac=?否则json无法调用
- }
- if (__refererhost__ != __apihost__) {
- this.Global.PollMode = "jsonp";
- } else {
- this.Global.PollMode = "json";
- }
- if (this.Global.PollMode == "jsonp") {
- /* $.ajaxSetup({
- //'jsonp' : false,
- 'jsonpCallback': "_jsonp_"
- });
- */
- }
- //view 模块相关的配置
- this.Global.View = {
- main: { NXPixel: 100, NYPixel: 50, sep: 0 },
- sin: { NXPixel: 100, NYPixel: 50, sep: 0 },
- cos: { NXPixel: 100, NYPixel: 50, sep: 0 },
- tick_source: { NXPixel: 100, NYPixel: 50, sep: 0 },
- profit_line: { NXPixel: 100, NYPixel: 50, sep: 0 },
- volumes: { sep: 1, height: 0.2 },
- volumes2: { sep: 1, height: 0.2 },
- ma: { sep: 0, height: 0.5 },
- //order:{sep:0,height:0.5},
- macd: { sep: 1, height: 0.2 },
- bolling: { sep: 0, height: 0.5 },
- kdj: { sep: 1, height: 0.2 },
- };
- this.Global.TPL = {
- signal: 'main:profit',
- mac2: 'main:volumes:volumes2:ma|main|10|color=red:ma|main|20|color=green:ma|main|50|color=yellow:ma|main|100|color=white:macd|main|12,26,9|color=white-lime:kdj|main|9|color=Red-blue-green:',
- mac: "main:volumes",
- bty: "main:volumes",
- eth: "main:volumes",
- ma: 'ma|main|10|color=red:ma|main|20|color=green:ma|main|50|color=yellow:ma|main|100|color=white:',
- volumes:'volumes:',
- macd: 'macd|main|12,26,9|color=white-lime:',
- bolling: 'bolling|main|20,2|color=green-green-green:',
- kdj: 'kdj|main|9|color=Red-blue-green:',
- ssi: "main:easyforex:fxtrade:" +
- "ma|main|10|color=red:" +
- "ma|easyforex|10|color=red:" +
- "ma|fxtrade|10|color=red:" +
- "ma|main|50|color=yellow:" +
- "ma|easyforex|50|color=yellow:" +
- "ma|fxtrade|50|color=yellow:" +
- "ma|main|100:" +
- "ma|easyforex|100:" +
- "ma|fxtrade|100:" +
- "matrend|main|10,20,30,50|color=red:" +
- "<matrend|main|50,80,120,180|color=yellow:" +
- "matrend|easyforex|10,20,30,50|color=red:" +
- "<matrend|easyforex|50,80,120,180|color=yellow:" +
- "matrend|fxtrade|10,20,30,50|color=red:" +
- "<matrend|fxtrade|50,80,120,180|color=yellow:" +
- "rsi|easyforex,main|14:" +
- "rsi|fxtrade,main|14",
- bolling_desity: "main:bolling_desity:profit",
- sin_cos: "sin||-10,10,1000|color=red:cos||-10,10,1000|color=green",
- profit: "profit_line||{ajax_path}|color=red",
- tick_price: "tick_source||bid-ask/20/1,fxdd,exness,fxcm|fxdd_color=green,fxpro_color=red,exness_color=blue,fxcm_color=yellow,fxdd_flag=true"
- };
- this.Global.arrow = {};
- this.Global.arrow[DataWriterProfit.BUY_OPEN] = {
- height: 15,
- width: 1,
- boder: "white",
- fill: "red",
- cta: (5 * Math.PI / 4),
- incta: (5 * Math.PI / 4)
- };
- this.Global.arrow[DataWriterProfit.BUY_CLOSE] = {
- height: 15,
- width: 1,
- boder: "pink",
- fill: "pink",
- cta: (Math.PI / 4),
- incta: (Math.PI / 4)
- };
- this.Global.arrow[DataWriterProfit.SELL_OPEN] = {
- height: 15,
- width: 1,
- boder: "aqua",
- fill: "aqua",
- cta: Math.PI * 7 / 4,
- incta: Math.PI * 3 / 4
- };
- this.Global.arrow[DataWriterProfit.SELL_CLOSE] = {
- height: 15,
- width: 1,
- boder: "yellow",
- fill: "yellow",
- cta: Math.PI * 3 / 4,
- incta: Math.PI * 7 / 4
- };
- this.Global.autoScroll = false;
- this.Global.signal = 3; //default signal id
- this.Global.WinTplID = "#__wintplid__";
- //this.Global.WinOrderTplID= "#__winordertplid__";
- this.Global.WinAPI = "http://" + __apihost__ + "/window.php";
- //this.Global.WinOrder = "http://" + __orderhost__+"/order";
- //alert(__apihost__);
- this.Global.Win = {};
- this.Global.Win.__indicator__ = {
- tab: {
- add: "添加指标",
- manage: "管理指标"
- }
- };
- /*this.Global.Win.__order__ ={
- tab:{
- order:"下单"
- }
- };*/
- this.Global.style = "hx";
- this.Global.Model = {};
- this.Global.timezone = 8;
- this.Global.overPadding = 3;
- this.Global.hoverTime = 400;
- //坐标轴相关的配置
- //对于坐标轴,有下面的配置模式:
- //1. 按照比例显示绘制数据。比如Y轴上的数据,为了对比,一般采用这样的方式。
- //2.
- //按照点进行排列。从我们外汇的图表来说,还可以把数据扩充成线性连续的模式。
- //K线图往往会缺乏数据。但是,有些时候,为了对比,或者绘制图形方便,扩充成连续的模式是非常的有必要的。
- //但是,扩充的时候要非常的注意非交易日的判断。一般来说,非交易日的没有数据的时间一般大于12个小时,而这
- //在交易日的情况下,基本不可能出现,所以,补充数据可以简单的判断没有数据的时间是否超过12个小时。
- //
- //3.
- //主图可以按照连续的方式扩充。附图的扩充方式增加了一种新的方式,那就是按照主图进行扩充。
- //
- //这些主要在搜索坐标数据的时候非常有用。
- //
- //
- this.Global.Axis = {
- main: { x: Axis.POINT | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL }, //扩展,也可以是 AXIS_NOMAL ,
- sin: { x: Axis.SCALE, y: Axis.SCALE | Axis.BIG2SMALL },
- cos: { x: Axis.SCALE, y: Axis.SCALE | Axis.BIG2SMALL },
- tick_source: { x: Axis.SCALE | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL | Axis.CUSTOM_DATA },
- profit_line: { x: Axis.POINT | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
- ma: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
- macd: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
- bolling: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
- kdj: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
- volumes: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
- volumes2: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
- //并采用描点法。也就是不按照比例进行计算坐标
- easyforex: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL }, //扩展,以主图的形式。着就是说,
- //主图没有的点,这个也进行扩展。
- //order:{x:Axis.MAIN | Axis.TIME, y:Axis.SCALE | Axis.BIG2SMALL| Axis.CUSTOM},
- profit: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL | Axis.CUSTOM }
- };
- //default grid config
- this.Global.Grid = {
- //全局私有配置,这部分配置是每个对象私有的。暂时,我们只支持全局公共配置。
- private: {
- },
- //全局公共配置
- public: {
- marginTop: [60, 80, 15, 1],
- margin: [20, 65, 15, 1],
- paddingX: 30, //绘制坐标的时候,要用到padding的值。
- paddingY: 0,
- NX: 10, //推荐的数目,但是按照现行算法可能会产生 50%左右的浮动(8-15)都有可能
- NY: 10, //推荐的数目,但是按照现行算法可能会产生 50%左右的浮动
- ledgeLen: 5,
- crossXMode: PlotGrid.NEAR, //采用寻找最近的点的模式
- crossYMode: PlotGrid.INTERPOLATION, //采用差值法
- bgColor: "white",
- axisColor: "rgb(225, 225, 225)",
- gridColor: "rgb(128, 0, 0)",
- fontColor: "rgba(225,225,225,0.4)",
- font: '',
- crossX: //光标画x轴线的颜色设置
- {
- bg: {
- color: "#999",
- width: 100,
- height: 14
- },
- font: "12px Arial",
- color: "#999",
- lineColor: "#999",
- fillcolor:"#0a0a0a"
- },
- crossY: {
- bg: //光标画Y轴线的颜色设置
- {
- color: "#999",
- width: 80,
- height: 20
- },
- font: "12px Arial",
- color: "#999",
- lineColor: "#999",
- fillcolor:"rgb(10,10,10)"
- },
- headText: {
- font: "",
- color: "rgb(200,0,0)"
- }
- },
- hx: {
- bgColor : "#0a0a0a",
- // background:url('../../../assets/img/Klogo.png') no-repeat,
- // background-size: 100%,
- axisColor : "#555",
- gridColor : "#555",//水平刻度移动端
- fontColor : "#555",
- xstyle_axis : 0,
- xstyle_grid : PlotGrid.NO_GRID,
- ystyle_axis : 0,
- ystyle_grid : PlotGrid.NO_GRID,
- xname : 10,
- yname : 10,
- // fontColor : "rgb(110,110,110)",
- font: "12px Arial"
- },
- mt: {
- bgColor: "black",
- axisColor: "rgb(225, 225, 225)",
- gridColor: "LightSlateGray",
- fontColor: "rgba(225,225,225,0.4)", //字体颜色
- xstyle_axis: 0,
- xstyle_grid: PlotGrid.NO_GRID,
- ystyle_axis: 0,
- ystyle_grid: 0,
- xname: 10,
- yname: 10,
- fontColor: "rgba(225,225,225,0.4)",
- font: "1.2em Arial"
- }
- };
- this.Global.volumes = {//volumn颜色修改
- public: {
- //lineColor:["red","green"]
- lineColor:["rgb(176,0,0)","rgb(24,179,75)"]//红涨绿卖
- }
- };
- this.Global.volumes2 = {
- public: {
- lineColor: ["rgb(176,0,0)", "rgb(220,43,43)"]
- }
- };
- this.Global.Line = {
- public: {
- lineColor: "pink"
- }
- };
- /*this.Global.Order = {
- public:{
- fontcolor:["red","aqua" ],
- linecolor:["red","aqua"],
- font:"1px Georgia",
- width : 1,
- size:20,
- tradersize:60,
- midsize:30
- }
- };*/
- this.Global.Candle = {
- public: {
- box_pixel: 4,
- space_pixel: 4,
- close: {
- bg: {
- color: "#ff6600",
- fillcolor:"#0a0a0a",
- width: 55,
- height: 14
- },
- type:"price",
- font: "",
- color: "#ff6600",
- lineColor: "rgb(225,225,225)"
-
- }
- },
- mt: {
- open_big_color: "white",
- open_small_color: "black",
- ob_border_color: "rgb(220,43,43)",
- os_border_color: "rgb(220,43,43)",
- grid: "mt"
- },
- hx: {//红涨绿卖
- open_big_color : "rgb(24,179,75)",/*红色"rgb(176,0,0)"*/
- open_small_color : "rgb(10,10,10)",
- ob_border_color : "rgb(24,179,75)",/*红色*/
- os_border_color :"rgb(176,0,0)" ,/*绿色"rgb(24,179,75)"*/
- grid: 'hx'
- }
- };
- }
- Config.obj = null;
- //单件模式
- Config.getInstance = function() {
- if (Config.obj == null) {
- Config.obj = new Config();
- //以下进行测试
- }
- return Config.obj;
- }
- Config.prototype.get = function(key, _default) {
- key = key.split(".");
- var _tmp = this;
- if (key.length == 0) return _default;
- for (var i = 0; i < key.length; i++) {
- if (typeof _tmp[key[i]] === "undefined") {
- return _default;
- } else {
- _tmp = _tmp[key[i]]
- }
- }
- return _tmp;
- }
- Config.prototype.getBrowserInfo = function() {
- var ua = navigator.userAgent.toLowerCase();
- var s;
- if (s = ua.match(/msie\s+([\d.]+)/)) {
- this.browser = "ie";
- this.bversion = s[1].split(".");
- } else if (s = ua.match(/firefox\/([\d.]+)/)) {
- this.browser = "firefox";
- this.bversion = s[1].split(".");
- } else if (s = ua.match(/chrome\/([\d.]+)/)) {
- this.browser = "chrome";
- this.bversion = s[1].split(".");
- } else if (s = ua.match(/opera.([\d.]+)/)) {
- this.browser = "opera";
- this.bversion = s[1].split(".");
- } else if (s = ua.match(/version\/([\d.]+).*safari/)) {
- this.browser = "safari";
- this.bversion = s[1].split(".");
- } else {
- this.browser = "other";
- this.bversion = [0, 0, 0];
- }
- if (!is_array(this.bversion) || this.bversion.length == 0) {
- this.bversion = [0, 0, 0];
- }
- for (var i = 0; i < this.bversion.length; i++) {
- this.bversion[i] = parseInt(this.bversion[i]);
- }
- //因为ie6的问题比较多,所以,添加一个专门的变量识别IE6
- this.isIE6 = (this.browser == "ie" && this.bversion[0] <= 6) ? true : false;
- }
- Config.prototype.set = function(key, value) {
- key = key.split(".");
- _tmp = this;
- if (key.length == 0) return this;
- var last = key.pop();
- for (var i = 0; i < key.length; i++) {
- if (typeof _tmp[key[i]] === "undefined") {
- _tmp[key[i]] = {};
- }
- _tmp = _tmp[key[i]];
- }
- _tmp[last] = value;
- return this;
- }
- Config.prototype.merge = function(key1, key2) {
- var dkey1 = this.get(key1);
- var dkey2 = this.get(key2);
- if (is_object(dkey1) && is_object(dkey2)) {
- for (var key in dkey2) {
- if (typeof key === "string" && typeof dkey2[key] !== "function") {
- dkey1[key] = dkey2[key];
- }
- }
- }
- this.set(key1, dkey1);
- }
- //控制器主要的工作是初始化整个工作环境。
- //1. canvas : Config.Global.MaxCanvasCount = 10 每个页面图形个数应该是有限制的,canvas太多,往往也看不清楚。
- //2. 选择正确的model Config.Global.ModelName = "ModelShortPoll"
- //3. 兼容性判断
- //
- //增加indicator。减少indicator的接口。
- //绘图接口
- //绘图更新接口
- //
- var periods = {
- // S5: 5,
- M1: 60,
- M2: 60 * 2,
- M3: 60 * 3,
- M4: 60 * 4,
- M5: 60 * 5,
- H1: 60 * 60,
- H2: 60 * 60 * 2,
- D1: 60 * 60 * 24,
- W1: 60 * 60 * 24 * 7,
- MN1: 60 * 60 * 24 * 30
- };
- function get_period_second(name) {
- var name = name.toUpperCase();
- var ratios = { S: 1, M: 60, H: 3600, D: 3600 * 24, W: 3600 * 24 * 7 };
- if (name == "MN1") {
- return periods[name];
- }
- var perfix = name.charAt(0);
- if (ratios[perfix] && ratios[perfix] > 0) {
- var base = parseInt(name.substr(1));
- if (isNaN(base)) return 0;
- return base * ratios[perfix];
- }
- return 0;
- }
- function Controller(api) {
- this.config = Config.getInstance();
- this.api = api;
- // console.log("api"+this.api);
- var opt = this.api.option;
- var indicators;
- this.plot_area = opt.plot_area;
- this.staticChat = opt.staticChat;
- this.startTime = opt.startTime;
- this.pair = opt.pair;
- this.toolbar = new ToolBar(this);
- this.initInd(opt.ind);
- this.runtime_load = opt.runtime_load;
- this.isinit = false;
- for (var key in this.pair) {
- if (is_object(this.pair[key])) {
- this.config.Global.yunit[key] = this.pair[key].yunit;
- }
- }
- this.timerID = null;
- this.intervalEvent = {};
- this.recall = {};
- if (this.api.option["toolbar.isenable"]) {
- this.toolbar.enable();
- } else {
- this.toolbar.disable();
- }
- this.model = this.getModel();
- this.view = this.getView();
- if (!this.runtime_load) {
- this.initChat();
- }
- this.isinit = false;
- this.init();
- }
- Controller.prototype.deinit = function() {
- this.model.deinit();
- this.view.deinit();
- this.toolbar.deinit();
- this.model = null;
- this.view = null;
- this.toolbar = null;
- }
- Controller.prototype.initChat = function() {
- this.indicators = this.api.indicators;
- var prevlist = [];
- var notseplist = [];
- for (var key in this.ind) {
- if (is_object(this.ind[key])) {
- name = key;
- if (this.ind[name].prev) {
- prevlist.push(name);
- continue;
- }
- if (!this.view.isSeperatePlot(name)) {
- notseplist.push(name);
- continue;
- }
- // if(name.split('"').length==2){
- // name=name.split('"')[1];
- // }
- this.registerChat(name, null, true);
- }
- //注册prev 形式的图
- }
- //对prevlist,首先它必须依赖一个 sep 的图。因为,每个not sep 都是,都是依赖某个sep放到某个sep上的。
- for (var i = 0; i < prevlist.length; i++) {
- var name = prevlist[i];
- var index = this.view.plotindex[this.ind[name].prev];
- if (typeof index === "undefined") {
- continue;
- }
- this.registerChat(name, index);
- }
- //对于非seplist的图表,这个性质是固有的,依赖某个图。
- for (var i = 0; i < notseplist.length; i++) {
- var name = notseplist[i];
- if (!this.ind[name].param) {
- index = 0;
- } else {
- var index = this.view.plotindex[this.ind[name].param[0][0]];
- if (typeof index === "undefined") {
- index = 0;
- }
- }
- this.registerChat(name, index);
- }
- }
- Controller.prototype.getIndParam = function(name) {
- if (this.ind[name] && this.ind[name].param) {
- return this.ind[name].param;
- }
- return false;
- }
- Controller.prototype.getIndList = function() {
- var ind = {};
- for (var key in this.ind) {
- ind[key] = 1;
- }
- return ind;
- }
- Controller.prototype.indTpl = function(indicator) {
- //判断是不是tpl
- //alert(disable_selected);
- if (this.config.Global.TPL[indicator]) {
- ToolBar.tplselect(indicator);
- indicator = this.config.Global.TPL[indicator];
- for (var key in HTML5StockChartAPI.API.tplParams) {
- var data = HTML5StockChartAPI.API.tplParams[key];
- if (typeof data === "string" || typeof data === "number") {
- indicator = indicator.replace(key, data);
- }
- }
- } else {
- ToolBar.tplselect("none");
- }
- // indicator =JSON.stringify(indicator).split(":");
- // console.log("indicator:"+indicator.split);
- if(indicator.split==undefined){
- return indicator
- }
- else{
- }
- if(indicator.split==undefined){
- return indicator;
- }
- indicator =indicator.split(':');
- return indicator;
- }
- Controller.prototype.initInd = function(indlist, disable_parse) {
- //ind 的结构进行调整:
- //区别对待下载数据,但是不显示的情况
- var indlist = this.indTpl(indlist);
- this.config.mainName = indlist[0];
- // if(this.config.mainName.split('"').length==2){
- // this.config.mainName=this.config.mainName.split('"')[1];
- // }
- // this.config.mainName=indlist[0]+'"';
- //alert(this.config.mainName);
- if (disable_parse) {
- var param_ind = indlist;
- } else {
- var param_ind = this.parseInd(indlist);
- }
- for (var i = 0; i < param_ind.length; i++) {
- var ind = param_ind[i];
- var name = param_ind[i].join("|");
- var ind_name = ind[0];
- //注册新的指标值,复制配置。
- if (ind[1]) {
- var depends = ind[1].split(",");
- for (var j = 0; j < depends.length; j++) {
- if (depends[j] == this.config.mainName || depends[j] == "null" || this.ind[depends[j]]) {
- //donothing
- continue;
- }
- if (this.config.Global.View[depends[j]]) {
- this.ind[depends[j]] = { name: depends[j], view: 0, prev: false };
- }
- }
- }
- ind.shift(); //shift 名称
- ind.shift(); //shift depends
- if (depends) {
- ind.unshift(depends);
- } else {
- ind.unshift("none");
- }
- this.ind[name].param = ind;
- this.config[name] = this.config[ind_name];
- this.config.Global.View[name] = this.config.Global.View[ind_name];
- this.config.Global.Axis[name] = this.config.Global.Axis[ind_name];
- }
- }
- Controller.prototype.parseInd = function(indlist) {
- var curperiod = get_period_second(this.api.p);
- this.ind = {};
- var param_ind = [];
- for (var i = 0; i < indlist.length; i++) {
- //判断是否是prev类型的
- var prev = false;
- var name = indlist[i];
- if (indlist[i].charAt(0) == "<") //prev
- {
- prev = this.config.mainName;
- if (i > 0) {
- for (var j = i - 1; j >= 0; j--) {
- if (indlist[j][0] != "<") {
- prev = indlist[j];
- break;
- }
- }
- }
- name = name.substr(1);
- }
- var ind = name.split("|");
- var index = ind[0].indexOf(",");
- var tper, tname;
- if (index != -1) {
- tname = ind[0].substring(0, index);
- tper = ind[0].substring(index + 1);
- name = tname + name.substring(ind[0].length);
- ind[0] = tname;
- if (tper != curperiod) {
- continue;
- }
- }
- if (ind.length > 1) {
- param_ind.push(ind);
- }
- this.ind[name] = {
- name: name,
- view: 1,
- prev: prev
- };
- }
- return param_ind;
- }
- Controller.prototype.addIntervalEvent = function(name, obj, recall) {
- this.intervalEvent[name] = obj;
- if (recall) {
- this.recall[name] = obj;
- }
- }
- Controller.prototype.removeIntervalEvent = function(name) {
- this.intervalEvent[name] = null;
- if (this.recall[name]) {
- this.recall[name] = null;
- }
- }
- Controller.prototype.recallEvent = function() {
- for (var key in this.recall) {
- if (this.recall[key] && is_object(this.recall[key])) {
- this.recall[key].recall(this);
- }
- }
- }
- Controller.prototype.init = function() {
- if (this.isinit) {
- return;
- }
- this.isinit = true;
- this.toolbar.init();
- this.view.init();
- this.setGlobalInterval();
- return true;
- }
- Controller.prototype.set = function(c, p) {
- // console.log('p:'+p)
- if (c && p) {
- this.c = c.toUpperCase();
- this.p = p.toUpperCase();
- $.cookie('period',this.p);
- this.init();
- if (this.model) {
- this.model.set(this.c, this.p);
- this.model.init();
- }
- }
- }
- Controller.prototype.setGlobalInterval = function() {
- var time = this.config.Global.Interval;
- if (time < 20) {
- time = 20;
- } //以20ms为单位
- //规则为:要实现一个功能,就分装一个函数在此处执行
- if (this.timerID !== null) {
- return;
- }
- var _this = this;
- this.timerID = window.setInterval(function() {
- var events = _this.intervalEvent;
- for (var key in events) {
- if (events[key] != null && is_object(events[key])) {
- events[key].run(_this);
- }
- }
- }, time);
- }
- Controller.prototype.flag = function(type) {
- debug(type);
- if (type == "new") {
- this.draw();
- this.recallEvent();
- if (this.config.Global.autoScroll) {
- triggerKeydown(Key.KEY_END);
- }
- } else if (type == "down") {
- this.draw();
- this.recallEvent();
- }
- }
- Controller.prototype.getModel = function() {
- var ModelClass = this.config.Global.modelName;
- //以后要加入兼容性的判断,最后选择一个正确的model
- return new ModelClass(this);
- }
- Controller.prototype.getView = function() {
- var ViewClass = this.config.Global.viewName;
- return new ViewClass(this);
- }
- Controller.prototype.registerChat = function(name, index, has_plot_area) {
- var indinfo = this.ind[name];
- if (indinfo.view) //如果没有view ,不会注册显示对象
- {
- this.view.registerPlot(name, index, has_plot_area, indinfo.param);
- }
- this.model.registerData(name);
- }
- Controller.prototype.unregisetChat = function(name) {
- this.view.unregisetData(name);
- this.view.unregisetPlot(name);
- }
- Controller.prototype.draw = function() {
- if(this.model==undefined)return;
- if (!this.model.ready) return;
- var viewconfig = this.view.getAxisConfig(); //view 的图形分布情况
- //然后。model要根据这个配置,生成相应的坐标数据。
- //坐标配置:
- // (绘图区域)
- // canvas_id => [width, height, 对应的图形名称:main, ma, easyforex ...]
- //
- // 返回的格式:图形名称 => 坐标数据
- //
- //主图要绘制的个数
- if (viewconfig.length <= 0) return;
- //清除原来的view数据
- this.view.clearData();
- this.model.clearData();
- debug("draw_data_init");
- var data = this.model.getData(viewconfig);
- for (var i = 0; i < data.length; i++) {
- //debug("get_data_beg");
- //获取数据内部进行封装:我们只调整这一块。
- //对画图来说,是自己计算的,还是服务器下载的是没有差别的。
- //这样就不会让问题扩大化。
- //debug("get_data_end");
- this.view.updateData(data[i], i); //加入数据
- //debug("calc_axis");
- }
- debug("draw_data_end");
- this.view.draw();
- //检查是否要下载数据
- this.model.downloadData();
- debug("draw_end");
- }
- Controller.prototype.startSet = function(name) {
- var one = this.view.plot[this.config.mainName].getOneSize();
- var area = this.view.grid[0].getPlotArea();
- if (name == "Next") {
- this.model.point(this.model.point() - Math.round(30 / one));
- } else if (name == "Prev") {
- this.model.point(this.model.point() + Math.round(30 / one));
- } else if (name == "PageDown") {
- this.model.point(this.model.point() + Math.round((area.x.beg - area.x.end) / one));
- } else if (name == "PageUp") {
- this.model.point(this.model.point() - Math.round((area.x.beg - area.x.end) / one));
- } else if (name == "Home") {
- this.model.point(this.model.endPos());
- this.model.state = 'home';
- } else if (name == "End") {
- this.model.point(0);
- this.model.state = 'end';
- }
- return this.model.point();
- }
- Controller.prototype.startOffset = function(offset) {
- var start = this.model.point();
- this.model.point(start + offset);
- }
- Controller.prototype.zoomIn = function() {
- this.view.plot[this.config.mainName].zoomIn();
- this.draw();
- }
- Controller.prototype.zoomOut = function() {
- this.view.plot[this.config.mainName].zoomOut();
- this.draw();
- }
- function Data() {
- }
- Data.OPEN = 0;
- Data.HIGH = 1;
- Data.LOW = 2;
- Data.CLOSE = 3;
- Data.VOLUMES = 4;
- //controller 中有一个接口会增加这个
- //事件,它提供一个接口给客户端
- //setVal()
- //getVal()
- //提供给controller 的接口是
- //run
- function IntervalEvent(count, callback, zerocall) {
- this.count = count;
- if (this.count <= 0) {
- this.count = 1;
- }
- this.current = 0;
- this.callback = callback;
- this.value = 0;
- this.prev = null;
- if (!zerocall) {
- this.zerocall = 0;
- } else {
- this.zerocall = zerocall;
- }
- }
- IntervalEvent.prototype.run = function(controller) {
- this.current++;
- if (this.count == this.current) {
- this.current = 0;
- if (this.zerocall) {
- this.prev = this.value;
- this.callback.call(this, controller);
- } else {
- if (this.value != 0) {
- this.prev = this.value;
- this.callback.call(this, controller);
- this.value = 0;
- }
- }
- }
- }
- IntervalEvent.prototype.getVal = function() {
- return this.value;
- }
- IntervalEvent.prototype.recall = function(controller) {
- this.value = this.prev;
- if (this.zerocall) {
- this.callback.call(this, controller, true);
- } else {
- if (this.value != 0) {
- this.callback.call(this, controller, true);
- this.value = 0;
- }
- }
- }
- IntervalEvent.prototype.setVal = function(val) {
- this.value = val;
- return this;
- }
- //数据更新部分:
- //广播服务器的设计是集中式的。我们要广播所有的数据,所以需要进行更新。
- //这个部分将会分为两个部分:下载K线,更新最新的数据
- //
- // 管理tick图:
- // 根据货币对k线,会注册一系列的K线,指标。
- // 更新或者下载的数据都有下面的属性:
- // 1. 货币对/时间/名称
- // 2. 绘图提供更新接口:
- // plot = plot_list[currency][time][name];
- // updateNew(data);
- // download(data);
- //
- //data.registerPlot(c, p, name, plot);
- //data.unregisetPlot(c, p, name, plot);
- //
- //采用广播协议的数据
- function Model(controller) {
- this.data = {};
- this.maindata = {};
- this.dataObj = {};
- this.realname = {};
- this.flagset = {};
- this.ready = false;
- //保存数据指针。标志当前图形读取的位置。
- this.datapoint = {};
- this.config = Config.getInstance();
- this.controller = controller;
- this.registerData(this.config.mainName); // 注册主图
- //alert(this.config.mainName);
- this.main = this.dataObj[this.config.mainName];
- this.downOptions = {};
- //这个由数据层来更新
- this.leftoffset = 0;
- this.rightoffset = 0;
- this.state = '';
- }
- Model.prototype.init = function() {
- //初始化数据
- if (this.c && this.p) {
- //判断是否这个货币对的数据已经初始化过了
- if (this.flag(Model.INITED)) {
- hide_loading();
- this.controller.draw();
- if (this.config.Global.newDisable || this.config[this.config.mainName].newdata) {
- this.newData();
- }
- } else if (this.flag(Model.INITING)) {
- return;
- } else {
- this.flag(Model.FIRST_NEW, 1);
- show_loading();
- this.flag(Model.INITING, 1);
- //alert(this.config.mainName);
- if (this.config['main'].downdata) {
- this.initData();
- } else {
- this.flag(Model.INITED, 1);
- this.init();
- }
- }
- }
- }
- Model.prototype.deinit = function() {
- //释放socket 资源
- }
- Model.NEW = 1;
- Model.DOWN = 1 << 1;
- Model.NEW_DATA = 1 << 2;
- Model.DOWN_DATA = 1 << 3;
- Model.INITED = 1 << 4;
- Model.INITING = 1 << 5;
- Model.NEW_DISABLE = 1 << 6;
- Model.DOWN_END = 1 << 7;
- Model.FIRST_NEW = 1 << 8;
- Model.UPDATE = 1 << 9;
- Model.prototype.registerData = function(name) {
- // console.log("name:"+name);
- if(this.config[name] && !this.dataObj[name]) {
- var newname = name.split("|", 2);
- if (newname.length == 2) {
- this.realname[newname[0]] = name;
- }
- var Reader = this.config[name].reader;
- var Writer = this.config[name].writer;
- this.dataObj[name] = {};
- if (Writer) {
- this.dataObj[name].writer = new Writer(this, name);
- }
- if (Reader) {
- this.dataObj[name].reader = new Reader(this, this.dataObj[name].writer, name);
- }
- //reader 要引用write
- }
- }
- Model.prototype.clearData = function() {
- for (var key in this.dataObj) {
- if (is_object(this.dataObj[key])) {
- this.dataObj[key].writer.clear();
- this.dataObj[key].reader.clear();
- }
- }
- }
- Model.prototype.getDataReader = function(name) {
- return this.dataObj[name].reader;
- }
- Model.prototype.unregisetData = function(name) {
- this.dataObj[name] = null;
- }
- Model.prototype.set = function(c, p) {
- if (this.c != c || this.p != p) {
- if (this.newDataXHR) this.newDataXHR.abort();
- //标记不在更新数据
- this.isNewing = false;
- if (this.subscribe) {
- this.subscribe();
- }
- this.downOptions = {};
- }
- this.c = c;
- this.p = p;
- $.cookie('period',p);
- //初始化标志位
- this.flagset = init_obj(this.flagset, this.c, this.p, 0);
- this.datapoint = init_obj(this.datapoint, this.c, this.p, 0);
- //set 所有的reader对象
- for (var key in this.dataObj) {
- if (is_object(this.dataObj[key])) {
- this.dataObj[key].reader.set();
- }
- }
- }
- Model.prototype.clearData = function() {
- this.data = {};
- }
- Model.prototype.getShift = function(plot) {
- var maxshift = -Infinity;
- for (var i = 0; i < plot.length; i++) {
- var name = plot[i];
- var shift = this.dataObj[name].reader.getShift();
- if (shift > maxshift) {
- maxshift = shift;
- }
- }
- return maxshift;
- }
- Model.prototype.getData = function(viewconfig) {
- //all plot list.
- var plot = [];
- this.plotnum = viewconfig[0].plotnum;
- for (var i = 0; i < viewconfig.length; i++) {
- var arr = viewconfig[i].plot;
- for (var j = 0; j < arr.length; j++) {
- plot.push(arr[j]);
- }
- }
- //初始化参数
- for (var i = 0; i < plot.length; i++) {
- var name = plot[i];
- //if (name == this.config.mainName) continue;
- var param = this.controller.getIndParam(name);
- if (param) {
- this.dataObj[name].reader.setParam(param);
- }
- }
- var shift = this.getShift(plot);
- //先计算普通的:
- for (var i = 0; i < viewconfig.length; i++) {
- this._getData(viewconfig[i].plot, viewconfig[i].plotnum + shift);
- }
- //再计算关联,但是不会在前台显示的数据
- var nodatalist = [];
- for (var i = 0; i < plot.length; i++) {
- var param = this.controller.getIndParam(plot[i]);
- if (param && param[0] != "none") {
- for (var k = 0; k < param[0].length; k++) {
- if (this.data[param[0][k]]) {
- continue;
- } else {
- nodatalist.push(param[0][k]);
- }
- }
- }
- }
- this._getData(nodatalist, viewconfig[0].plotnum + shift);
- //再计算通过这些数据得到“计算的数据”
- for (var j = 0; j < viewconfig.length; j++) {
- for (var i = 0; i < viewconfig[j].plot.length; i++) {
- var name = viewconfig[j].plot[i];
- var param = this.controller.getIndParam(name);
- if (param && param[2] != "__ignore__") {
- if (name == this.config.mainName) {
- continue;
- }
- if (param[0] != "none") {
- for (var k = 0; k < param[0].length; k++) {
- this.dataObj[name].reader.setDependData(param[0][k], this.data[param[0][k]]);
- }
- }
- this.data[name] = this.dataObj[name].reader.getData(this.config[name].data);
- }
- }
- }
- //计算完成了,这些数据就没有用了,释放掉内存
- for (var i = 0; i < nodatalist.length; i++) {
- this.data[nodatalist[i]] = null;
- }
- return this.formatData(viewconfig, shift);
- }
- Model.prototype._getData = function(plotlist, num) {
- if (!this.data[this.config.mainName]) {
- this.data[this.config.mainName] = this.dataObj[this.config.mainName].reader.getData(this.plotnum, this.config[this.config.mainName].data, true);
- this.maindata = this.dataObj[this.config.mainName].reader.getData(this.num, this.config[this.config.mainName].data, true);
- }
- //计算所有没有参数的情况
- for (var i = 0; i < plotlist.length; i++) {
- var name = plotlist[i];
- if (name == this.config.mainName) continue;
- var param = this.controller.getIndParam(name);
- if (!param || param[2] === "__ignore__") {
- this.data[name] = this.dataObj[name].reader.getDataByMain(this.config[name].data);
- }
- }
- }
- Model.prototype.shiftData = function(shift) {
- //先shift main,main直接按照数字shift
- //其他相关的shift按照时间进行shift。因为,不一定是对齐的。
- var main = this.config.mainName;
- if (shift > 0 && shift < this.data[main].x.length) {
- //this.data[main].x = this.data[main].x.slice(0, -shift);
- //this.data[main].y = this.data[main].y.slice(0, -shift);
- //var minx = this.data[main].x[this.data[main].x.length -1];
- /*for (var key in this.data)
- {
-
- if (key == main) continue;
- if (this.data[key] && is_object(this.data[key]))
- {
- var shift = this.getShiftNumber(this.data[key].x, minx);
- this.data[key].x = this.data[key].x.slice(0, -shift);
- this.data[key].y = this.data[key].y.slice(0, -shift);
- }
- }*/
- }
- for (var key in this.data) {
- if (this.data[key] && is_object(this.data[key])) {
- this.data[key] = this.dataObj[key].reader.formatData(this.data[key].x, this.data[key].y);
- }
- }
- }
- Model.prototype.getShiftNumber = function(x, minx) {
- var count = 0;
- for (var i = x.length - 1; i >= 0; i--) {
- if (x[i] >= minx) {
- break;
- } else {
- count++;
- }
- }
- return count;
- }
- //如果是主图的数据,因为要用于对齐,所以,复制一份
- //防止外界对其进行修改操作。
- Model.prototype.formatData = function(viewconfig, shift) {
- this.shiftData(shift);
- //再计算通过这些数据得到“计算的数据”
- var data = [];
- //var text;
- for (var j = 0; j < viewconfig.length; j++) {
- data[j] = {};
- //text = "";
- for (var i = 0; i < viewconfig[j].plot.length; i++) {
- var name = viewconfig[j].plot[i];
- if (name == this.config.mainName) {
- data[j][name] = object_copy(this.data[this.config.mainName]);
- data[j][name].x = array_copy1d(this.data[this.config.mainName].x);
- } else {
- data[j][name] = this.data[name];
- }
- //text += "[" + this.getShowName(name) + " " + this.lastData(this.data[name].y[0]) + "] ";
- }
- data[j].c = this.c;
- data[j].p = this.p;
- //data[j].text = text;
- }
- return data;
- }
- Model.prototype.update = function(data, type) {
- if (!data) {
- if (type == Model.DOWN) {
- this.ready = true;
- this.controller.flag("down");
- this.flag(Model.DOWN_END, 1);
- }
- return;
- }
- if (data.code) {
- if (data.code == "goto" && data.msg) {
- window.location.href = data.msg;
- }
- return;
- }
- var is_new = false;
- var is_down = false;
- var is_update = false;
- if (!data.c || !data.p) {
- return;
- }
- var c = data.c.toUpperCase();
- var p = data.p.toUpperCase();
- //数据已经下载到末尾了
- var end = data.end;
- this.flag(Model.DOWN_END, end);
- if (data.code) {
- debug(data.code);
- //发生了错误
- return;
- }
- this.downOptions = data.options || {};
- for (var key in data) {
- //下载的数据
- if (!is_object(data[key])) continue;
- //这三个是保留的
- if (key == "c" || key == "p" || key == "code" || key == "end") {
- continue;
- }
- var keyreal = key;
- if (typeof this.dataObj[key] === "undefined") {
- key = this.realname[key];
- }
- if (typeof key === "undefined") {
- continue;
- }
- if (this.dataObj[key]) {
- if (type == Model.NEW) {
- is_new = true;
- if (this.dataObj[key].writer) this.dataObj[key].writer.setNewData(c, p, data[keyreal]);
- } else if (type == Model.UPDATE) {
- is_update = true;
- if (this.dataObj[key].writer) this.dataObj[key].writer.setUpdateData(c, p, data[keyreal]);
- } else if (this.downOptions.total_size) {
- is_down = true;
- if (this.dataObj[key].writer && this.dataObj[key].writer.setDownloadDataByOffset) {
- this.dataObj[key].writer.setDownloadDataByOffset(c, p, data[keyreal], this.downOptions);
- } else {
- if (this.dataObj[key].writer) this.dataObj[key].writer.setDownloadData(c, p, data[keyreal]);
- }
- } else {
- //判断是否存在数据对象,那么更新图形的数据。
- is_down = true;
- if (this.dataObj[key].writer) this.dataObj[key].writer.setDownloadData(c, p, data[keyreal]);
- }
- }
- }
- if (is_new) {
- this.ready = true;
- this.controller.flag("new");
- }
- if (is_down) {
- this.ready = true;
- this.controller.flag("down");
- }
- if (is_update) {
- this.ready = true;
- this.controller.flag("new");
- }
- }
- Model.prototype.getIndicatorList = function() {
- var list = [];
- for (var key in this.dataObj) {
- if (key == this.config.mainName) continue; //主图的数据,数据接口会默认更新
- if (is_object(this.dataObj[key])) {
- list.push(key);
- }
- }
- return list;
- }
- //数据集合中,按照时间,或者某个x轴一路更新
- //肯定会有一个边界。这个数据边界就从这里取。
- Model.prototype.startXValue = function() {
- var start = this.main.reader.startXValue();
- if (start <= 0 && this.controller.startTime) {
- return this.controller.startTime;
- }
- return start;
- }
- Model.prototype.endXValue = function() {
- return this.main.reader.endXValue();
- }
- Model.prototype.leftDataCount = function() {
- return this.endPos() - this.point() - this.plotnum;
- }
- Model.prototype.rightDataCount = function() {
- return this.point();
- }
- Model.prototype.endPos = function() {
- return this.main.reader.getEndPos();
- }
- Model.prototype.flag = function(key, value, c, p) {
- if (!c) {
- c = this.c;
- }
- if (!p) {
- p = this.p;
- }
- if (!c || !p) {
- return;
- }
- c = c.toUpperCase();
- p = p.toUpperCase();
- if (typeof value === "undefined") {
- return (this.flagset[c][p] & key) == key; //判断标志位是否已经被设置了
- } else if (value == 0) {
- this.flagset[c][p] = this.flagset[c][p] & (~key); //清除标志位
- } else {
- this.flagset[c][p] = this.flagset[c][p] | key; //设置标志位
- }
- }
- Model.prototype.point = function(value) {
- if (typeof value === "undefined") {
- return this.datapoint[this.c][this.p];
- } else {
- this.datapoint[this.c][this.p] = value;
- }
- }
- Model.prototype.getLeftOffset = function() {
- return this.leftoffset;
- }
- Model.prototype.getRightOffset = function() {
- return this.rightoffset;
- }
- Model.prototype.getDownOffset = function(down_flag) {
- this.count = this.config.Global.downloadCount;
- if (down_flag == -1 && this.getRightOffset() == 0) {
- return -1;
- }
- if (down_flag == 1 && this.getLeftOffset() >= this.downOptions.total_size) {
- return -1;
- }
- if (down_flag == 1) {
- var offset = this.getLeftOffset() + 1; //读取下一个数据
- //超出范围
- if (offset >= this.downOptions.total_size) offset = -1;
- }
- if (down_flag == -1) {
- var offset = this.getRightOffset() - this.config.Global.downloadCount;
- if (offset < 0) {
- offset = 0;
- this.count = this.getRightOffset() - offset;
- }
- }
- return offset;
- }
- Model.prototype.getDataByTime = function(name, time, near) {
- var x = this.dataObj[name].writer.getX(this.c, this.p);
- var y = this.dataObj[name].writer.getY(this.c, this.p);
- var index = binsearch_r(x, time);
- var obj = {};
- obj.time = timeToDate(time, this.config.Global.timeformat[this.p], this.config.Global.timezone);
- if (index == -1 && near == "candle") {
- index = find_last_little_r(x, time);
- if (index == -1) return false;
- var close = y[index][Data.CLOSE];
- obj.data = [close, close, close, close, y[index][Data.VOLUMES]];
- } else {
- if (index == -1) return false;
- obj.data = y[index];
- }
- return obj;
- }
- __javascript_debug__ = false;
- __datasource__ = "db";
- __datafile__ = "db";
- __debug__ = false;
- __static__ = false;
- __runtime_load__ = false;
- __start_time__ = false;
- __baseurl__ = "http:\/\/locaohost:9001\/";
- __broadcast_server_active__ = "115.236.165.18";
- __loadhost__ = "localhost:9001";
- __refererhost__ = "localhost:9001";
- __orderhost__ = "localhost:9001";
- __apihost__ = "rsi.33.cn";
- __dbreset__ = ""
- __musicselect__ = { "alert.wav": "alert", "alert2.wav": "alert2", "connect.wav": "connect", "disconnect.wav": "disconnect", "email.wav": "email", "expert.wav": "expert", "ok.wav": "ok", "request.wav": "request", "stops.wav": "stops", "tick.wav": "tick", "timeout.wav": "timeout", "wait.wav": "wait", "": "", "\u05a3\u0534 - ": "\u05a3\u0534 - " };
- //plot base function. process base plot function.
- function Key() {
- }
- Key.KEY_PREV = 37;
- Key.KEY_UP = 38;
- Key.KEY_NEXT = 39;
- Key.KEY_DOWN = 40;
- Key.KEY_HOME = 36;
- Key.KEY_END = 35;
- Key.KEY_PAGE_DOWN = 34;
- Key.KEY_PAGE_UP = 33;
- function Plot(view, grid, name) {
- this.view = view;
- this.name = name;
- this.controller = this.view.controller;
- this.grid = grid;
- this.getPlotArea();
- this.ctx = this.grid.ctx;
- this.ctxBG = this.grid.ctxBG;
- this.ctxFront = this.grid.ctxFront;
- this.axis = this.grid.axis;
- this.canvas = this.grid.canvas;
- this.config = Config.getInstance();
- this.param = {};
- classname = getClassName(this);
- classname = classname.substr(4);
- if (this.config.Global[classname]) {
- this.conf = this.config.Global[classname].public;
- } else {
- this.conf = {};
- }
- //对K线图的操作是全局性的。也就是说,这里的不会像grid里面一样复制一份全局配置。
- //而是直接操作全局配置
- }
- //默认一个时间占据一个像素,这个是线条默认的占用值。
- Plot.prototype.getOneSize = function() {
- return 1;
- }
- //默认一个时间占据一个像素,这个是线条默认的占用值。
- Plot.prototype.getPlotArea = function() {
- var area = this.grid.getPlotArea();
- this.top = area.y.end;
- this.left = area.x.end;
- this.bottom = area.y.beg;
- this.right = area.x.beg + this.grid.conf.paddingX;
- }
- Plot.prototype.getShowName = function() {
- var name = this.name.toUpperCase();
- name = name.replace("MAIN", "OHLC").replace("FXTRADE", "OANDA").replace("||", " ");
- if (name.indexOf("PROFIT_LINE") != -1) {
- name = "PROFIT";
- }
- name = name.split("|");
- if (name.length == 1) {
- return name[0];
- }
- var pre = name.shift();
- return pre + " (" + name.join(" , ") + ")";
- }
- Plot.prototype.lastData = function() {
- var data = this.view.model.getDataReader(this.name).last();
- if (typeof data === "undefined") {
- return "";
- }
- try {
- var yunit = this.axis.viewconfig.y.axis_option.unit;
- } catch (e) {
- return "";
- }
- var ret = [];
- if (is_array(data)) {
- for (var i = 0; i < data.length; i++) {
- ret[i] = this.grid.getText(0, data[i], yunit);
- }
- return ret;
- } else if (!isNaN(Number(data))) {
- return this.grid.getText(0, data, yunit);
- } else {
- return data;
- }
- }
- Plot.prototype.setParam = function(param) {
- if (param.length >= 3) {
- this.param = this.parseParam(param[2]);
- }
- }
- Plot.prototype.parseParam = function(pstr) {
- pstr = pstr.split(",");
- var ret = {};
- for (var i = 0; i < pstr.length; i++) {
- var tmp = pstr[i].split("=", 2);
- ret[tmp[0]] = tmp[1];
- }
- return ret;
- }
- Plot.prototype.lastDataShow = function() {
- var data = this.lastData();
- if (is_array(data)) {
- return data.join(", ");
- }
- return data;
- }
- //价格标线
- Plot.prototype.priceFlag = function(close_price, conf) {
- var close_y = this.axis.getY(close_price);
- drawWithArrowheads(this.grid.xEnd.x-14,close_y,this.grid.xEnd.x+30,close_y,this.ctx);
- // drawRow(this.ctx, new Point(this.grid.xEnd.x , close_y), 10, conf.lineColor, 1);
- //能直接访问grid的内容
- var height = conf.bg.height / 2;
- if (close_y >= 0 && close_y - this.grid.O.y < height) {
- close_y = this.grid.O.y + height;
- }
- if (close_y <= this.grid.xyEnd.y && this.grid.xyEnd.y - close_y < height) {
- close_y = this.grid.xyEnd.y - height;
- }
- conf.unit = this.yunit;
- writeTextOption(this.ctx, new Point(this.grid.xEnd.x-6, close_y), close_price, conf);
- }
- function Shape(ctx, width, height, opt) {
- this.ctx = ctx;
- this.width = width ? width : 0;
- this.height = height ? height : 70;
- if (!opt) {
- opt = {};
- }
- this.boder = opt.boder ? opt.boder : "black";
- this.fill = opt.fill ? opt.fill : "black";
- this.cta = opt.cta ? opt.cta : 0;
- }
- __symbol__list__ = {
- // "BTYBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.001 },
- // "BTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
- "BCCBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
- "ETHBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
- "ETCBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
- // "SC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.0001 },
- // "WTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.0001 },
- // "NYCC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.001 },
- // "BTS": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.001 },
- "LTCBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
- "ZECBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 }
- }
- function ToolBar(controller) {
- this.controller = controller;
- this.pair = this.controller.pair;
- // this.initPair();
- // this.hideSymbol(); //隐藏没有数据的货币对
- this.config = Config.getInstance();
- this.api=this.controller.api;
- this.isenable = true;
- }
- ToolBar.prototype.deinit = function() {
- }
- //显示出BTY 和ETH标签
- ToolBar.prototype.initPair = function() {
- // $("#symbol").html('');
- for (var c in this.pair) {
- if (!is_object(this.pair[c])) {
- continue;
- }
- }
- }
- ToolBar.prototype.enable = function() {
- $("#toolbar").show();
- this.isenable = true;
- }
- ToolBar.prototype.disable = function() {
- $("#toolbar").hide();
- this.isenable = false;
- }
- ToolBar.prototype.hideSymbol = function() {
- var _this = this;
- $("#symbol2").find("li").each(
- function() {
- var text = $(this).text();
- text = $.trim(text);
- $(this).show();
- if (typeof _this.pair[text] !== "object") {
- $(this).hide();
- }
- }
- );
- }
- ToolBar.prototype.hidePeriod = function(c) {
- var _this = this;
- if (!c) return;
- var _timeList = _this.pair[c];
- if (!_timeList) return;
- _timeList = _timeList.time;
- _timeMap = {};
- for (var i = 0; i < _timeList.length; i++) {
- _timeMap[_timeList[i]] = 1;
- }
- $("#period").find("li").each(
- function() {
- var text = $(this).text();
- text = $.trim(text);
- $(this).show();
- if (_timeMap[text] !== 1) {
- $(this).hide();
- }
- }
- );
- }
- ToolBar.prototype.init = function() {
- this.InitIndicatorstatus();
- //添加事件
- var _this=this;
- $("#Indicator_list label").click(function () {
- var name=$(this).text();
- _this.IndicatorStatusChange(this);
- })
- // $("#Indicator_list li").click(function () {
- // var name=$(this).attr('name');
- // if($(this).find('a').attr('class')=='active'){
- // $(this).find('a').removeClass('active');
- // }
- // else{
- // $(this).find('a').addClass('active');
- // }
-
- // _this.IndicatorStatusChange(name);
- // })
- //bty,eth选择切换
- $("#symbol2 a").click(function(){
- $("#symbol2 a").removeClass("active");
- var uid=$.cookie().id;
- $(this).addClass("active");
- _this.newsymbol(this);
- });
- $("#getsymbol").click(function(){
- console.log($.cookie('symbol'));
- if(sessionStorage.getItem('symbol')=='YCC'){
- HTML5StockChartAPI.API.setPair('NYCC', sessionStorage.getItem('period'));
- }else{
- HTML5StockChartAPI.API.setPair($.cookie('symbol'), sessionStorage.getItem('period'));
- }
-
- })
- $("#ethsymbol").click(function(){
- HTML5StockChartAPI.API.setPair("ETHBTC", $.cookie('period'));
- })
- $("#etcsymbol").click(function(){
- HTML5StockChartAPI.API.setPair("ETCBTC", $.cookie('period'));
- })
- $("#bccsymbol").click(function(){
- HTML5StockChartAPI.API.setPair("BCCBTC", $.cookie('period'));
- })
- /* $("#Indicator_list a").click(function(){
- var name=$(this).text();
- _this.IndicatorStatusChange(name);
- });*/
- $("#period li").click(function() {
- $("#period a").removeClass("active");
- _this.period(this);
- });
- $("#plot_area").bind('click', function() {
- _this.toolList();
- });
- $('body').not($("#plot_area")).unbind('mouseover', function() {
- // console.log($(this));
- $('body').css("cursor", "hand");
- _this.toolList();
- //$("#dropzone").slideUp("normal");
- });
- // this.addSelectEvent($("#symbol2"), this.symbol);
- this.addSelectEvent($("#period"), this.period);
- //this.addSelectEvent($("#tool_list"), this.toolList);//加号功能,指标
- this.addClickEvent($("#zoom"), this.zoom);
- //选择:
- ToolBar.selectItem($("#period"), $.cookie('period'));
- }
- ToolBar.prototype.InitIndicatorstatus = function() {
- // console.log("this.api:"+this.api);
- var inds = $.cookie('ind');
- if (this.config.Global.TPL[inds]) {
- inds = this.config.Global.TPL[inds];
- }
- if (inds.indexOf("ma|main|") != -1) {
- this.SetIndicatorStatus("MA");
- }
- if (inds.indexOf("macd|main|") != -1) {
- this.SetIndicatorStatus("MACD");
- }
- if (inds.indexOf("volumes") != -1) {
- this.SetIndicatorStatus("VOLUMES");
- }
- if (inds.indexOf("bolling") != -1) {
- this.SetIndicatorStatus("BOLLING");
- }
- if (inds.indexOf("kdj") != -1) {
- this.SetIndicatorStatus("KDJ");
- }
- }
- ToolBar.prototype.SetIndicatorStatus = function(indname) {
- $("#Indicator_list label").each(function() {
- if ($(this).text() == indname) {
- $(this).addClass("active");
- }
- });
- }
- ToolBar.prototype.IndicatorStatusChange = function(obj) {
- var name=$(obj).text();
- if($(obj).attr("class")=='active'){
- $(obj).removeClass('active');
- }
- else{
- $(obj).addClass('active')
- }
- var indstr = "main:";
- $("#Indicator_list label").each(function(){
- if ($(this).attr("class")=='active') {
- switch ($(this).text()) {
- case "MA":
- indstr += Config.getInstance().Global.TPL["ma"];
- break;
- case "VOLUMES":
- indstr += Config.getInstance().Global.TPL["volumes"];
- break;
- case "MACD":
- indstr += Config.getInstance().Global.TPL["macd"];
- break;
- case "BOLLING":
- indstr += Config.getInstance().Global.TPL["bolling"];
- break;
- case "KDJ":
- indstr += Config.getInstance().Global.TPL["kdj"];
- break;
- }
- }
- })
- // var indstr = "main:";
- // var indstr = this.api.read('ind');
- // if(this.config.Global.TPL[indstr]) {
- // indstr = this.config.Global.TPL[indstr];
- // }
- // switch (obj) {
- // case "MA":
- // indstr += Config.getInstance().Global.TPL["ma"];
- // break;
- // case "VOLUMES":
- // indstr += Config.getInstance().Global.TPL["volumes"];
- // break;
- // case "MACD":
- // indstr += Config.getInstance().Global.TPL["macd"];
- // break;
- // case "BOLLING":
- // indstr += Config.getInstance().Global.TPL["bolling"];
- // break;
- // case "KDJ":
- // indstr += Config.getInstance().Global.TPL["kdj"];
- // break;
- // }
- // console.log("IndicatorStatusChange:"+name);
- // var indstr = "main:";
- // // 选中那个a 标签就执行什么
- // $("input[name = Indicator]:checkbox").each(function() {
- // if ($(this).is(":checked")) {
- // switch ($(this).val()) {
- // case "MA":
- // indstr += Config.getInstance().Global.TPL["ma"];
- // break;
- // case "VOLUMES":
- // indstr += Config.getInstance().Global.TPL["volumes"];
- // break;
- // case "MACD":
- // indstr += Config.getInstance().Global.TPL["macd"];
- // break;
- // case "BOLLING":
- // indstr += Config.getInstance().Global.TPL["bolling"];
- // break;
- // case "KDJ":
- // indstr += Config.getInstance().Global.TPL["kdj"];
- // break;
- // }
- // }
- // });
- this.api.setInd(indstr);
- }
-
- ToolBar.prototype.signal = function(obj) {
- var signal_id = $.trim(obj.attr('name'));
- //write cookie of signal
- api.setSignal(signal_id);
- }
- ToolBar.prototype.model = function(obj) {
- var model_id = $.trim(obj.attr('name'));
- //write cookie of model
- api.setModel(model_id);
- }
- ToolBar.prototype.tplswitch = function(obj) {
- var tpl = $.trim(obj.attr('name'));
- if (tpl == "none") return;
- var api = HTML5StockChartAPI.API;
- api.setIndicatorConf(tpl);
- }
- ToolBar.tplselect = function(name) {
- ToolBar.selectItem($("#tpl_list"), name);
- //alert(name);
- }
- ToolBar.prototype.clickFirst = function(obj) {
- var obj = obj.find("li");
- for (var i = 0; i < obj.length; i++) {
- var item = $(obj.get(i));
- if (item.css("display") == "none") {
- continue;
- }
- item.click();
- break;
- }
- }
- ToolBar.prototype.clickByName = function(obj, name) {
- var obj = obj.find("li");
- for (var i = 0; i < obj.length; i++) {
- var item = $(obj.get(i));
- if ($.trim(item.text()) == name) {
- item.click();
- break;
- }
- }
- }
- ToolBar.prototype.clickByLiName = function(obj, name) {
- var obj = obj.find("li");
- for (var i = 0; i < obj.length; i++) {
- var item = $(obj.get(i));
- if (item.attr("name") == name) {
- item.click();
- break;
- }
- }
- }
- ToolBar.prototype.symbol = function(obj) {
- var c = $.trim(obj.text());
- //c="MAC";
- var c = this.findSelected($("#symbol2"));
- //if(c = "ETH") window.location.href="http://33.cn/ethcny";
- //if(c = "BTY") window.location.href="http://33.cn/";
- this.hidePeriod(c); //隐藏没有数据的时间周期
- var p = this.findSelected($("#period"));
- $.cookie('period',p);
- // console.log("p=", p);
- if (!p) {
- //this.clickFirst($("#period"));
- HTML5StockChartAPI.API.setPair(c, this.controller.p);
- } else {
- HTML5StockChartAPI.API.setPair(c, p);
- }
- }
- ToolBar.prototype.newsymbol = function(obj) {
- var c = $(obj).attr("name");
- if ($.cookie('symbol') != c) {
- $.cookie("symbol", null);
- $.cookie("symbol", c);
- }
- //$("#period").children().first();
- // $("#period").children().first().text(c);
- //c="MAC";
- //var c = this.findSelected($("#symbol"));
- //if(c = "ETH") window.location.href="http://33.cn/ethcny";
- //if(c = "BTY") window.location.href="http://33.cn/";
- // this.hidePeriod(c); //隐藏没有数据的时间周期
- var p = this.findSelected($("#period"));
- $.cookie('period',p);
- // console.log("p=", p);
- if (!p) {
- //this.clickFirst($("#period"));
- HTML5StockChartAPI.API.setPair(c, this.controller.p);
- } else {
- HTML5StockChartAPI.API.setPair(c, p);
- }
- }
- ToolBar.prototype.toolList = function(obj) {
- var name = obj.attr("name");
- var _this = this;
- if (name == "cross") //cross情况
- {
- $("#plot_area").css("cursor", "crosshair");
- var view = this.controller.view;
- if (window["FlashCanvas"]) {
- var count = 5;
- } else {
- var count = 2;
- }
- var crossMoveInterval = new IntervalEvent(
- count,
- function(controller, recall) //可以重新被call
- {
- var _this = controller.view;
- if (typeof recall == "undefined") {
- _this.draw();
- }
- if (!this.value || this.value.length != 3) {
- return;
- }
- var x = this.value[0];
- var y = this.value[1];
- var index = this.value[2];
- for (var i = 0; i < _this.canvasActiveCount; i++) {
- _this.grid[i].drawCrossX(x, _this.axis[0]);
- }
- _this.grid[index].drawCrossY(y);
- }
- );
- for (var i = 0; i < view.canvasActiveCount; i++) {
- view.canvas[i].bind("mousemove", crossMoveInterval, this.crossMove);
- }
- //if the page is redraw, call it by controller.recall(). now, only new tick
- //redraw need to recall.
- this.controller.addIntervalEvent("crossMove", crossMoveInterval, true);
- $(document).bind("mouseover", function(e) {
- // console.log(e.target);
- $("body").css("cursor", "default");
- for (var i = 0; i < view.canvasActiveCount; i++) {
- view.canvas[i].unbind("mousemove", _this.crossMove);
- }
- view.draw();
- _this.controller.removeIntervalEvent("crossMove");
- _this.clickByLiName($("#tool_list"), "none");
- $(document).unbind("mouseover");
- });
- } else if (name == "kline_first") { //
- var view = this.config.Global.View;
- for (var key in view) {
- if (is_object(view[key]) && typeof view[key].disable_axis_area !== "undefined") {
- view[key].disable_axis_area = 1;
- }
- }
- this.controller.draw();
- } else if (name == "ind_first") {
- var view = this.config.Global.View;
- for (var key in view) {
- if (is_object(view[key]) && typeof view[key].disable_axis_area !== "undefined") {
- view[key].disable_axis_area = 0;
- }
- }
- this.controller.draw();
- } else if (name == "indicator") {
- $("#tool_list").find("li[name='indicator']").css('cursor', 'pointer');
- indicator.show();
- } else if (name == "tick_price") {
- }
- }
- ToolBar.prototype.toolList = function() {
- var _this = this;
- $("#plot_area").css("cursor", "crosshair");
- this.controller=this.api.controller;
- var view = this.controller.view;
- if (window["FlashCanvas"]) {
- var count = 5;
- } else {
- var count = 2;
- }
- var crossMoveInterval = new IntervalEvent(
- count,
- function(controller, recall) //可以重新被call
- {
- var _this = controller.view;
- if (typeof recall == "undefined") {
- _this.draw();
- }
- if (!this.value || this.value.length != 3) {
- return;
- }
- var x = this.value[0];
- var y = this.value[1];
- var index = this.value[2];
- for (var i = 0; i < _this.canvasActiveCount; i++) {
- _this.grid[i].drawCrossX(x, _this.axis[0]);
- }
- _this.grid[index].drawCrossY(y);
- }
- );
- for (var i = 0; i < view.canvasActiveCount; i++) {
- view.canvas[i].bind("mousemove", crossMoveInterval, this.crossMove);
- }
- //if the page is redraw, call it by controller.recall(). now, only new tick
- //redraw need to recall.
- this.controller.addIntervalEvent("crossMove", crossMoveInterval, true);
- $(document).bind("mouseover", function(e) {
- $("#plot_area").css("cursor", "default");
- if(e.target.id.indexOf("plot")==-1){
- for (var i = 0; i < view.canvasActiveCount; i++) {
- view.canvas[i].unbind("mousemove", _this.crossMove);
- }
- view.draw();
- _this.controller.removeIntervalEvent("crossMove");
- _this.clickByLiName($("#tool_list"), "none");
- $(document).unbind("mouseover");
- }
-
- });
- }
- ToolBar.prototype.crossMove = function(event) {
- var crossMoveInterval = event.data;
- var id = $(this).attr("id");
- var index = id.split("_").pop();
- index = index.substr(0, index.length - 1);
- index = parseInt(index);
- var x = event.pageX - $(this).offset().left;
- var y = event.pageY - $(this).offset().top;
- crossMoveInterval.setVal([x, y, index]);
- }
- ToolBar.prototype.period = function(obj) {
- var c =$.cookie('symbol');
- if ($(obj).find("a").length ==1) {
- var p = $.trim($(obj).text());
- $.cookie('period',p);
- } else {
- // $(obj).find("a").setAttribute('class','active');
- var elemt = obj.firstChild;
- elemt.setAttribute('class', 'active');// obj拿到的是类似<li name="M1" class="period"><a href="#">M1</a></li>,所以需要拿到M1也就是a标签下的text
- var p = $.trim($(elemt).text());
- $.cookie('period',p);
- $.cookie('period',p);
- }
- // console.log("period:"+p)
- HTML5StockChartAPI.API.setPair(c, p);
- /* if (!c) {
- return; //没有意义,直接忽略
- } else {
- HTML5StockChartAPI.API.setPair("MAC", p);
- }*/
- }
- ToolBar.prototype.zoom = function(obj) {
- var name = obj.attr("name");
- if (name == "in") {
- this.controller.zoomIn();
- } else if (name == "out") {
- this.controller.zoomOut();
- }
- }
- ToolBar.prototype.style = function(obj) {
- var name = obj.attr("name");
- set_style(name);
- this.controller.draw();
- }
- ToolBar.prototype.findSymbolSelected = function(obj) {
- var text = "";
- $(obj).find("a").each(function() {
- if ($(this).attr("class") == "active") {
- text = $(this).attr("name");
- }
- })
- // console.log("findSymbolSelected:"+$.trim(text));
- return $.trim(text);
- }
- ToolBar.prototype.findSelected = function(obj) {
- var text = obj.find("li > strong").text();
- return $.trim(text);
- }
- ToolBar.prototype.addSelectEvent = function(obj, callback) {
- //获取li
- var _this = this;
- var _obj = obj.find("li");
- _obj.each(
- function() {
- var __callback = callback;
- var __obj = _obj;
- $(this).bind("click", _this,
- function(event) {
- var _this = event.data;
- __obj.each(
- function() {
- var text = $(this).text();
- text = $.trim(text);
- // $(this).html("<a href=\"javascript:void(0)\">" + text + "</a>");
- }
- );
- $(this).html('<a class="active" >' + $.trim($(this).text()) + '</a>');
- if (__callback) __callback.call(_this, $(this));
- }
- );
- }
- );
- }
- ToolBar.prototype.addClickEvent = function(obj, callback) {
- var _this = this;
- var _obj = obj.find("li");
- _obj.each(
- function() {
- var __callback = callback;
- $(this).bind("click", _this,
- function(event) {
- var _this = event.data;
- if (__callback) __callback.call(_this, $(this))
- }
- );
- }
- );
- }
- //select item , not trigger event.
- ToolBar.selectItem = function(obj, name) {
- var __obj = obj.find("li");
- var _this = obj.find("li[name='" + name + "']");
- __obj.each(
- function() {
- var text = $(this).text();
- text = $.trim(text);
- $(this).html("<a href=\"javascript:void(0)\">" + text + "</a>");
- }
- );
- //alert(_this.length);
- $(_this).html('<a class="active">' + $.trim($(_this).text()) + '</a>');
- }
- //view 视图,负责绘制图形。
- //控制器把从model 读取数据后,做处理完成。然后更新到view里面。
- //view 再利用这些数据,绘制出图形,view 不能直接读取model 的数据。
- //而是读取control 的数据,这样有一个中间的层次,便于扩展。
- //view 没有c . p 的概念。每个图形的model都会有一个getData接口。
- //每个图形的 view 都有一个setData 的接口。
- //关于图形的显示格式。我想任何选项,包括view 包括 model的都通过
- //更改config的形式来实现。对象本身只是读取配置,不提供更改接口。
- //比如:view 的样式的修改。每次在之前会读取配置。
- //比如:model改成静态图形了,也是类似的修改配置,就可以自动完成。
- //在不同对象之间传递配置信息过于繁琐。我想直接读取配置是最好的方式。
- //
- function View(controller) {
- //当前的图像
- this.controller = controller;
- this.model = this.controller.model;
- this.config = Config.getInstance();
- this.plot_area = this.controller.plot_area;
- this.setPlotArea();
- this.canvas = [];
- this.canvasBG = [];
- this.canvasFront = [];
- this.canvasContainer = [];
- this.resize = [];
- this.grid = [];
- this.axis = [];
- //给每个canvas分配一个grid对象
- var main_axis = new Axis(null);
- for (var i = 0; i < this.config.Global.maxCanvasCount; i++) {
- var prefix = "#" + this.config.Global.canvasIDPerfix + i;
- var id = prefix + "2";
- var bg = prefix + "1";
- var front = prefix + "0";
- var id_div = "#" + this.config.Global.canvasIDPerfix + "div" + "_" + i;
- //canvas
- var tmp = $(id);
- if (!tmp) {
- continue;
- }
- if (!this.config.isIE6) {
- tmp.hide();
- }
- this.canvas.push(tmp);
- this.canvasBG.push($(bg).hide());
- this.canvasFront.push($(front).hide());
- this.canvasContainer.push($(prefix).hide());
- //resize
- var resize = $(id_div);
- resize.hide();
- this.resize.push(resize);
- if (i == 0) { //主图
- var axis_obj = main_axis;
- } else {
- var axis_obj = new Axis(main_axis);
- }
- this.axis.push(axis_obj);
- this.grid.push(new PlotGrid(this, i));
- }
- //设置宽度
- this.setWidth();
- this.setHeight();
- set_style();
- //主图被注册了
- this.canvasActiveCount = 1;
- //判断兼容性
- if (!check_textRender(this.canvas[0])) {
- //console.log('loading stroke text' + __baseurl__ + "js/strokeText.js");
- //include(__baseurl__ + "js/strokeText.js");
- }
- this.plot = {};
- this.plotindex = {};
- this.plotArea = {};
- this.plotArea[this.config.mainName] = true;
- this.viewconfig = [];
- //注册主图
- this.registerPlot(this.config.mainName, null, true, this.controller.ind[this.config.mainName].param);
- }
- View.prototype.deinit = function() {
- }
- View.prototype.setPlotArea = function(fixd) {
- if (this.plot_area != window) {
- var pa = $(this.plot_area);
- this.plotWidth = pa.attr("fw") ? pa.attr("fw") : pa.width();
- this.plotHeight = pa.attr("fh") ? pa.attr("fh") : pa.height();
- $("#plot_area").height(this.plotHeight);
- $("#plot_area").width(this.plotWidth);
- $("#plot_content").show();
- return;
- }
- if (!fixd) {
- fixd = {};
- fixd.x = 10;
- fixd.y = 3;
- if (this.config.browser == "ie" && this.config.bversion[0] >= 8) {
- fixd.y = 8;
- }
- }
- $("#plot_content").hide();
- this.plotWidth = $(this.plot_area).width() - fixd.x;
- this.offsetHeight = $("#plot_area").offset().top;
- this.plotHeight = $(this.plot_area).height() - this.offsetHeight - fixd.y;
- $("#plot_area").height(this.plotHeight + 1);
- $("#plot_area").width($(this.plot_area).width());
- if (this.plotWidth < 200) this.plotWidth = 200;
- if (this.plotHeight < 100) this.plotHeight = 100;
- $("#plot_content").show();
- }
- View.prototype.setWidth = function(w) {
- if (!w) {
- w = this.plotWidth;
- }
- for (var i = 0; i < this.config.Global.maxCanvasCount; i++) {
- set_width(this.canvas[i], w);
- set_width(this.canvasBG[i], w);
- set_width(this.canvasFront[i], w);
- set_width(this.resize[i], w);
- this.grid[i].setWidth(w);
- }
- }
- View.prototype.setHeight = function() {
- // console.log()
- for (var i = 0; i < this.config.Global.maxCanvasCount; i++) {
- set_height(this.canvas[i], 1);
- }
- }
- View.prototype.init = function() {
- //注册全局事件
- //resize 和 canvas 的事件放在grid中
- this.lastW = $(this.plot_area).width();
- this.lastH = $(this.plot_area).height();
- $(document).bind("keydown", this, this.keydown);
- $(document).bind("keyup", this, this.keyup);
- $(this.plot_area).bind("resize", this, this.resizeWindow);
- var _this = this;
- _this.wheelEvent = new IntervalEvent(3,
- function(controller) {
- var mainName = controller.config.mainName;
- var one = controller.view.plot[mainName].getOneSize();
- var offset = Math.round(-this.value * 40 / one);
- controller.startOffset(offset);
- controller.draw();
- }
- );
- this.controller.addIntervalEvent("wheelEvent", _this.wheelEvent);
- var wheelobj;
- if (this.plot_area == window) {
- wheelobj = document;
- } else {
- wheelobj = this.plot_area;
- }
- $(wheelobj).mousewheel(
- function(event, delta)
- {
- var e = window.event||event;
- console.log("滚轮事件:"+e)
- if (e.wheelDelta == 120) {
- _this.controller.zoomIn();
- return true;
- } else if (e.wheelDelta == -120) {
- _this.controller.zoomOut();
- return true;
- }
- if (e.detail == -3) {
- _this.controller.zoomIn();
- return true;
- } else if (e.detail == 3) {
- _this.controller.zoomOut();
- return true;
- }
- if (e.originalEvent.deltaY == -3) {
- _this.controller.zoomIn();
- return true;
- } else if (e.originalEvent.deltaY == 3) {
- _this.controller.zoomOut();
- return true;
- }
- //return false;
- }
- );
- //注册十字光标事件
- }
- View.prototype.registerPlot = function(name, index, has_plot_area, param) {
- if (this.config[name] && !this.plot[name]) {
- var Plot = this.config[name].plot;
- var index = this.getCanvas(name, index);
- this.plot[name] = new Plot(this, this.grid[index], name);
- if (param) this.plot[name].setParam(param);
- if(index==0){
- this.canvas[index].css('display', 'block');
- this.canvasBG[index].css('display', 'block');
- this.canvasFront[index].css('display', 'block');
- // this.canvas[index].css('padding-top', '60px');
- // this.canvasBG[index].css('padding-top', '60px');
- // this.canvasFront[index].css('padding-top', '60px');
-
- }
- else{
- this.canvas[index].css('display', 'block');
- this.canvasBG[index].css('display', 'block');
- this.canvasFront[index].css('display', 'block');
- // this.canvas[index].css('padding-top', '10px');
- // this.canvasBG[index].css('padding-top', '10px');
- // this.canvasFront[index].css('padding-top', '10px');
- }
-
- this.canvasContainer[index].css('display', 'block');
- this.resize[index].show();
- this.plotindex[name] = index;
- if (has_plot_area) {
- this.plotArea[name] = has_plot_area;
- }
- this.grid[index].addPlot(name, this.plot[name]);
- this.setLast();
- }
- }
- View.prototype.isSeperatePlot = function(name) {
- if (!this.config.Global.View[name]) {
- return null;
- }
- return this.config.Global.View[name].sep;
- }
- View.prototype.setLast = function() {
- for (var i = 0; i < this.canvasActiveCount; i++) {
- this.grid[i].clearLast();
- }
- this.grid[this.canvasActiveCount - 1].setLast();
- }
- View.prototype.unregisetPlot = function(name) {
- this.plot[name] = null;
- this.plotindex[name] = null;
- this.setLast();
- var index = this.plotindex[name];
- this.grid[index].removePlot(name);
- }
- View.prototype.draw = function() {
- //draw grid
- //绘制Y轴
- for (var i = 0; i < this.canvasActiveCount; i++) {
- if (is_object(this.grid[i])) {
- if (this.data[i].axis.y.axis) {
- this.grid[i].drawBg();
- this.grid[i].drawY();
- this.grid[i].drawX(this.axis[0]);
- //画canvas分割折线
- var ctx = this.grid[i].ctx;
- if(i != this.canvasActiveCount - 1){
- drawLever(ctx,this.grid[i].xEnd.x-20,this.grid[i].yEnd.y-2,'#999',10,10);
- drawLever(ctx,this.grid[i].xEnd.x-20,this.grid[i].yEnd.y+2,'#999',10,-10);
- }
-
- //绘制底部线条
- // this.grid[i].drawLine(this.ctx, data.x, data.y, color);
- //this.grid[i].drawBoder(this.axis[0]);
- } else {
- this.grid[i].drawBg();
- this.grid[i].drawX(this.axis[0]);
- // drawLever(ctx,this.grid[i].xEnd.x,this.grid[i].yEnd.y,'#999',10,10);
- //绘制底部线条
- //this.grid[i].drawBoder(this.axis[0]);
- }
- }
- if (i == this.canvasActiveCount - 1) {
- //画线
- //绘制底线没有其他图层了画线
- var ctx = this.grid[i].ctx;
- ctx.beginPath();
- ctx.moveTo(this.grid[i].O.x, this.grid[i].yEnd.y+20 - this.grid[i].O.y);
- ctx.lineTo(this.grid[i].xEnd.x, this.grid[i].yEnd.y+20 - this.grid[i].O.y);
- ctx.closePath();
- ctx.lineWidth = 0.3;
- ctx.strokeStyle = "#fff";
- ctx.stroke();
- }
- }
- //绘制x。目前,x只需要绘制最后一个图形x轴部分
- //开始绘制每个图形
- for (i = 0; i < this.data.length; i++) {
- var plot = this.data[i].data;
- var text = "";
- for (var key in plot) {
- if (is_object(plot[key])) {
- //坐标轴的选项对绘图中的 转换是有用的。在通过数字 转换
- //成固定格式的数据的时候非常有用。比如时间转换,4舍五入等。
- if (plot[key].x && plot[key].x.length > 0) {
- this.plot[key].draw(plot[key]);
- //顶部内容 update by fangxiao from 2016/6/29/17:47
- // text += "[" + this.plot[key].getShowName() + " " + this.plot[key].lastDataShow() + "] ";
- }
- }
- }
- if (text.length > 0) {
- // console.log(text);
- this.grid[i].writeHeadText(text);
- }
- }
- }
- //获取坐标轴的配置:
- //
- //1.附图,那么要和主图对应,这样时间应该是通过查询产生的。所以,不需要提供配置。
- //2.计算x轴,完全是利用主图的配置,这样计算主图的配置就可以了。
- //
- View.prototype.getAxisConfig = function() {
- var one = this.plot[this.config.mainName].getOneSize(); //获取一个点占用的点数
- var nx = this.config.Global.View[this.config.mainName].NXPixel; //x轴的数目推荐坐标的数目
- var ny = this.config.Global.View[this.config.mainName].NYPixel; //x轴的数目推荐坐标的数目
- var viewconfig = [];
- for (var i = 0; i < this.canvasActiveCount; i++) {
- if (is_object(this.grid[i])) {
- viewconfig[i] = {};
- var area = this.grid[i].getPlotArea();
- var plotnum = Math.ceil((area.x.beg - area.x.end) / one);
- viewconfig[i].plotnum = plotnum;
- viewconfig[i].one = one;
- viewconfig[i].x = {};
- viewconfig[i].x.n = Math.round((area.x.beg - area.x.end) / nx);
- viewconfig[i].x.beg = area.x.beg;
- viewconfig[i].x.end = area.x.end;
- viewconfig[i].y = {};
- viewconfig[i].y.n = Math.round((area.y.beg - area.y.end) / ny);
- viewconfig[i].y.beg = area.y.beg;
- viewconfig[i].y.end = area.y.end;
- }
- }
- for (var key in this.plotindex) {
- var index = this.plotindex[key];
- if (index === null) continue;
- if (!viewconfig[index]) continue;
- if (typeof viewconfig[index].plot === "undefined") viewconfig[index].plot = [];
- viewconfig[index].plot.push(key);
- }
- this.viewconfig = viewconfig;
- return viewconfig;
- }
- View.prototype.getAxis = function(name) {
- var index = this.plotindex[name];
- return this.axis[index];
- }
- View.prototype.getCanvas = function(name, index) {
- //为指标和主函数分配canvas.
- var plotconfig = this.config.Global.View;
- //判断是否要增加canvas
- if (name == this.config.mainName) {
- this.grid[0].setHeight(this.plotHeight);
- }
- if ((typeof index !== "undefined") && index !== null && index < this.canvasActiveCount) {
- return index;
- }
- if (!plotconfig[name] || !plotconfig[name].sep) {
- return 0;
- }
- var h = this.getUnitHeight(name);
- // console.log("getUnitHeight:"+h);
- var index = this.setExistPlotHeight(h);
- // console.log("getUnitHeight:"+h * plotconfig[name].height);
- this.grid[index++].setHeight(h * plotconfig[name].height);
- this.canvasActiveCount = index;
- return index - 1;
- }
- //设置已经存在的图像的高度
- View.prototype.setExistPlotHeight = function(unit_h) {
- //设置所有的canvas 的高度为0
- var plotconfig = this.config.Global.View;
- for (i = 0; i < this.grid.length; i++) {
- this.grid[i].setHeight(1);
- }
- this.grid[0].setHeight(unit_h);
- var index = 1;
- //返回新加入名称的canvas
- for (var key in this.plot) {
- if (is_object(this.plot[key])) {
- if (key == this.config.mainName) continue; //主图, 直接pass
- if (!plotconfig[key]) continue; //没有配置,直接pass
- if (plotconfig[key].sep) { //分离
- // console.log("unit_h * plotconfig[key].height:"+unit_h * plotconfig[key].height)
- this.grid[index++].setHeight(unit_h * plotconfig[key].height);
- }
- }
- }
- return index;
- //新图加在末尾
- }
- //新家图像
- View.prototype.getUnitHeight = function(newname) {
- var x = 1;
- var plotconfig = this.config.Global.View;
- for (var key in this.plot) {
- if (is_object(this.plot[key])) {
- if (key == this.config.mainName) continue; //主图, 直接pass
- if (!plotconfig[key]) continue; //没有配置,直接pass
- if (!this.plotArea[key]) {
- continue;
- }
- if (plotconfig[key].sep) { //分离
- x += plotconfig[key].height;
- }
- }
- }
- if (newname) {
- x += plotconfig[newname].height;
- }
- var h = this.plotHeight * (1 / x);
- return h;
- }
- View.prototype.clearData = function() {
- this.data = [];
- //清除原来的main值
- this.axis[0].main = null;
- for (var i = 0; i < this.canvasActiveCount; i++) {
- this.axis[i].clearData();
- }
- }
- View.prototype.updateData = function(data, index) {
- var axis = this.axis[index];
- axis.setViewConfig(this.viewconfig[index]);
- axis.setData(data);
- this.data[index] = axis.getData();
- }
- //这里的PlotGrid 的名字是暂时使用的,具体什么名字还没有取好
- //因为事件主要是在plotgrid中处理,所以,我用了这个名字
- View.prototype.keydown = function(event) {
- var _this = event.data;
- PlotGrid.setMoveInterval("key", _this.grid[0]);
- debug("keydown");
- if (event.keyCode == Key.KEY_NEXT) {
- var offset = _this.controller.startSet("Next");
- PlotGrid.moveQueue.push(offset);
- return false;
- } else if (event.keyCode == Key.KEY_PREV) {
- var offset = _this.controller.startSet("Prev");
- PlotGrid.moveQueue.push(offset);
- return false;
- } else if (event.keyCode == Key.KEY_PAGE_DOWN) {
- var offset = _this.controller.startSet("PageDown");
- PlotGrid.moveQueue.push(offset);
- return false;
- } else if (event.keyCode == Key.KEY_PAGE_UP) {
- var offset = _this.controller.startSet("PageUp");
- PlotGrid.moveQueue.push(offset);
- return false;
- } else if (event.keyCode == Key.KEY_HOME) {
- var offset = _this.controller.startSet("Home");
- PlotGrid.moveQueue.push(offset);
- return false;
- } else if (event.keyCode == Key.KEY_END) {
- var offset = _this.controller.startSet("End");
- PlotGrid.moveQueue.push(offset);
- return false;
- } else if (event.keyCode == Key.KEY_UP) {
- _this.controller.zoomIn();
- return false;
- } else if (event.keyCode == Key.KEY_DOWN) {
- _this.controller.zoomOut();
- return false;
- }
- }
- View.prototype.keyup = function(event) {
- debug("keyup");
- var _this = event.data;
- PlotGrid.clearMoveInterval(_this.grid[0]);
- }
- View.prototype.resizeGrid = function(offset, index) {
- debug("set resize offset " + offset);
- if (offset == 0) return;
- var grid1 = this.grid[index];
- var grid2 = this.grid[index + 1];
- // if(index==0){
- // var margin1 = grid1.marginTop[grid1.TOP] + grid1.marginTop[grid1.BOTTOM];
- // var margin2 = grid2.marginTop[grid2.TOP] + grid2.marginTop[grid2.BOTTOM];
- // }else{
- // var margin1 = grid1.margin[grid1.TOP] + grid1.margin[grid1.BOTTOM];
- // var margin2 = grid2.margin[grid2.TOP] + grid2.margin[grid2.BOTTOM];
- // }
- var margin1 = grid1.margin[grid1.TOP] + grid1.margin[grid1.BOTTOM];
- var margin2 = grid2.margin[grid2.TOP] + grid2.margin[grid2.BOTTOM];
- if (!grid1 || !grid2) return;
- if (offset > 0 && grid2.height - margin2 - offset <= 5) {
- offset = grid2.height - 5 - margin2;
- }
- if (offset < 0 && grid1.height - margin1 + offset <= 5) {
- offset = -(grid1.height - 5 - margin1);
- }
- grid1.setHeight(grid1.height + offset);
- grid2.setHeight(grid2.height - offset);
- }
- View.prototype.resizeWindow = function(e) {
- var _this = e.data;
- if (!_this.lastW) {
- return;
- }
- if (_this.lastW == $(window).width() && _this.lastH == $(window).height()) {
- return;
- }
- //debugx("resize0: " + _this.lastW + "," + _this.lastH);
- //debugx("resize1: " + $(window).width() + "," + $(window).height());
- _this.setPlotArea();
- _this.setWidth();
- //_this.setExistPlotHeight(_this.getUnitHeight());
- //debugx("resize2: " + $(window).width() + "," + $(window).height());
- //保存最新的window值
- _this.lastW = $(window).width();
- _this.lastH = $(window).height();
- _this.controller.draw();
- }
- function Win(title, width, height, opt) {
- this.title = title;
- this.width = width ? width : 400;
- this.height = height ? height : 300;
- if (!opt) opt = {};
- this.autoclose = opt.autoclose ? opt.autoclose : 0;
- this.left = opt.left ? opt.left : -1; //-1表示默认向左,其实就是窗口居中
- this.top = opt.top ? opt.top : -1; //top 的意义和 left相同
- this.config = Config.getInstance();
- this.tpl = $(this.config.Global.WinTplID);
- this.cache = {};
- }
- Win.zindex = 1000;
- Win.prototype.getHtml = function() {
- var html = this.tpl.html();
- html = html.replace("{|$title|}", this.title);
- html = html.replace("{|$autoclose|}", this.autoclose);
- return html;
- }
- Win.prototype.createWindow = function(targetID) {
- if ($("#" + targetID).length) {
- return;
- }
- this.conf = this.config.Global.Win[targetID];
- var html
- var newhtml
- if (targetID == "__order__") {
- this.win = $("<div id='" + targetID + "'> </div><input type=\"hidden\" id=\"ordershow\" value=\"0\" />");
- html = this.getHtml();
- newhtml = html.replace("class=\"content\">", "id='popwin' class=\"content\">");
- } else {
- this.win = $("<div id='" + targetID + "'> </div>");
- newhtml = this.getHtml();
- }
- this.targetID = targetID;
- $("body").append(this.win);
- this.win.html(newhtml);
- this.dragArea = this.getClassQuery("popTop");
- this.win.dragdrop(this.dragArea);
- this.setWidth(this.width).setHeight(this.height);
- this.win.css("position", "absolute");
- this.win.css("z-index", Win.zindex);
- this.setPotion();
- Win.zindex++;
- this.addTab();
- this.addEvent();
- this.clickFirst(this.getClassQuery("cc"));
- this.win.hide();
- }
- Win.prototype.addTab = function() {
- var query = this.getClassQuery("cc");
- query = $(query);
- for (var key in this.conf.tab) {
- if (typeof this.conf.tab[key] == "string") {
- query.append('<li name="' + key + '"><a href="javascript:;">' + this.conf.tab[key] + '</a></li>');
- }
- }
- }
- Win.prototype.clickFirst = function(query) {
- query = $(query);
- query.children().first().click();
- }
- Win.prototype.setPotion = function() {
- if (this.top == -1) {
- var top = Math.max(0, ($(window).height() - this.height) / 2);
- }
- if (this.left == -1) {
- var left = Math.max(0, ($(window).width() - this.width) / 2);
- }
- this.win.css("top", top + "px");
- this.win.css("left", left + "px");
- }
- Win.prototype.setWidth = function(w) {
- var mainContainer = this.getClassQuery("windowBody");
- $(mainContainer).width(w);
- return this;
- }
- Win.prototype.setHeight = function(h) {
- var mainContainer = this.getClassQuery("windowBody");
- $(mainContainer).height(h);
- return this;
- }
- Win.prototype.getClassQuery = function(classname) {
- var targetID = this.targetID;
- if (targetID.charAt(0) != "#") {
- targetID = "#" + this.targetID
- }
- if (classname.charAt(0) != ".") {
- classname = " ." + classname;
- }
- var query = targetID + classname;
- return query
- }
- Win.prototype.show = function() {
- this.win.show();
- this.win.css("z-index", Win.zindex++);
- }
- Win.prototype.addEvent = function() {
- //close
- var query = this.getClassQuery("adel");
- var _this = this;
- $(query).click(
- function() {
- $("#tool_dl").find("li[name=none]").click();
- _this.win.hide();
- }
- );
- //tab
- var query = this.getClassQuery("cc");
- var _this = this;
- $(query).children().click(function(e) {
- $(query).children().removeClass("current");
- $(this).addClass("current");
- if (_this.load) {
- _this.load($(this).attr("name"));
- }
- });
- }
- function WinAjax(name, title, width, height, opt) {
- sup(this, title, width, height, opt);
- }
- ClassExtend(WinAjax, Win);
- WinAjax.prototype.load = function(name, flag) {
- //这里可以根据name 做一些特殊的处理。
- //但是,目前,我们采用的是 ajax 从服务器下载相关的配置
- this.tab = name;
- this.flag = flag;
- var query = this.getClassQuery("content");
- if (this.cache[name + flag]) {
- $(query).html(this.cache[name + flag]);
- return;
- }
- var api
- if (name == "order") {
- api = this.config.Global.WinOrder;
- } else {
- api = this.config.Global.WinAPI;
- }
- var _this = this;
- if (this.ajax) {
- this.ajax.abort();
- }
- var param = { win: this.targetID, tab: name, __tmp: Math.random() };
- if (this.flag) {
- param.flag = this.flag;
- }
- if (name == "order") {
- this.ajax = $.get(api, function(data) {
- //_this.cache[data.tab + data.flag] = data.data;
- $(query).html(data);
- }, "html");
- } else {
- this.ajax = $.get(api, param, function(data) {
- _this.cache[data.tab + data.flag] = data.data;
- $(query).html(data.data);
- }, "jsonp");
- }
- }
- function ShapeArrow(ctx, width, height, opt) {
- sup(this, ctx, width, height, opt);
- }
- ClassExtend(ShapeArrow, Shape);
- ShapeArrow.prototype.arrowhalf = function(ctx, width, height) {
- var pi = Math.PI;
- ctx.save();
- ctx.translate(0, -height);
- ctx.beginPath();
- ctx.moveTo(0, 0);
- ctx.lineTo(width, 0);
- var head = (0.618) * height;
- ctx.lineTo(width, head);
- if (width <= 3) {
- var add = 3;
- } else {
- var add = width / 0.618;
- }
- ctx.lineTo(width + add, head - width * Math.tan(pi / 3));
- ctx.lineTo(0, height);
- ctx.closePath();
- ctx.stroke();
- ctx.fill();
- ctx.restore();
- }
- ShapeArrow.prototype.basic_arrow = function(ctx, width, height) {
- ctx.save();
- this.arrowhalf(ctx, width, height);
- ctx.transform(-1, 0, 0, 1, 0, 0);
- this.arrowhalf(ctx, width, height);
- ctx.restore();
- }
- //箭头的定位在于两个方面。一个方面是旋转的角度,一个是箭头指向的位置
- ShapeArrow.prototype.draw = function(point) {
- var ctx = this.ctx;
- var cta = this.cta;
- ctx.save();
- ctx.translate(point.x, point.y);
- ctx.rotate(cta);
- ctx.strokeStyle = this.boder;
- ctx.fillStyle = this.fill;
- this.basic_arrow(ctx, this.width, this.height);
- ctx.restore();
- }
- function PlotAdvFractals(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(PlotAdvFractals, Plot);
- PlotAdvFractals.prototype.draw = function(data) {
- var color;
- if (this.param.lineColor) {
- color = this.param.lineColor;
- } else {
- color = this.conf.lineColor;
- }
- /* for(var i = 0 ;i<data.x.length ;i++){
- if(data.y[i][0] ==-1){
- writeText(this.ctx, new Point(data.x[i] , data.y[i][1]+12), "d", color[0], this.param.font);
- }else if(data.y[i][0] == 1){
- writeText(this.ctx, new Point(data.x[i] , data.y[i][1]-12), "u", color[1], this.param.font);
- }
- }*/
- var y1 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][1];
- }
- drawLine(this.ctx, data.x, y1, color[0]);
- }
- function Plotadx(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotadx, Plot);
- Plotadx.prototype.draw = function(data) {
- var color;
- if (this.param.lineColor) {
- color = this.param.lineColor;
- } else {
- color = this.conf.lineColor;
- }
- var y1 = []
- var y2 = []
- var y3 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][0];
- y2[i] = data.y[i][1];
- y3[i] = data.y[i][2];
- }
- drawLine(this.ctx, data.x, y1, color[0]);
- drawLine(this.ctx, data.x, y2, color[1]);
- drawLine(this.ctx, data.x, y3, color[2]);
- }
- function Plotatr(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotatr, Plot);
- Plotatr.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color;
- } else {
- color = this.conf.lineColor;
- }
- var y1 = []
- var y2 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][0];
- y2[i] = data.y[i][1];
- }
- drawLine(this.ctx, data.x, y1, color[0]);
- drawLine(this.ctx, data.x, y2, color[1]);
- }
- function Plotbdensity(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotbdensity, Plot);
- Plotbdensity.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.lineColor) {
- color = this.param.lineColor;
- } else {
- color = this.conf.lineColor;
- }
- for (var i = 0; i < data.y.length; i++) {
- if (data.y[i][2] != 0) {
- writeText(this.ctx, new Point(data.x[i], data.y[i][0]), "~", color[0], this.param.font)
- writeText(this.ctx, new Point(data.x[i], data.y[i][1]), "*", color[0], this.param.font)
- }
- if (data.y[i][6] != 0) {
- writeText(this.ctx, new Point(data.x[i], data.y[i][4]), "~", color[1], this.param.font)
- writeText(this.ctx, new Point(data.x[i], data.y[i][5]), "*", color[1], this.param.font)
- }
- if (data.y[i][10] != 0) {
- writeText(this.ctx, new Point(data.x[i], data.y[i][8]), "~", color[2], this.param.font)
- writeText(this.ctx, new Point(data.x[i], data.y[i][9]), "*", color[2], this.param.font)
- }
- }
- }
- function PlotBolling(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(PlotBolling, Plot);
- PlotBolling.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color.split("-");
- } else {
- color = this.conf.lineColor;
- }
- var y1 = []
- var y2 = []
- var y3 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][0];
- y2[i] = data.y[i][1];
- y3[i] = data.y[i][2];
- }
- drawLine(this.ctx, data.x, y1, color[0]);
- drawLine(this.ctx, data.x, y2, color[1]);
- drawLine(this.ctx, data.x, y3, color[2]);
- }
- function PlotBollingDesity(view, grid, name) {
- sup(this, view, grid, name);
- this.color = ["red", "rgb(255, 128, 128)", "red", "rgb(255, 128, 128)",
- "green", "rgb(128, 255, 128)", "green", "rgb(128, 255, 128)",
- "yellow", "rgb(128, 255, 128)", "yellow", "rgb(128, 255, 128)",
- "Cyan", "Cyan",
- "Blue", "Blue",
- "Fuchsia", "Fuchsia",
- ];
- }
- ClassExtend(PlotBollingDesity, Plot);
- PlotBollingDesity.prototype.draw = function(data) {
- this.X = data.x;
- this.Y = data.y;
- this.setMaxMinDesity();
- this.getPlotArea();
- this.box = this.view.plot[this.config.mainName].getBoxSize();
- this.left = this.view.plot[this.config.mainName].getBoxLeft();
- for (var i = 0; i < this.X.length; i++) {
- this.drawOne(this.X[i], this.Y[i]);
- }
- }
- PlotBollingDesity.prototype.setMaxMinDesity = function() {
- var min = Infinity
- var max = -Infinity;
- var y = this.Y;
- for (var i = 0; i < y.length; i++) {
- for (var j = 1; j < y.length; j += 2) {
- if (y[i][j] == -1) {
- continue;
- }
- if (max < y[i][j]) {
- max = y[i][j];
- }
- if (min > y[i][j]) {
- min = y[i][j]
- }
- }
- }
- this.maxD = max;
- this.minD = min;
- }
- PlotBollingDesity.prototype.drawOne = function(time, data) {
- var price, desity, color, left, top;
- try {
- for (var i = 0; i < 16; i += 2) {
- price = data[i];
- if (price == -1 || data[i + 1] == -1) {
- continue;
- }
- desity = this.getDesity(data[i + 1]);
- color = this.color[i / 2];
- this.ctx.fillStyle = color;
- left = time - this.left;
- top = price - desity;
- if (top < this.top || top > this.bottom) {
- continue;
- }
- this.ctx.fillRect(left, top, this.box, desity);
- }
- } catch (e) {}
- }
- PlotBollingDesity.prototype.getDesity = function(d) {
- return (Math.floor(((d - this.minD) / (this.maxD - this.minD)) * 6) + 1);
- }
- PlotBollingDesity.prototype.lastDataShow = function() {
- var data = this.lastData();
- var newdata = [];
- for (var i = 0; i < data.length; i += 2) {
- newdata[i / 2] = data[i];
- }
- return newdata;
- }
- function PlotCandle(view, grid, name) {
- sup(this, view, grid, name);
- //放大缩小尺寸控制更加灵活。采用配置数组的形式
- this.box = [1, 2, 3, 5, 7, 9, 11, 13];
- this.space = [0, 1, 1, 2, 2, 3, 4, 5];
- this.left = [0, 1, 1, 2, 3, 4, 5, 6]
- // this.box = [ 7, 9, 11, 13,15,18,21,23];
- // this.space = [ 2, 3, 4, 5,6,8,9,10];
- // this.left = [ 3, 4, 5, 6,7,9,10,11]
- // this.box = [3, 5, 9, 13, 17, 19, 23, 25];
- // this.space = [1, 2, 3, 5, 7, 8, 10, 11];
- // this.left = [1, 2, 4, 6, 8, 9, 11, 12]
- }
- ClassExtend(PlotCandle, Plot);
- PlotCandle.prototype.zoomIn = function() {
- if (this.conf.box_pixel >= 7 && this.conf.space_pixel >= 7) {
- return;
- }
- if (this.conf.box_pixel < this.conf.space_pixel) {
- this.conf.box_pixel++;
- } else if (this.conf.box_pixel > this.conf.space_pixel) {
- this.spaceOffset(1);
- } else {
- this.conf.box_pixel++;
- }
- }
- PlotCandle.prototype.spaceOffset = function(offset) {
- var prev = this.space[this.conf.space_pixel];
- this.conf.space_pixel = this.conf.space_pixel + offset;
- var current = this.space[this.conf.space_pixel];
- if (prev == current) {
- this.conf.box_pixel = this.conf.box_pixel + offset;
- }
- }
- PlotCandle.prototype.zoomOut = function() {
- if (this.conf.box_pixel <= 0 && this.conf.space_pixel <= 0) {
- return;
- }
- if (this.conf.box_pixel < this.conf.space_pixel) {
- this.spaceOffset(-1);
- } else if (this.conf.box_pixel > this.conf.space_pixel) {
- this.conf.box_pixel--;
- } else {
- this.spaceOffset(-1);
- }
- this.conf.box_pixel = this.conf.box_pixel < 0 ? 0 : this.conf.box_pixel;
- }
- PlotCandle.prototype.getOneSize = function() {
- return this.box[this.conf.box_pixel] + 2*this.space[this.conf.space_pixel];
- }
- PlotCandle.prototype.getBoxLeft = function() {
- return this.left[this.conf.box_pixel];
- }
- PlotCandle.prototype.getBoxSize = function() {
- return this.box[this.conf.box_pixel];
- }
- PlotCandle.prototype.draw = function(data) {
- this.data = data;
- this.X = data.x;
- this.Y = data.y;
- this.xunit = this.data.xunit;
- this.yunit = this.data.yunit;
- this.closePriceFlag();
- var width = this.box[this.conf.box_pixel];
- var left = this.left[this.conf.box_pixel];
- if (width > 2) {
- width--;
- }
- this.config.Global.boxwidth = width;
- //最高最低点标签
- var maxy=this.Y[this.data.maxIndex][1]-5;
- var miny=this.Y[this.data.minIndex][2]+15;
- writeText(this.ctx,new Point(this.X[this.data.maxIndex],maxy),parseFloat(this.data.maxY).toFixed(3), "#ff6600", "#fff");
- writeText(this.ctx,new Point(this.X[this.data.minIndex],miny),parseFloat(this.data.minY).toFixed(3), "#ff6600", "#fff");
- //画个分界线
- for (var i = 0; i < this.X.length; i++) {
- this.drawOne(this.X[i], this.Y[i], width, left);
- // var ohlc=this.Y[i];
- // var maxy=parseFloat(GetText(ohlc[1],this.yunit)).toFixed(3);
- // var miny=parseFloat(GetText(ohlc[2],this.yunit)).toFixed(3);
- // if(maxy==this.data.maxY){
- // writeText(this.ctx, new Point(this.X[i] + this.conf.ledgeLen + 2, this.Y[i]), this.data.maxY, this.conf.fontColor, this.conf.font);
- // }
- // if(miny==this.data.minY){
- // writeText(this.ctx, new Point(this.X[i] + this.conf.ledgeLen + 2, this.Y[i]), this.data.maxY, this.conf.fontColor, this.conf.font);
- // }
- }
- //console.log(data.text);
- }
- //按照道理,这些数据都应该是计算好了之后,
- //会送给客户端的。这个部分,还是要对数据层进行改进
- //才能比较好的封装。现在暂时这样处理。
- PlotCandle.prototype.closePriceFlag = function() {
- //view 一般不调用model的数据。因为,这样使得view 和 model层直接联系起来。
- //但是,我们知道,我们的Controller 是一般性的分发。
- //而且这样的一般性的分发在大多数情况下面是够用的。
- //出于这样的考虑,我们允许在view里面调用model,因为,的确很多时候需要这样的调用。
- //每个图都有对应的 model plot
- var close_price = this.view.model.getDataReader(this.name).close(0);
- this.priceFlag(close_price, this.conf.close);
- }
- PlotCandle.prototype.over = function(x, y) {
- //查找最接近的
- // console.log("1");
- if (!this.X || !this.Y) return;
- var index = find_near(this.X, x);
- if (index == -1) return false;
- if (Math.abs(this.X[index] - x) > this.getOneSize()) {
- return false;
- }
- var ohlc = this.Y[index];
- // console.log("text PlotCandle");
- //找到此金额的y轴坐标
- //if (ohlc[Data.HIGH] - this.config.Global.overPadding <= y && ohlc[Data.LOW] + this.config.Global.overPadding >= y) {
- var findTime = this.axis.getXValue(x, PlotGrid.NEAR);
- if (findTime === false) return;
- var cdata = this.view.model.getDataByTime(this.name, findTime, "candle");
- if (!cdata) return false;
- var time = cdata.time;
- var ohlc = cdata.data;
- var yunit = this.axis.viewconfig.y.axis_option.unit;
- var fallOrDegrees = parseFloat(GetText(ohlc[Data.CLOSE], yunit) - GetText(ohlc[Data.OPEN], yunit)) / parseFloat(GetText(ohlc[Data.OPEN], yunit));
- var fallOrDegrees = fallOrDegrees.toFixed(3);
-
- $(".freetimebox li:first-child").text("时间:"+time);
- $(".freetimebox li:nth(1)").text("开:"+GetText(ohlc[Data.OPEN], yunit));
- $(".freetimebox li:nth(2)").text("高:"+GetText(ohlc[Data.HIGH], yunit));
- $(".freetimebox li:nth(3)").text("低:"+GetText(ohlc[Data.LOW], yunit));
- $(".freetimebox li:nth(4)").text("收:"+GetText(ohlc[Data.LOW], yunit));
- $(".freetimebox li:nth(4)").text("收:"+GetText(ohlc[Data.CLOSE], yunit));
- $(".freetimebox li:nth(5)").text("涨幅:"+fallOrDegrees);
- $(".freetimebox li:nth(6)").text("振幅:"+fallOrDegrees);
- $(".freetimebox li:nth(7)").text("量:"+GetText(ohlc[Data.VOLUMES], yunit));
- $('.freetimebox').show();
- //timeLine Data
- // timelineData(time, GetText(ohlc[Data.OPEN], yunit), GetText(ohlc[Data.HIGH], yunit), GetText(ohlc[Data.LOW], yunit), GetText(ohlc[Data.CLOSE], yunit), GetText(ohlc[Data.VOLUMES], yunit));
- // console.log("text PlotCandle");
- // return time + "<br/>" + "O: " + GetText(ohlc[Data.OPEN], yunit) + "<br />" + "H: " + GetText(ohlc[Data.HIGH], yunit) + "<br />" + "L : " + GetText(ohlc[Data.LOW], yunit) + "<br />" + "C: " + GetText(ohlc[Data.CLOSE], yunit) + "<br />" + "V: " + GetText(ohlc[Data.VOLUMES], yunit) + "<br />";
- // } else {
- // return false;
- // }
- }
- PlotCandle.prototype.drawOne = function(time, ohlc, width, left) {
- var ctx = this.ctx;
- var open = ohlc[Data.OPEN];
- var high = ohlc[Data.HIGH];
- var low = ohlc[Data.LOW];
- var close = ohlc[Data.CLOSE];
- time += 0.5;
- open += 0.5;
- high += 0.5;
- low += 0.5;
- close += 0.5;
- if (high == low) {
- //画个横线就可以了
- ctx.strokeStyle = this.conf.os_border_color;
- ctx.beginPath();
- ctx.moveTo(time - left, open);
- ctx.lineTo(time + width, open);
- ctx.stroke();
- return;
- }
- if (open < close) {
- var up = open;
- var down = close;
- var fill = this.conf.open_big_color;
- var border = this.conf.ob_border_color;
- } else {
- var up = close;
- var down = open;
- var fill = this.conf.open_small_color;
- var border = this.conf.os_border_color;
- }
- ctx.strokeStyle = border;
- ctx.beginPath();
- ctx.moveTo(time, high);
- ctx.lineTo(time, low);
- ctx.stroke();
- if (this.conf.space_pixel > 0) {
- ctx.fillStyle = fill;
- ctx.fillRect(time - left, up, width, down - up);
- ctx.strokeRect(time - left, up, width, down - up);
- }
- }
- function PlotFractals(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(PlotFractals, Plot);
- PlotFractals.prototype.draw = function(data) {
- var color;
- if (this.param.lineColor) {
- color = this.param.lineColor;
- } else {
- color = this.conf.lineColor;
- }
- /* for(var i = 0 ;i<data.x.length ;i++){
- if(data.y[i][0] ==-1){
- writeText(this.ctx, new Point(data.x[i] , data.y[i][1]+12), "d", color[0], this.param.font);
- }else if(data.y[i][0] == 1){
- writeText(this.ctx, new Point(data.x[i] , data.y[i][1]-12), "u", color[1], this.param.font);
- }
- }*/
- var y1 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][1];
- }
- drawLine(this.ctx, data.x, y1, color[0]);
- }
- //grid 是一个令人纠结的类,他是图形的一部分,各种图形都在grid上进行绘制
- function PlotGrid(view, index) {
- this.TOP = 0;
- this.RIGHT = 1;
- this.BOTTOM = 2;
- this.LEFT = 3;
- this.index = index;
- this.view = view;
- this.axis = this.view.axis[index];
- this.canvas = $(this.view.canvas[index]);
- this.canvasBG = $(this.view.canvasBG[index]);
- this.canvasFront = $(this.view.canvasFront[index]);
- this.canvasContainer = $(this.view.canvasContainer[index]);
- this.resize = this.view.resize[index];
- this.controller = this.view.controller;
- this.plot = [];
- if (!this.canvas.get(0).getContext) {
- //debug(Alert(this.canvas.get(0)));
- $("#flash_notify").show();
- alert("not support flash or html5");
- }
- this.ctx = this.canvas.get(0).getContext('2d');
-
- this.ctxBG = this.canvasBG.get(0).getContext('2d');
- this.ctxFront = this.canvasFront.get(0).getContext('2d');
- // if(index==0){
- // this.height = this.canvas.get(0).height-60;
- // }
- // else{
- // this.height = this.canvas.get(0).height-10;
- // }
- this.width = this.canvas.get(0).width;
- this.height = this.canvas.get(0).height;
-
- // var img=document.getElementById("myCanvas");
- // this.ctx.drawImage(pic,0,0,this.width, this.height);
- this.config = Config.getInstance();
- this.conf = this.config.Global.Grid.public; //这个是全局公共配置,更改会引起全局对象的改变。
- //私有变量导出
- this.margin = array_copy(this.conf.margin);
- this.xstyle_axis = this.conf.xstyle_axis;
- this.ystyle_axis = this.conf.ystyle_axis;
- this.setConfig();
- this.addEvent();
- PlotGrid._this = this;
- }
- PlotGrid.FIX_BEG = 1; //开始值固定 (小值)
- PlotGrid.FIX_END = 1 << 1; //结束值固定 (大值)
- PlotGrid.FLOAT = 1 << 2; //浮动计算,可以得到更好的坐标值(浮动20%,得到一些更好的值)
- PlotGrid.GT_ZERO = 1 << 3;
- PlotGrid.TIME = 1 << 4;
- PlotGrid.FIX_PIXEL = 1 << 5;
- PlotGrid.NO_GRID = 1 << 6;
- PlotGrid.NO_AXIS = 1 << 7;
- PlotGrid.NEAR = 1 << 8; //采用寻找最近的点的模式
- PlotGrid.INTERPOLATION = 1 << 9; //采用差值法
- PlotGrid.ADD_YEAR = 1 << 10; //采用差值法
- PlotGrid.prototype.setConfig = function() {
- this.O = new Point(this.margin[this.LEFT], this.margin[this.TOP]);
- this.xEnd = new Point(this.width - this.margin[this.RIGHT], this.margin[this.TOP]);
- this.yEnd = new Point(this.margin[this.LEFT], this.height - this.margin[this.BOTTOM]);
- this.xyEnd = new Point(this.width - this.margin[this.RIGHT], this.height - this.margin[this.BOTTOM]);
- }
- PlotGrid.prototype.setLast = function() {
- this.clearLast();
- if (this.margin[this.BOTTOM] < 20) {
- this.margin[this.BOTTOM] = 20; //又足够的地方写字
- }
- this.resize.hide();
- this.xstyle_axis = this.xstyle_axis & ~PlotGrid.NO_AXIS;
- this.setConfig();
- }
- PlotGrid.prototype.clearLast = function() {
- this.margin = array_copy(this.conf.margin);
- if (!this.xstyle_axis) {
- this.xstyle_axis = 0;
- }
- this.resize.show();
- this.xstyle_axis |= PlotGrid.NO_AXIS;
- this.setConfig();
- }
- PlotGrid.prototype.setHeight = function(h) {
- h = Math.round(h);
- // console.log(h);
- this.height = h;
- // if(this.canvasContainer.attr('id')=="plot_canvas_0"){
- // h=h-60;
- // }
- // else{
- // h=h;
- // }
- // console.log("PlotGrid.prototype.setHeight:"+this.height)
- set_height(this.canvas, h);
- set_height(this.canvasBG, h);
- set_height(this.canvasFront, h);
- set_height(this.canvasContainer, h);
- this.resize.css("top", $(this.canvas).offset().top + h - 4);
- this.setConfig();
- }
- PlotGrid.prototype.setWidth = function(w) {
- this.width = w;
- this.setConfig();
- }
- PlotGrid.prototype.getPlotArea = function() {
- //获取绘图的区域
- var area = { x: {}, y: {} };
- area.y.beg = Math.round(this.xyEnd.y - this.conf.paddingY);
- area.y.end = Math.round(this.xEnd.y);
- area.x.beg = Math.round(this.xyEnd.x - this.conf.paddingX);
- area.x.end = Math.round(this.yEnd.x);
- return area;
- }
- //绘制行,要考虑padding的值 update by fangxiao from 2016/6/29 17:16
- PlotGrid.prototype.drawY = function(axis) {
- if (!axis) axis = this.axis;
- axis_option = axis.viewconfig.y.axis_option;
- var points = axis.viewconfig.y.axis;
- for (var i = 0; i < points.length; i++) {
- var point = new Point(this.O.x, points[i].key);
- var len = this.xEnd.x - this.O.x;
- if (this.conf.ystyle_grid & PlotGrid.NO_GRID) {
- //do noting
- } else {
- drawRow(this.ctx, point, len, this.conf.gridColor, 1);
- }
-
- if (this.ystyle_axis & PlotGrid.NO_AXIS) {
- //do nothing
- } else {
- var point = new Point(this.xEnd.x, points[i].key);
- //drawRow(this.ctx, point, this.conf.ledgeLen, this.conf.axisColor, 1); 去除y轴右侧字旁边的横杆
- var text = this.getText(axis_option.style, points[i].value, axis_option.unit);
- if (i == points.length - 1) //最后一个点,往内缩
- {
- // var ypoint = points[i].key + 12;
- var ypoint = points[i].key;
- } else {
- var ypoint = points[i].key;
- }
- if(i!=0){
- drawDashLine(this.ctx,this.O.x,ypoint,this.xEnd.x,ypoint,2);
- }
-
- writeText(this.ctx, new Point(this.xEnd.x + this.conf.ledgeLen + 2, ypoint), text, this.conf.fontColor, this.conf.font);
- }
- }
- }
- PlotGrid.prototype.drawCrossX = function(x, axis) {
- var len = this.yEnd.y - this.O.y;
- drawCol(this.ctx, new Point(x, this.O.y-15), len+20, this.conf.crossX.lineColor, 0.6);
- if (this.xstyle_axis & PlotGrid.NO_AXIS) {
- //do nothing;
- } else {
- this.writeXLable(x, axis);
- }
- }
- //开始绘制
- PlotGrid.prototype.writeXLable = function(x, axis) {
- if (typeof axis === "undefined") {
- axis = this.axis;
- }
- var value = this.axis.getXValue(x, this.conf.crossXMode, axis);
- if (value === false) return;
- var opt = axis.viewconfig.x.axis_option;
- value = this.getText(opt.style, value, opt.unit);
- writeTextOption(this.ctx, new Point(x - this.conf.crossX.bg.width / 2, this.yEnd.y + this.conf.crossX.bg.height / 2), value, this.conf.crossX);
- }
- //开始绘制
- PlotGrid.prototype.writeYLable = function(y, axis) {
- if (typeof axis === "undefined") {
- axis = this.axis;
- }
- var value = this.axis.getYValue(y, this.conf.crossYMode, axis);
- if (value === false) return;
- var opt = axis.viewconfig.y.axis_option;
- value = this.getText(opt.style, value, opt.unit);
- writeTextOption(this.ctx, new Point(this.xEnd.x, y), value, this.conf.crossY);
- }
- PlotGrid.prototype.writeHeadText = function(text) {
- writeText(this.ctx, new Point(this.O.x + 10, this.O.y + 20), text, this.conf.headText.color, this.conf.headText.font);
- }
- PlotGrid.prototype.drawCrossY = function(y) {
- var len = this.xEnd.x - this.O.x;
- drawRow(this.ctx, new Point(this.O.x, y), len, this.conf.crossY.lineColor, 0.3);
- if (this.ystyle_axis & PlotGrid.NO_AXIS) {
- //do nothing
- } else {
- this.writeYLable(y);
- }
- }
- PlotGrid.prototype.drawX = function(axis) {
- if (!axis) axis = this.axis;
- axis_option = axis.viewconfig.x.axis_option;
- var points = axis.viewconfig.x.axis;
- if (typeof points === "undefined") {
- return;
- }
- for (var i = 0; i < points.length; i++) {
- var point = new Point(points[i].key, this.O.y);
- var len = this.yEnd.y - this.O.y;
- if (this.conf.xstyle_grid & PlotGrid.NO_GRID) {
- //do noting
- } else {
- drawCol(this.ctx, point, len, this.conf.gridColor, 1);
- }
- if (this.xstyle_axis & PlotGrid.NO_AXIS) {
- //do nothing
- } else {
- var point = new Point(points[i].key, this.yEnd.y);
- //画线
- drawCol(this.ctx, point, this.conf.ledgeLen, this.conf.axisColor, 1);
- var offset = 0;
- if (i == points.length - 1) {
- var text = this.getText(axis_option.style | PlotGrid.ADD_YEAR, points[i].value, axis_option.unit);
- offset = -20;
- } else {
- var text = this.getText(axis_option.style, points[i].value, axis_option.unit);
- }
- writeText(this.ctx, new Point(points[i].key + offset,
- this.yEnd.y + this.conf.ledgeLen + 12), text, this.conf.fontColor, this.conf.font);
- }
- }
- }
- //如果是固定像素的形式的,xstart 是开始index xend 是结束的 index xunit 是数据
- //设计默认是xend 是画在最右边,如果屏幕像素不够,自动会舍弃xstart 这边的。
- PlotGrid.prototype.drawBg = function() {
- this.ctx.fillStyle = this.conf.bgColor;
- this.ctx.fillRect(0, 0, this.width, this.height);
- }
- //update by fangxiao from 2016、6/29 17:24
- PlotGrid.prototype.drawBoder = function(axis) {
- /*
- if (!axis) axis = this.axis;
- axis_option = axis.viewconfig.x.axis_option;
- var points = axis.viewconfig.x.axis;
- if (typeof points === "undefined")
- {
- return;
- }*/
- //绘制底部线条
- this.ctx.lineWidth = 0.85;
- this.ctx.strokeStyle = this.conf.axisColor;
- //this.ctx.moveTo(this.O.x + 0.5,this.0.y+this.O.y-this.yend.y+0.5);
- //this.ctx.lineTo(this.xEnd.x+0.5,this.0.y+this.O.y-this.yend.y+0.5);
- //this.ctx.stroke();
- //this.ctx.moveTo(this.O.x + 0.5,this.yEnd.y - this.O.y);
- //this.ctx.lineTo(this.xEnd.x - this.O.x, this.yEnd.y - this.O.y);
- //this.ctx.fill();
- // this.ctx.stroke();
- this.ctx.strokeRect(this.O.x + 0.5, this.O.y + 0.5, this.xEnd.x - this.O.x, this.yEnd.y - this.O.y);
- }
- PlotGrid.prototype.getText = function(style, value, unit) {
- if (style & Axis.TIME) {
- var format = this.config.Global.timeformat[this.axis.p];
- if (style & PlotGrid.ADD_YEAR) {
- format = "Y-" + format;
- }
- var text = timeToDate(value, format, this.config.Global.timezone);
- } else {
- var text = GetText(value, unit);
- }
- return text;
- }
- PlotGrid.minwidth = 1; //每个图形点的最小值,至少是一个像素
- PlotGrid.moveQueue = [];
- PlotGrid.moveTimeid = null;
- PlotGrid.xleft = 0;
- PlotGrid.ytop = 0;
- //1. 情况1: 指标 和
- //加载第一次数据被绑定
- //2. 情况2:在加载数据的时候,这在初始化。【这个时候,加一个任务,初始化未初始化的指标】
- //3. 情况3:数据已经初始化完成了,指标被加入。这个时候,马上初始化指标。然后,新下载的数据,先让指标自己缓存起来。
- //4. 暂时只考虑被绑定的情况
- PlotGrid.setMoveInterval = function(mode, _this) {
- if (PlotGrid.moveTimeid !== null) return;
- debug(mode);
- if (typeof mode === "undefined") {
- mode = "mouse";
- }
- if (mode == "mouse") {
- PlotGrid.mode = mode;
- //var _time = 30;
- var _time = 10;
- PlotGrid.minwidth = _this.view.plot[_this.view.config.mainName].getOneSize();
- } else if (mode == "key") {
- PlotGrid.mode = mode;
- //var _time = 100;
- var _time = 100;
- } else {
- //do nothing
- PlotGrid.mode = mode;
- }
- if (window["FlashCanvas"]) {
- //_time = 60;
- _time = 60;
- }
- this.moveTimeid = window.setInterval(function() {
- if (PlotGrid.moveQueue.length > 0) {
- debug("setInterval draw beg");
- PlotGrid.moveTo(PlotGrid.moveQueue.pop(), _this);
- debug("setInterval draw end");
- PlotGrid.moveQueue = [];
- }
- }, _time);
- debug(this.moveTimeid);
- }
- PlotGrid.clearMoveInterval = function(_this) {
- if (PlotGrid.moveQueue.length > 0) {
- PlotGrid.moveTo(PlotGrid.moveQueue.pop(), _this);
- PlotGrid.moveQueue = [];
- }
- if (PlotGrid.moveTimeid !== null) window.clearInterval(PlotGrid.moveTimeid);
- debug("clearMoveInterval");
- PlotGrid.moveTimeid = null;
- }
- PlotGrid.prototype.getYValue = function(y, axis) {
- if (typeof axis === "undefined") {
- axis = this.axis;
- }
- var value = this.axis.getYValue(y, this.conf.crossYMode, axis);
- if (value === false) return;
- var opt = axis.viewconfig.y.axis_option;
- value = this.getText(opt.style, value, opt.unit);
- return value;
- }
- PlotGrid.prototype.addEvent = function() {
- this.active = true;
- //这两个事件在主图中注册就可以了
- $(this.canvasContainer).bind('mousedown touchstart', this, function(e) {
- debug('mousedown');
- var _this = e.data;
- //PlotGrid.xleft = e.pageX;
- PlotGrid.xleft = isPC() ? e.pageX - $(this).offset().left : e.originalEvent.targetTouches[0].pageX - $(this).offset().left;
- PlotGrid.setMoveInterval('mouse', _this);
- var canvas_mousemove = function(e) {
- //console.log("move");
- var _this = e.data;
- //var newxleft = e.pageX - $(this).offset().left;
- var newxleft = isPC() ? e.pageX - $(this).offset().left : e.originalEvent.targetTouches[0].pageX - $(this).offset().left;
- PlotGrid.moveQueue.push(newxleft);
- debug("move to " + newxleft);
- return false;
- };
- $(_this.canvasContainer).bind('mousemove touchmove', _this, canvas_mousemove);
- var _canvas = _this.canvas;
- if (_canvas.selector == "#plot_canvas_02") {
- /*var x = e.pageX - $(_canvas).offset().left;*/
- var x = isPC() ? e.pageX - $(_canvas).offset().left : e.originalEvent.targetTouches[0].pageX - $(_canvas).offset().left;
- /*var y = e.pageY - $(_canvas).offset().top;*/
- var y = isPC() ? e.pageY - $(_canvas).offset().top : e.originalEvent.targetTouches[0].pageY - $(_canvas).offset().top;
- /*
- if(_this.xEnd.x >x && (_this.xEnd.x-x)<40){
- $("#tool_list").find("li[name='order']").css('cursor', 'pointer');
- $("#ordershow").val(_this.getYValue(y));
- $("#orderprice").val( $("#ordershow").val());
- $("#orderdirection").html("买");
- order.show();
- }else if(_this.xEnd.x <x){
- $("#tool_list").find("li[name='order']").css('cursor', 'pointer');
- $("#ordershow").val(_this.getYValue(y));
- $("#orderprice").val( $("#ordershow").val());
- $("#orderdirection").html("卖");
- order.show();
- }*/
- }
- $(document).bind('mouseup touchend', _this, function(e) {
- var _this = e.data;
- $(_this.canvasContainer).unbind('mousemove', canvas_mousemove);
- $(this).unbind('mouseup');
- PlotGrid.clearMoveInterval(_this);
- return false;
- });
- return false;
- });
- $(this.resize).bind("mousedown touchstart", this, function(e) {
- debug("resize mouse down");
- var _this = e.data;
- //PlotGrid.ytop = e.pageY;
- PlotGrid.ytop = isPC() ? e.pageY : e.originalEvent.targetTouches[0].pageY;
- PlotGrid.setMoveInterval('resize', _this);
- $("body").css("cursor", "n-resize");
- var document_mousemove = function(e) {
- var _this = e.data;
- //var newxtop = e.pageY;
- var newxtop = isPC() ? e.pageY : e.originalEvent.targetTouches[0].pageY;
- PlotGrid.moveQueue.push(newxtop);
- debug("move to new top " + newxtop);
- return false;
- };
- $(document).bind('mousemove tonchmove', _this, document_mousemove);
- $(document).bind('mouseup touchend', _this, function(e) {
- $(document).unbind('mousemove tonchmove', document_mousemove);
- $("body").css("cursor", "default");
- $(document).unbind('mouseup');
- PlotGrid.clearMoveInterval(_this);
- return false;
- });
- return false;
- });
- this.bindHover();
- }
- //鼠标经过的位置hover出框框
- PlotGrid.prototype.bindHover = function() {
- var _this = this;
- var mouseMoveInterval = new IntervalEvent(
- 3,
- function(controller) //可以重新被call
- {
- if (!this.value || this.value.length != 4) {
- return;
- }
- var x = this.value[0];
- var y = this.value[1];
- var time = this.value[2];
- if (time < 0) //已经显示过了,不用再显示了。
- {
- return;
- }
- var newtime = (new Date()).getTime();
- if (newtime - time >= PlotGrid._this.config.Global.hoverTime) {
- var show = 1;
- this.value[2] = -1;
- } else {
- var show = 0;
- }
- // console.log("time:"+time+",newtime:"+newtime+",show:"+show+",x:"+x+",y:"+y);//头部标题内容
- if (this.X && this.Y) {
- var index = find_near(this.X, x);
- if ((index != -1) && (Math.abs(this.X[index] - x) <= this.getOneSize())) {
- var ohlc = this.Y[index];
- if (ohlc[Data.HIGH] - this.config.Global.overPadding <= y && ohlc[Data.LOW] + this.config.Global.overPadding >= y) {
- var findTime = this.axis.getXValue(x, PlotGrid.NEAR);
- if (findTime === false) return;
- var cdata = this.view.model.getDataByTime(this.name, findTime, "candle");
- if (!cdata) return false;
- var time = cdata.time;
- var ohlc = cdata.data;
- var yunit = this.axis.viewconfig.y.axis_option.unit;
- var fallOrDegrees = parseFloat(GetText(ohlc[Data.CLOSE], yunit) - GetText(ohlc[Data.OPEN], yunit)) / parseFloat(GetText(ohlc[Data.OPEN], yunit));
- var fallOrDegrees = fallOrDegrees.toFixed(3);
- //timeLine Data
- // timelineData(time, GetText(ohlc[Data.OPEN], yunit), GetText(ohlc[Data.HIGH], yunit), GetText(ohlc[Data.LOW], yunit), GetText(ohlc[Data.CLOSE], yunit), fallOrDegrees, GetText(ohlc[Data.VOLUMES], yunit));
- // console.log("text PlotCandle");
- }
- }
- }
- PlotGrid.doHover(x, y, this.value[3], show);
- }, true
- );
- $(this.canvas).bind("mousemove touchmove", this, this.mouseMove);
- this.controller.addIntervalEvent("mouseMoveInterval", mouseMoveInterval);
- $(this.canvas).bind("mouseout touchend", this, function(e) {
- $("#msgbox").hide();
- });
- }
- PlotGrid.prototype.mouseMove = function(e) {
- var _this = e.data;
- PlotGrid._this = _this;
- var _canvas = _this.canvas;
- //var x = e.pageX - $(_canvas).offset().left;
- var x = isPC() ? e.pageX - $(_canvas).offset().left : e.originalEvent.targetTouches[0].pageX - $(_canvas).offset().left;
- //var y = e.pageY - $(_canvas).offset().top;
- var y = isPC() ? e.pageY - $(_canvas).offset().top : e.originalEvent.targetTouches[0].pageY - $(_canvas).offset().top;
- var time = (new Date()).getTime();
- var interval = _this.controller.intervalEvent.mouseMoveInterval;
- //位置没有变化,不进行处理
- if (interval.value && interval.value[0] == x && interval.value[1] == y) {
- return;
- }
- interval.setVal([x, y, time, e]);
- }
- //十字光标经过操作
- PlotGrid.doHover = function(x, y, e, showhover) {
- var _this = PlotGrid._this;
- if (!showhover) {
- if ($("#msgbox").css('display') != "none") {
- $("#msgbox").css("top", -1000).css("left", -1000);
- $("#msgbox").hide();
- //debugx("hide1: " + x + "," + y);
- }
- return false;
- }
- //_this.controller.intervalEvent.mouseMoveInterval.setVal(null);
- var overstr = '';
- for (var i = _this.plot.length - 1; i >= 0; i--) {
- if (_this.plot[i].obj.over) { //将内容加入头部
- overstr = _this.plot[i].obj.over(x, y);
- if (overstr) break;
- }
- }
- if (overstr) {
- $("#msgbox").html(overstr);
- //debugx("show: " + x + "," + y);
- var top = e.pageY + 10;
- var left = e.pageX + 10;
- var w = $("#msgbox").width();
- var h = $("#msgbox").height();
- if (top + h + 10 > $(window).height()) {
- top = $(window).height() - h - 12;
- }
- if (left + w + 10 > $(window).width()) {
- left = $(window).width() - w - 12;
- }
- $("#msgbox").css("top", top).css("left", left);
- $("#msgbox").show();
- } else {
- $("#msgbox").css("top", -1000).css("left", -1000);
- $("#msgbox").hide();
- //debugx("hide2: " + x + "," + y);
- }
- }
- PlotGrid.prototype.removeEvent = function() {
- this.active = false;
- $(document).unbind("keydown");
- $(this.canvas).unbind('mousedown uchstartto');
- $(this.canvas).unbind('mousemove touchmove');
- $(document).unbind('mouseup touchend');
- }
- PlotGrid.moveTo = function(newxleft, _this) {
- if (PlotGrid.mode == "mouse") {
- if (newxleft - PlotGrid.xleft > PlotGrid.minwidth) //move to left
- {
- _this.controller.startOffset(Math.round((newxleft - PlotGrid.xleft) / PlotGrid.minwidth));
- _this.controller.draw();
- PlotGrid.xleft = newxleft;
- } else if (PlotGrid.xleft - newxleft > PlotGrid.minwidth) {
- _this.controller.startOffset(-Math.round((PlotGrid.xleft - newxleft) / PlotGrid.minwidth));
- _this.controller.draw();
- PlotGrid.xleft = newxleft;
- }
- } else if (PlotGrid.mode == "key") {
- _this.controller.draw();
- } else if (PlotGrid.mode == "resize") {
- _this.view.resizeGrid(newxleft - PlotGrid.ytop, _this.index);
- _this.controller.draw();
- PlotGrid.ytop = newxleft;
- }
- }
- PlotGrid.prototype.addPlot = function(name, plot) {
- var obj = { name: name, obj: plot };
- this.plot.push(obj);
- }
- PlotGrid.prototype.removePlot = function(name) {
- var plot = [];
- for (var i = 0; i < plot.length; i++) {
- var item = plot[i];
- if (item.name != name) {
- plot.push(item);
- }
- }
- this.plot = plot;
- }
- function isPC() {
- var userAgentInfo = navigator.userAgent;
- //alert(userAgentInfo)
- var Agents = ["Android", "iPhone",
- "SymbianOS", "Windows Phone",
- "iPad", "iPod"
- ];
- var flag = true;
- for (var v = 0; v < Agents.length; v++) {
- if (userAgentInfo.indexOf(Agents[v]) > 0) {
- flag = false;
- break;
- }
- }
- return flag;
- }
- function PlotKshape(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(PlotKshape, Plot);
- PlotKshape.tagMap = {
- 1: "A",
- 2: "a",
- 3: "B",
- 4: "b",
- 5: "C",
- 6: "c",
- 7: "D",
- 8: "d",
- 9: "E",
- 10: "e",
- 11: "N",
- 12: "n",
- 13: "W",
- 14: "w",
- 15: "X",
- 16: "x",
- 17: "F",
- 18: "f",
- 19: "L",
- 20: "l",
- 21: "T",
- 22: "t",
- 23: "G",
- 24: "g",
- 25: "Z",
- 26: "z",
- 27: "V",
- 28: "v",
- 29: "J",
- 30: "j",
- 31: "Y",
- 32: "y"
- };
- PlotKshape.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.lineColor) {
- color = this.param.lineColor;
- } else {
- color = this.conf.lineColor;
- }
- for (var i = 0; i < data.x.length; i++) {
- if (data.y[i][1] != -1) {
- writeText(this.ctx, new Point(data.x[i], data.y[i][0]), PlotKshape.tagMap[data.y[i][1]], color[0], this.param.font);
- }
- if (data.y[i][2] != -1) {
- writeText(this.ctx, new Point(data.x[i], data.y[i][0] + 12), PlotKshape.tagMap[data.y[i][2]], color[1], this.param.font);
- }
- }
- }
- function PlotLine(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(PlotLine, Plot);
- PlotLine.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color;
- } else {
- color = this.conf.lineColor;
- }
- drawLine(this.ctx, data.x, data.y, color);
- }
- function PlotMacd(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(PlotMacd, Plot);
- PlotMacd.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color.split("-");
- } else {
- color = this.conf.lineColor;
- }
- var y1 = []
- var y2 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][0];
- y2[i] = data.y[i][1];
- }
- //color[1] = "rgb(112,207,88)";
- drawLine(this.ctx, data.x, y2, color[0],1.5);
- this.plotBar(data.x, y1, color[1]);
- }
- PlotMacd.prototype.getShowName = function() {
- var name = this.name.toUpperCase();
- name = name.replace("MAIN", "").replace("||", " ");
- name = name.split("|");
- if (name.length == 1) {
- return name[0];
- }
- var pre = name.shift();
- return pre + " (" + name.join(" , ") + ")";
- }
- PlotMacd.prototype.plotBar = function(x, H, colorbar) {
- var zero_y = this.axis.getY(0);
- drawRow(this.ctx, { x: this.left, y: zero_y }, this.right - this.left, this.conf.lineColorZero);
- this.ctx.beginPath();
- this.ctx.strokeStyle = colorbar;
- for (var i = 0; i < x.length; i++) {
- try {
- if (isNaN(H[i])) continue;
- this.ctx.moveTo(x[i] + 0.5, zero_y);
- this.ctx.lineTo(x[i] + 0.5, H[i]);
- } catch (e) {
- // console.log(e);
- // console.log(x[i]);
- // console.log(H[i]);
- }
- }
- this.ctx.stroke();
- }
- function Plotmatrend(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotmatrend, Plot);
- Plotmatrend.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color;
- } else {
- color = this.conf.lineColor;
- }
- var y1 = []
- var y2 = []
- var y3 = []
- var y4 = []
- var y5 = []
- var y6 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][0];
- y2[i] = data.y[i][1];
- y3[i] = data.y[i][2];
- y4[i] = data.y[i][3];
- y5[i] = data.y[i][4];
- y6[i] = data.y[i][5]
- }
- drawLine(this.ctx, data.x, y1, color[0]);
- drawLine(this.ctx, data.x, y2, color[1]);
- drawLine(this.ctx, data.x, y3, color[2]);
- drawLine(this.ctx, data.x, y4, color[3]);
- drawLine(this.ctx, data.x, y5, color[4]);
- drawLine(this.ctx, data.x, y6, color[5]);
- }
- function PlotMLine(view, grid, name) {
- sup(this, view, grid, name);
- this.laststatus = "";
- this.lastquick = "";
- }
- ClassExtend(PlotMLine, Plot);
- PlotMLine.prototype.draw = function(data) {
- //建立点,mline的格式
- //
- var color, width;
- this.data = data;
- var last = this.lastData();
- for (var key in data.data) {
- if (this.param[key.toLowerCase() + "_color"]) {
- color = this.param[key.toLowerCase() + "_color"];
- } else {
- color = this.conf.lineColor;
- }
- if (data.width && data.width[key]) {
- width = data.width[key];
- //console.log(width);
- }
- if (data.data[key].x.length > 0) {
- drawLine(this.ctx, data.data[key].x, data.data[key].y, color, width);
- }
- if (this.param[key.toLowerCase() + "_flag"]) {
- this.priceFlag(last[key].bidask[0], this.config.Global.Candle["public"].close);
- }
- }
- }
- PlotMLine.prototype.lastDataShow = function() {
- var text = [];
- text.push("Local-QuickT = " + this.data.offset.local);
- text.push("QuickT-SlowT = " + this.data.offset.delt);
- if (1) {
- var last = this.lastData();
- var laststatus = "BID(";
- for (var key in last) {
- laststatus += key + "=" + this.grid.getText(0, last[key].bidask[0], this.data.yunit) + " ";
- }
- this.laststatus = laststatus + ")";
- }
- if (!this.data.quick.inquick) {
- var quick = this.data.quick;
- if (quick.start && quick.end) {
- this.lastquick = " ([" + quick.start + ", " + quick.end + "] Point: " + quick.point / 10 + " Time: " + quick.delt + ") "
- }
- }
- return this.lastquick + this.laststatus + text.join(" , ");
- }
- PlotMLine.prototype.getShowName = function() {
- var text = "";
- var keyarr;
- var name = this.name.split("|", 2)[0];
- for (var key in this.param) {
- if (key.indexOf("_color") !== -1) {
- keyarr = key.split("_");
- text += keyarr[0] + "(" + this.param[key] + ") ";
- }
- }
- var ret = name + " " + text;
- ret = ret.toUpperCase();
- return ret;
- }
- function PlotOrder(view, grid, name) {
- sup(this, view, grid, name);
- this.arrow = {};
- var conf = this.config.Global.arrow[DataWriterProfit.BUY_OPEN];
- this.arrow[DataWriterProfit.BUY_OPEN] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
- var conf = this.config.Global.arrow[DataWriterProfit.BUY_CLOSE];
- this.arrow[DataWriterProfit.BUY_CLOSE] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
- var conf = this.config.Global.arrow[DataWriterProfit.SELL_OPEN];
- this.arrow[DataWriterProfit.SELL_OPEN] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
- var conf = this.config.Global.arrow[DataWriterProfit.SELL_CLOSE];
- this.arrow[DataWriterProfit.SELL_CLOSE] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
- }
- ClassExtend(PlotProfit, Plot);
- PlotProfit.prototype.draw = function(data) {
- var x, y, type;
- this.X = data.x;
- this.Y = data.y;
- for (var i = 0; i < data.x.length; i++) {
- for (var j = 0; j < data.y[i].length; j++) {
- y = data.y[i][j];
- type = y[0];
- y = y[1];
- x = this.fixedX(data.x[i], type);
- this.arrow[type].draw(new Point(x, y));
- }
- }
- }
- PlotProfit.prototype.getShowName = function() {
- return this.controller.c + " " + this.controller.p;
- }
- PlotProfit.prototype.lastDataShow = function() {
- return "";
- }
- PlotProfit.prototype.fixedX = function(x, type) {
- x += 0.5;
- var box = this.view.plot[this.config.mainName].getBoxSize();
- var left = this.view.plot[this.config.mainName].getBoxLeft();
- if (type == DataWriterProfit.BUY_OPEN || type == DataWriterProfit.SELL_OPEN) {
- x -= left;
- } else {
- x += box - left;
- }
- return x;
- }
- PlotProfit.prototype.over = function(x1, y1) {
- if (!this.X) {
- return false;
- }
- var x, y, type, bk = false;
- x1 += 0.5;
- for (var i = 0; i < this.X.length; i++) {
- for (var j = 0; j < this.Y[i].length; j++) {
- y = this.Y[i][j][1];
- type = this.Y[i][j][0];
- x = this.fixedX(this.X[i], type);
- if (this.inarrow(new Point(x, y), type, x1, y1)) {
- bk = true;
- break;
- }
- }
- if (bk) {
- break;
- }
- }
- if (!bk) {
- return false;
- }
- var findTime = this.axis.getXValue(this.X[i], PlotGrid.NEAR);
- if (findTime === false) return;
- var cdata = this.view.model.getDataByTime(this.name, findTime);
- if (!cdata) {
- return false;
- }
- cdata.data = cdata.data[j];
- /*
- var data = cdata.data[2];
- var open_time = timeToDate(data[1], null, this.config.Global.timezone);
- var close_time = timeToDate(data[8], null, this.config.Global.timezone);
- return "Ticket: " + data[0] + "<br />" +
- "Open Time: " + open_time + "<br />" +
- "Close Time: " + close_time + "<br />" +
- "Open Price: " + data[5] + "<br />" +
- "Close Price:" + data[9] + "<br />" +
- "Size: " + data[3] + "<br />" +
- "Profit: " + data[13] + "<br />";
- */
- return "<b>Type</b>: " + (DataWriterProfit.nameMap[cdata.data[0]]) + "<br/>" +
- "<b>Price</b>: " + cdata.data[1] + "<br/>" +
- "<b>OrderID</b>: " + cdata.data[2] + "<br/>";
- }
- //某个坐标是否在某个点内部
- PlotProfit.prototype.inarrow = function(point, type, x, y) {
- var conf = this.config.Global.arrow[type];
- var cta = conf.incta;
- var len = conf.height;
- var width = conf.width + 5;
- point.y = -point.y;
- y = -y;
- var newpoint = axis_translate(new Point(x, y), cta, point);
- if (newpoint.x >= 0 && newpoint.x <= len && Math.abs(newpoint.y) <= width) {
- return true;
- } else {
- return false;
- }
- }
- function Plotcombinparam1001(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotcombinparam1001, Plot);
- Plotcombinparam1001.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color;
- } else {
- color = this.conf.lineColor;
- }
- var y1 = []
- var y2 = []
- var y3 = []
- var y4 = []
- var y5 = []
- var y6 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][0];
- y2[i] = data.y[i][1];
- y3[i] = data.y[i][2];
- y4[i] = data.y[i][3];
- y5[i] = data.y[i][4];
- y6[i] = data.y[i][5];
- }
- drawLine(this.ctx, data.x, y1, color[0]);
- drawLine(this.ctx, data.x, y2, color[1]);
- drawLine(this.ctx, data.x, y3, color[2]);
- drawLine(this.ctx, data.x, y4, color[3]);
- drawLine(this.ctx, data.x, y5, color[4]);
- drawLine(this.ctx, data.x, y6, color[5]);
- }
- function PlotProfit(view, grid, name) {
- sup(this, view, grid, name);
- this.arrow = {};
- var conf = this.config.Global.arrow[DataWriterProfit.BUY_OPEN];
- this.arrow[DataWriterProfit.BUY_OPEN] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
- var conf = this.config.Global.arrow[DataWriterProfit.BUY_CLOSE];
- this.arrow[DataWriterProfit.BUY_CLOSE] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
- var conf = this.config.Global.arrow[DataWriterProfit.SELL_OPEN];
- this.arrow[DataWriterProfit.SELL_OPEN] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
- var conf = this.config.Global.arrow[DataWriterProfit.SELL_CLOSE];
- this.arrow[DataWriterProfit.SELL_CLOSE] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
- }
- ClassExtend(PlotProfit, Plot);
- PlotProfit.prototype.draw = function(data) {
- var x, y, type;
- this.X = data.x;
- this.Y = data.y;
- for (var i = 0; i < data.x.length; i++) {
- for (var j = 0; j < data.y[i].length; j++) {
- y = data.y[i][j];
- type = y[0];
- y = y[1];
- x = this.fixedX(data.x[i], type);
- this.arrow[type].draw(new Point(x, y));
- }
- }
- }
- PlotProfit.prototype.getShowName = function() {
- return this.controller.c + " " + this.controller.p;
- }
- PlotProfit.prototype.lastDataShow = function() {
- return "";
- }
- PlotProfit.prototype.fixedX = function(x, type) {
- x += 0.5;
- var box = this.view.plot[this.config.mainName].getBoxSize();
- var left = this.view.plot[this.config.mainName].getBoxLeft();
- if (type == DataWriterProfit.BUY_OPEN || type == DataWriterProfit.SELL_OPEN) {
- x -= left;
- } else {
- x += box - left;
- }
- return x;
- }
- PlotProfit.prototype.over = function(x1, y1) {
- if (!this.X) {
- return false;
- }
- var x, y, type, bk = false;
- x1 += 0.5;
- for (var i = 0; i < this.X.length; i++) {
- for (var j = 0; j < this.Y[i].length; j++) {
- y = this.Y[i][j][1];
- type = this.Y[i][j][0];
- x = this.fixedX(this.X[i], type);
- if (this.inarrow(new Point(x, y), type, x1, y1)) {
- bk = true;
- break;
- }
- }
- if (bk) {
- break;
- }
- }
- if (!bk) {
- return false;
- }
- var findTime = this.axis.getXValue(this.X[i], PlotGrid.NEAR);
- if (findTime === false) return;
- var cdata = this.view.model.getDataByTime(this.name, findTime);
- if (!cdata) {
- return false;
- }
- cdata.data = cdata.data[j];
- /*
- var data = cdata.data[2];
- var open_time = timeToDate(data[1], null, this.config.Global.timezone);
- var close_time = timeToDate(data[8], null, this.config.Global.timezone);
- return "Ticket: " + data[0] + "<br />" +
- "Open Time: " + open_time + "<br />" +
- "Close Time: " + close_time + "<br />" +
- "Open Price: " + data[5] + "<br />" +
- "Close Price:" + data[9] + "<br />" +
- "Size: " + data[3] + "<br />" +
- "Profit: " + data[13] + "<br />";
- */
- return "<b>Type</b>: " + (DataWriterProfit.nameMap[cdata.data[0]]) + "<br/>" +
- "<b>Price</b>: " + cdata.data[1] + "<br/>" +
- "<b>OrderID</b>: " + cdata.data[2] + "<br/>";
- }
- //某个坐标是否在某个点内部
- PlotProfit.prototype.inarrow = function(point, type, x, y) {
- var conf = this.config.Global.arrow[type];
- var cta = conf.incta;
- var len = conf.height;
- var width = conf.width + 5;
- point.y = -point.y;
- y = -y;
- var newpoint = axis_translate(new Point(x, y), cta, point);
- if (newpoint.x >= 0 && newpoint.x <= len && Math.abs(newpoint.y) <= width) {
- return true;
- } else {
- return false;
- }
- }
- function Plotrsi(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotrsi, Plot);
- Plotrsi.prototype.draw = function(data) {
- this.plotBar(data.x, data.y);
- }
- Plotrsi.prototype.lastDataShow = function() {
- var data = this.lastData();
- return data;
- }
- Plotrsi.prototype.plotBar = function(x, H) {
- var zero_y = this.axis.getY(50);
- drawRow(this.ctx, { x: this.left, y: zero_y }, this.right - this.left, this.conf.lineColorZero);
- this.ctx.beginPath();
- this.ctx.strokeStyle = this.conf.lineColorH;
- for (var i = 0; i < x.length; i++) {
- try {
- if (isNaN(H[i])) continue;
- this.ctx.moveTo(x[i] + 0.5, zero_y);
- this.ctx.lineTo(x[i] + 0.5, H[i]);
- } catch (e) {
- // console.log(e);
- // console.log(x[i]);
- // console.log(H[i]);
- }
- }
- this.ctx.stroke();
- }
- function Plotrsisma(view, grid, name) {
- sup(this, view, grid, name);
- //放大缩小尺寸控制更加灵活。采用配置数组的形式
- this.box = [1, 2, 3, 5, 7, 9, 11, 13];
- this.space = [0, 1, 1, 2, 2, 3, 4, 5];
- this.left = [0, 1, 1, 2, 3, 4, 5, 6]
- }
- ClassExtend(Plotrsisma, Plot);
- Plotrsisma.prototype.zoomIn = function() {
- if (this.conf.box_pixel >= 7 && this.conf.space_pixel >= 7) {
- return;
- }
- if (this.conf.box_pixel < this.conf.space_pixel) {
- this.conf.box_pixel++;
- } else if (this.conf.box_pixel > this.conf.space_pixel) {
- this.spaceOffset(1);
- } else {
- this.conf.box_pixel++;
- }
- }
- Plotrsisma.prototype.spaceOffset = function(offset) {
- var prev = this.space[this.conf.space_pixel];
- this.conf.space_pixel = this.conf.space_pixel + offset;
- var current = this.space[this.conf.space_pixel];
- if (prev == current) {
- this.conf.box_pixel = this.conf.box_pixel + offset;
- }
- }
- Plotrsisma.prototype.zoomOut = function() {
- if (this.conf.box_pixel <= 0 && this.conf.space_pixel <= 0) {
- return;
- }
- if (this.conf.box_pixel < this.conf.space_pixel) {
- this.spaceOffset(-1);
- } else if (this.conf.box_pixel > this.conf.space_pixel) {
- this.conf.box_pixel--;
- } else {
- this.spaceOffset(-1);
- }
- this.conf.box_pixel = this.conf.box_pixel < 0 ? 0 : this.conf.box_pixel;
- }
- Plotrsisma.prototype.getOneSize = function() {
- return this.box[this.conf.box_pixel] + 2 * this.space[this.conf.space_pixel];
- }
- Plotrsisma.prototype.getBoxLeft = function() {
- return this.left[this.conf.box_pixel];
- }
- Plotrsisma.prototype.getBoxSize = function() {
- return this.box[this.conf.box_pixel];
- }
- Plotrsisma.prototype.draw = function(data) {
- this.data = data;
- this.X = data.x;
- this.Y = data.y;
- this.xunit = this.data.xunit;
- this.yunit = this.data.yunit;
- var width = this.box[this.conf.box_pixel];
- var left = this.left[this.conf.box_pixel];
- if (width > 2) {
- width--;
- }
- for (var i = 0; i < this.X.length; i++) {
- this.drawOne(this.X[i], this.Y[i], width, left);
- }
- var ySma = []
- for (var i = 0; i < data.y.length; i++) {
- ySma[i] = data.y[i][7];
- }
- drawLine(this.ctx, data.x, ySma, this.conf.SmaColor);
- }
- //鼠标经过十字光标显示的内容框
- Plotrsisma.prototype.over = function(x, y) {
- //查找最接近的
- // console.log("1");
- if (!this.X || !this.Y) return;
- var index = find_near(this.X, x);
- if (index == -1) return false;
- if (Math.abs(this.X[index] - x) > this.getOneSize()) {
- return false;
- }
- var ohlc = this.Y[index];
- if (ohlc[Data.HIGH] - this.config.Global.overPadding <= y && ohlc[Data.LOW] + this.config.Global.overPadding >= y) {
- // console.log("Plotrsisma");
- var findTime = this.axis.getXValue(x, PlotGrid.NEAR);
- if (findTime === false) return;
- var cdata = this.view.model.getDataByTime(this.name, findTime, "candle");
- if (!cdata) return false;
- var time = cdata.time;
- var ohlc = cdata.data;
- var yunit = this.axis.viewconfig.y.axis_option.unit;
- var fallOrDegrees=parseFloat(GetText(ohlc[Data.CLOSE], yunit)-GetText(ohlc[Data.OPEN], yunit))/parseFloat(GetText(ohlc[Data.OPEN], yunit)) ;
- var fallOrDegrees=fallOrDegrees.toFixed(3);
- //timeLine Data
- // timelineData(time,GetText(ohlc[Data.OPEN], yunit),GetText(ohlc[Data.HIGH], yunit),GetText(ohlc[Data.LOW], yunit),GetText(ohlc[Data.CLOSE], yunit),fallOrDegrees,GetText(ohlc[Data.VOLUMES], yunit));
- // return time + "<br/>" + "O: " + GetText(ohlc[Data.OPEN], yunit) + "<br />" + "H: " + GetText(ohlc[Data.HIGH], yunit) + "<br />" + "L : " + GetText(ohlc[Data.LOW], yunit) + "<br />" + "C: " + GetText(ohlc[Data.CLOSE], yunit) + "<br />" +
- // +"V: " + GetText(ohlc[Data.VOLUMES], yunit) + "<br />";
- } else {
- return false;
- }
- }
- Plotrsisma.prototype.drawOne = function(time, ohlc, width, left) {
- var ctx = this.ctx;
- var open = ohlc[Data.OPEN];
- var high = ohlc[Data.HIGH];
- var low = ohlc[Data.LOW];
- var close = ohlc[Data.CLOSE];
- time += 0.5;
- open += 0.5;
- high += 0.5;
- low += 0.5;
- close += 0.5;
- if (high == low) {
- //画个横线就可以了
- ctx.strokeStyle = this.conf.hx.os_border_color;
- ctx.beginPath();
- ctx.moveTo(time - left, open);
- ctx.lineTo(time + width, open);
- ctx.stroke();
- return;
- }
- if (open < close) {
- var up = open;
- var down = close;
- var fill = this.conf.hx.open_big_color;
- var border = this.conf.hx.ob_border_color;
- } else {
- var up = close;
- var down = open;
- var fill = this.conf.hx.open_small_color;
- var border = this.conf.hx.os_border_color;
- }
- ctx.strokeStyle = border;
- ctx.beginPath();
- ctx.moveTo(time, high);
- ctx.lineTo(time, low);
- ctx.stroke();
- if (this.conf.space_pixel > 0) {
- ctx.fillStyle = fill;
- ctx.fillRect(time - left, up, width, down - up);
- ctx.strokeRect(time - left, up, width, down - up);
- }
- }
- function PlotTrendLine(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(PlotTrendLine, Plot);
- PlotTrendLine.prototype.draw = function(data) {
- this.X = data.x;
- this.Y = data.y;
- var plot_list = this.config.Global.trend_line_selected;
- if (plot_list == null) {
- return;
- }
- for (var i = 0; i < data.x.length; i++) {
- if (plot_list.indexOf("" + data.y[i][2]) == -1) {
- continue;
- }
- this.drawTrendLine(data.x[i], data.y[i][0], data.y[i][1], data.y[i][2], data.y[i]);
- }
- }
- PlotTrendLine.prototype.drawTrendLine = function(x, y, tan, type, data) {
- //曲线方程 y = ax + b
- var a = -tan;
- var b = y + tan * x;
- var p = [];
- p[0] = {};
- p[1] = {};
- var i = 0;
- var o = this.grid.O;
- var xy = this.grid.xyEnd;
- var plot_point = {};
- if (data[5] == 0 && typeof data[6] !== "undefined") {
- plot_point.x = data[6];
- plot_point.y = data[7];
- } else {
- if (tan != 0) {
- //和坐标轴的交点的计算
- //o 点 , 和o点的对角点
- //计算曲线与坐标轴的绘图区域的焦点
- //top
- ytop = o.y;
- xtop = (ytop - b) / a;
- if (i < 2 && xtop >= o.x && xtop <= xy.x) {
- p[i].x = xtop;
- p[i].y = ytop;
- i++;
- }
- //bottom
- ybot = xy.y;
- xbot = (ybot - b) / a;
- if (i < 2 && xbot >= o.x && xbot <= xy.x) {
- p[i].x = xbot;
- p[i].y = ybot;
- i++;
- }
- //left
- xleft = o.x;
- yleft = xleft * a + b;
- if (i < 2 && yleft >= o.y && yleft <= xy.y) {
- p[i].x = xleft;
- p[i].y = yleft;
- i++;
- }
- //right
- xright = xy.x;
- yright = xright * a + b;
- if (i < 2 && yright >= o.y && yright <= xy.y) {
- p[i].x = xright;
- p[i].y = yright;
- i++;
- }
- } else {
- p[0].x = o.x;
- p[0].y = y;
- p[1].x = xy.x;
- p[1].y = y;
- }
- //从 x ,y 开始,然后绘制到边界上。
- if (p[0].x > x) {
- plot_point = p[0];
- } else {
- plot_point = p[1];
- }
- }
- plotLine(this.ctx, { x: x, y: y }, plot_point, this.conf.lineColor[type]);
- }
- PlotTrendLine.prototype.over = function(x1, y1) {
- //console.log(this.X);
- //console.log(this.Y);
- mind = Infinity;
- mini = 0;
- if (typeof this.X === "undefined") {
- return;
- }
- for (var i = 0; i < this.X.length; i++) {
- var d = this.distance(x1, y1, this.X[i], this.Y[i]);
- if (d < mind) {
- mind = d;
- mini = i;
- }
- }
- //i 是最短距离了
- if (mind <= 3) {
- return "<b>index:</b>" + this.Y[mini][3] + "<br/>";
- }
- }
- PlotTrendLine.prototype.distance = function(x1, y1, x, y) {
- //曲线方程
- A = -y[1];
- B = -1;
- C = y[0] + y[1] * x;
- d = Math.abs(A * x1 + B * y1 + C) / Math.sqrt(A * A + B * B);
- return d;
- }
- function Plotvolumes(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotvolumes, Plot);
- Plotvolumes.prototype.draw = function(data) {
- //偏移量配置 根据function Plotrsisma(view, grid, name)函数的配置
- var left = [0, 1, 1, 2, 3, 4, 5, 6];
- // var left = [ 3, 4, 5, 6,7,9,10,11]
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color;
- } else {
- color = this.conf.lineColor;
- }
- var zero_y = this.axis.getY(0);
- for (var i = 0; i < data.y.length - 1; i++) {
- if (isNaN(data.y[i][0])) {
- data.y[i][0] = 1;
- }
- /*if (data.y[i][0]>data.y[i+1][0]){
- this.ctx.strokeStyle = color[1]; //green
- }else if (data.y[i][0]<data.y[i+1][0]){
- this.ctx.strokeStyle = color[0]; //red
- }*/
- if (data.y[i].length == 2) {
- if(zero_y>data.y[i][0]){
- var height=zero_y-data.y[i][0];
- }
- else{
- var height=data.y[i][0]-zero_y;
- }
- this.ctx.strokeStyle = color[1]; //green
- //绘制矩形 参考Plotrsisma.prototype.drawOne函数
- this.ctx.closePath();
- this.ctx.beginPath();
- this.ctx.lineWidth = 1;
- this.ctx.fillStyle = color[1];
- this.ctx.fillRect(data.x[i]+0.5-left[this.config.Global.Candle.public.box_pixel],zero_y-height,this.config.Global.boxwidth,height);
- this.ctx.strokeRect(data.x[i]+0.5-left[this.config.Global.Candle.public.box_pixel],zero_y-height,this.config.Global.boxwidth,height);
- this.ctx.closePath();
- // this.ctx.moveTo(data.x[i] + 0.5, zero_y);
- // this.ctx.lineTo(data.x[i] + 0.5, data.y[i][0]);
- // this.ctx.closePath();
- // this.ctx.lineWidth = this.config.Global.boxwidth;
- // this.ctx.stroke();
- // this.ctx.closePath();
-
- } else {
- this.ctx.strokeStyle = color[0]; //red
-
- this.ctx.closePath();
- this.ctx.beginPath();
- if(zero_y>data.y[i][0]){
- var height=zero_y-data.y[i][0];
- }
- else{
- var height=data.y[i][0]-zero_y;
- }
- this.ctx.lineWidth = 1;
- this.ctx.fillStyle = "#0a0a0a";
- this.ctx.fillRect(data.x[i]+0.5-left[this.config.Global.Candle.public.box_pixel],zero_y-height,this.config.Global.boxwidth,height);
- this.ctx.strokeRect(data.x[i]+0.5-left[this.config.Global.Candle.public.box_pixel],zero_y-height,this.config.Global.boxwidth,height);
- this.ctx.closePath();
- // if(zero_y>data.y[i][0])
- // {
- // var height=zero_y-data.y[i][0];
- // this.ctx.strokeRect(data.x[i] + 0.5-this.config.Global.boxwidth,data.y[i][0],this.config.Global.boxwidth,height)
- // this.ctx.closePath();
- // }
- // else{
- // var height=data.y[i][0]-zero_y;
- // this.ctx.lineWidth=5;
- // if(height!=0){
- // this.ctx.strokeRect(data.x[i] + 0.5-this.config.Global.boxwidth,data.y[i][0],this.config.Global.boxwidth,height);
- // this.ctx.closePath();
- // }
- //
- // }
- // this.ctx.closePath();
-
- }
- // this.ctx.beginPath();
- // this.ctx.moveTo(data.x[i] + 0.5, zero_y);
- // this.ctx.lineTo(data.x[i] + 0.5, data.y[i][0]);
- // this.ctx.closePath();
- // this.ctx.lineWidth = this.config.Global.boxwidth;
- // this.ctx.stroke();
- // this.ctx.closePath();
-
- }
- this.ctx.beginPath();
- this.ctx.moveTo(data.x[data.y.length - 1] + 0.5, zero_y);
- this.ctx.lineTo(data.x[data.y.length - 1] + 0.5, data.y[data.y.length - 1][0]);
- this.ctx.closePath();
- //this.ctx.lineWidth = this.config.Global.boxwidth;
- this.ctx.stroke();
- }
- function Plotvolumes2(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotvolumes2, Plot);
- Plotvolumes2.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color;
- } else {
- color = this.conf.lineColor;
- }
- var zero_y = this.axis.getY(0);
- for (var i = 0; i < data.x.length; i++) {
- if (isNaN(data.y[i][0])) continue;
- this.ctx.beginPath();
- this.ctx.moveTo(data.x[i] + 0.5, zero_y);
- if (data.y[i][0] > zero_y) {
- this.ctx.strokeStyle = color[1];
- this.ctx.lineTo(data.x[i] + 0.5, 2 * zero_y - data.y[i][0]);
- } else {
- this.ctx.strokeStyle = color[0];
- this.ctx.lineTo(data.x[i] + 0.5, data.y[i][0]);
- }
- this.ctx.closePath();
- this.ctx.stroke();
- }
- }
- function PlotWave(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(PlotWave, Plot);
- PlotWave.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.color) {
- color = this.param.color;
- } else {
- color = this.conf.lineColor;
- }
- var y1 = []
- for (var i = 0; i < data.y.length; i++) {
- y1[i] = data.y[i][0];
- }
- drawLine(this.ctx, data.x, y1, color[0]);
- }
- function Plotwdensity(view, grid, name) {
- sup(this, view, grid, name);
- }
- ClassExtend(Plotwdensity, Plot);
- Plotwdensity.prototype.draw = function(data) {
- //建立点
- var color;
- if (this.param.lineColor) {
- color = this.param.lineColor;
- } else {
- color = this.conf.lineColor;
- }
- for (var i = 0; i < data.y.length; i++) {
- for (var j = 0; j < data.y[i].length / 2; j++) {
- if (data.y[i][2 * j] != 0 && data.y[i][j * 2 + 1] != 0) {
- writeText(this.ctx, new Point(data.x[i], data.y[i][2 * j]), "~", color[j], this.param.font)
- }
- }
- }
- }
- //Node 版本的数据接收
- //这里主要针对本地传送数据。[直接一次性加载的策略]
- function ModelNode(controller) {
- sup(this, controller);
- this.host = this.config.Global.NodeHost;
- this.port = this.config.Global.NodePort;
- this.isinit = false;
- }
- ClassExtend(ModelNode, Model);
- ModelNode.prototype.initData = function() {
- if (this.isinit) return;
- this.isinit = true;
- var socket = io.connect('http://' + document.domain);
- this.socket = socket;
- var _this = this;
- socket.on("error", function(data) {
- // console.log("error");
- });
- socket.on("init", function(data) {
- // console.log("init");
- _this.updateData(data, "init");
- });
- socket.on("data", function(data) {
- if (data.main && data.main.options.prev_calculated == 0) console.log("data");
- _this.updateData(data, "new");
- });
- var _this = this;
- _this.isconnect = false;
- socket.on("connect", function() {
- _this.isconnect = true;
- _this.subscribe();
- });
- this.socket = socket;
- }
- ModelNode.prototype.subscribe = function() {
- if (this.isconnect) {
- this.socket.emit("subscribe", { c: this.controller.c, p: this.controller.p });
- }
- }
- ModelNode.prototype.downloadData = function() {
- }
- ModelNode.prototype.newData = function() {
- }
- ModelNode.prototype.updateData = function(data, action_name) {
- // console.log("data.p:"+data.p);
- if (data && data.c && data.p) {
- if (data.c != this.c || data.p != this.p) {
- //$("#symbol li[name="+data.c+"]").click();
- $("#period li[name=" + data.p + "]").click();
- action_name = "init";
- }
- }
- if (action_name == "init") {
- if (data && data.c && data.p) {
- this.flag(Model.INITED, 1, data.c, data.p);
- } else {
- this.flag(Model.INITED, 1);
- }
- hide_loading();
- } else {
- debug("update");
- }
- this.update(data, Model.UPDATE);
- }
- //采用短连接下载数据的接口,有两个子类,一个子类是poll 采用轮询的方式更新数据。
- //还有一个 WS采用websocket 的方式更新数据,
- //如果在配置中,指定采用poll,那么我们就采用poll
- //如果在配置中 指定采用websokect,但是发现,有些浏览器不支持,我们还是要退回轮询的方式。
- //而服务器端 会有两套服务器。
- //为了便于扩展。我们没有直接重写 data.set 类。
- function ModelShort(controller) {
- sup(this, controller);
- this.controller=controller;
- this.api = this.config.Global.DataAPI;
- this.prevPoint = 0;
- }
- ClassExtend(ModelShort, Model);
- ModelShort.prototype.getAPI = function() {
- console.log($.cookie('symbol'));
- if($.cookie('symbol')=="YCC"){
- return "https://kdata.fxee.com/kdata?datafile=db" + "&c=NYCC&p="+ this.p;
- }
- else{
- return "https://kdata.fxee.com/kdata?datafile=db" + "&c=" + $.cookie('symbol') + "&p=" + this.p;
- }
- // if(this.p==null){
- // return "https://tick.33.cn:4062/kdata?datafile=db" + "&c=" + $.cookie('symbol') + "&p=H1" ;
- // }
- // else{
- // return "https://tick.33.cn:4062/kdata?datafile=db" + "&c=" + $.cookie('symbol') + "&p=" + this.p;
- // }
-
- // if(this.c=="ETC"){
- // return etcUrl + "&c=" + this.c + "&p=" + this.p;
- // }
- // else{
- // if (this.api.indexOf("?") == -1) {
- // return this.api + "?" + "c=" + this.c + "&p=" + this.p;
- // } else {
- // return this.api + "&c=" + this.c + "&p=" + this.p;
- // }
- // }
-
- }
- ModelShort.prototype.download = function(action_name) {
- this.count = this.config.Global.downloadCount;
- if (action_name == "down") {
- if (this.flag(Model.DOWN_END)) return;
- //判断左边是否需要下载(左边的优先下载)
- var down_flag = 0;
- if (this.leftDataCount() < this.config.Global.lowMark) {
- if (this.downOptions.total_size) {
- if (this.getLeftOffset() < this.downOptions.total_size - 1) down_flag = 1;
- } else {
- down_flag = 1; //left
- }
- }
- //判断右边是否需要下载。对于以时间下载的模式,不会消去数据。所以,右边的永远不需要下载。
- if (down_flag == 0 && this.rightDataCount() < this.config.Global.lowMark) {
- if (this.downOptions.total_size) {
- if (this.getRightOffset() > 0) down_flag = -1;
- }
- }
- if (!down_flag) return;
- }
- if (this.config[this.config.mainName].downdata == 0) return;
- var api = this.getAPI();
- if (!api) return;
- var _this = this;
- var ind = this.getIndicatorList();
- //用一个数字,来标记这些状态. init_beg 和 init_end
- //是一对,设置了一个,就会清除另外的一个
- if (this.flag(Model.DOWN) == 1) return; //如果数据正在下载中,那么忽略新的下载任务
- if (this.downOptions.total_size) {
- //以位置分页
- if (this.state.length == '' && action_name == 'down') {
- var offset = this.getDownOffset(down_flag);
- if (offset < 0) return;
- } else if (this.state == 'home') {
- offset = this.downOptions.total_size - this.count;
- } else if (this.state == "end") {
- offset = 0;
- }
- if (this.getRightOffset() <= offset && offset <= this.getLeftOffset()) {
- this.state = '';
- return;
- }
- var baseparam = { action: action_name, offset: offset, count: this.count, 'ind': ind.join(":") }
- } else {
- //以时间分页
- var baseparam = { action: action_name, ts: this.startXValue(), count: this.count, 'ind': ind.join(":") }
- }
- var pollmode = this.config.Global.PollMode;
- baseparam.out = pollmode;
- this.flag(Model.DOWN, 1);
- $.ajax({
- type: "post",
- url: api,
- data: baseparam,
- success: function(data) {
- // console.log("ajax data:"+data);
- if (data) {
- _this.processDown(data, data.action);
- }
- },
- error : function() {
- // view("异常!");
- alert("异常!");
- //光标移至输入用户名框
- $("#loginusername").focus();
- return -1;
- },
- complete: function(xhr) {
- _this.flag(Model.DOWN, 0);
- _this.state = '';
- },
- dataType: baseparam.out
- });
- }
- ModelShort.prototype.processDown = function(data, action_name) {
- if (action_name == "init") {
- if (data && data.c && data.p) {
- this.flag(Model.INITED, 1, data.c, data.p);
- } else {
- this.flag(Model.INITED, 1);
- }
- hide_loading();
- } else {
- debug("down ok");
- }
- this.update(data, Model.DOWN);
- this.flag(Model.DOWN_DATA, 1); //标记下载的数据可用了
- if (action_name == "init") {
- //this.newData();
- }
- }
- ModelShort.prototype.initData = function() {
- return this.download("init");
- }
- ModelShort.prototype.downloadData = function() {
- this.download("down");
- }
- //通过广播的方式得到tick数据。在本地计算出K线的数据。(方案1)
- //但是本地计算有些麻烦,比较简单的解决方案是:支持一个new 命令
- //把相关的数据下载下来。并注册广播该数据。这个广播服务器需要复杂一点。
- //暂时采用第二种方案,个人认为这个方案在不需要tick报价的情况下,客户端
- //逻辑最少,数据最不容易出错。
- //
- //tick广播服务器,只要缓存24小时内的数据,一般就不会有出现断层。【如果new
- //命令在的时间是在24小时以外的。可以提醒客户端,刷新。但是不考虑这样的异常。】
- //
- //下载数据:会收集所有注册指标的名称,一起下载。下载的数据,按照主K线图对齐。
- //没有对齐的填上NULL,如果某个点为NULL,那么这个点就直接跳过,不会进行绘制
- //function 继承
- function ModelShortPoll(controller) {
- sup(this, controller);
- this.interval = new IntervalEvent(Math.round(this.config.Global.PollInterval / this.config.Global.Interval), function(controller) {
- if(controller.model==undefined)return;
- controller.model.newData();
- }, true);
- controller.addIntervalEvent("poll", this.interval);
- }
- ClassExtend(ModelShortPoll, ModelShort);
- ModelShortPoll.prototype.newData = function() {
- var api = this.getAPI();
- if (!api) return;
- //如果是静态图形
- if (this.controller.staticChat) return true;
- var _this = this;
- if (this.isNewing) {
- if (getTime() - this.lastSend > 1000 * this.config.Global.maxConnectAliveTime) {
- //reconnect. may be the connect is error
- } else {
- return false;
- }
- }
- //如果没有初始化,那么返回
- if (!this.flag(Model.INITED)) {
- return;
- }
- this.isNewing = true;
- this.lastSend = getTime();
- var ind = this.getIndicatorList();
- //更新时间按照主图:的最新数据
- var first = this.flag(Model.FIRST_NEW) ? 1 : 0;
- this.c = this.c;
- console.log(this);
- var baseparam = { action: 'new', "ind": ind.join(":"), te: this.endXValue(), first: first, __tmp: Math.random() };
- var pollmode = this.config.Global.PollMode;
- baseparam.out = pollmode;
- this.newDataXHR = $.ajax({
- type: "post",
- url: api,
- data: baseparam,
- success: function(data) {
- _this.processNew(data);
- _this.isNewing = false;
- },
- complete: function(xhr) {
- _this.isNewing = false;
- },
- dataType: baseparam.out
- });
- return true;
- }
- ModelShortPoll.prototype.processNew = function(data) {
- if (data != null) {
- this.update(data, Model.NEW);
- this.flag(Model.FIRST_NEW, 0, data.c, data.p);
- }
- }
- //通过广播的方式得到tick数据。在本地计算出K线的数据。(方案1)
- //但是本地计算有些麻烦,比较简单的解决方案是:支持一个new 命令
- //把相关的数据下载下来。并注册广播该数据。这个广播服务器需要复杂一点。
- //暂时采用第二种方案,个人认为这个方案在不需要tick报价的情况下,客户端
- //逻辑最少,数据最不容易出错。
- //
- //tick广播服务器,只要缓存24小时内的数据,一般就不会有出现断层。【如果new
- //命令在的时间是在24小时以外的。可以提醒客户端,刷新。但是不考虑这样的异常。】
- //
- //下载数据:会收集所有注册指标的名称,一起下载。下载的数据,按照主K线图对齐。
- //没有对齐的填上NULL,如果某个点为NULL,那么这个点就直接跳过,不会进行绘制
- //function 继承
- //这个是通过 websocket 广播进行数据更新的模式。数据下载部分不变,只是更新了数据更新的部分。
- function ModelShortWS(controller) {
- sup(this, controller);
- this.wsinit = false;
- if (!this.config.Global.WSHost) {
- return;
- }
- this.url = "ws://" + this.config.Global.WSHost + ":" + this.config.Global.WSPort + "/";
- this.interval = new IntervalEvent(Math.round(1000 / this.config.Global.Interval), function(controller) {
- var model = controller.model;
- if (getTime() - model.lastRead > model.config.Global.maxNOData * 1000) {
- model.lastRead = getTime();
- if (model.wsinit) {
- if (model.ws) {
- model.ws.close();
- }
- model.ws = null;
- model.wsinit = false;
- model.newData();
- } else {
- model.ws = null;
- model.wsinit = false;
- model.newData();
- }
- return;
- }
- if (getTime() - model.lastRead > model.config.Global.pingTime * 1000) {
- if (model.ws) {
- try {
- model.ws.send("ping");
- } catch (e) {}
- }
- }
- }, true);
- if (!this.config.Global.newDisable) {
- controller.addIntervalEvent("ws", this.interval);
- }
- this.ws = null;
- }
- ClassExtend(ModelShortWS, ModelShort);
- ModelShortWS.prototype.initWS = function() {
- var _this = this;
- if (this.ws) return;
- if (this.url) {
- this.ws = new WebSocket(this.url);
- this.ws.onopen = function() {
- _this.open();
- };
- this.ws.onmessage = function(e) {
- _this.message(e);
- };
- this.ws.onclose = function(e) {
- _this.message(e);
- };
- }
- }
- ModelShortWS.prototype.newData = function() {
- //如果是静态图形
- if (this.controller.staticChat || this.config.Global.newDisable) return true;
- if (!this.flag(Model.INITED)) {
- return;
- }
- //货币对+指标列表
- var ind = this.getIndicatorList();
- this.cmd = [];
- var hasmain = false;
- var super_ind = [];
- for (var i = 0; i < ind.length; i++) {
- if (ind[i] == this.config.mainName) {
- hasmain = true;
- break;
- }
- }
- if (!hasmain) ind.push(this.config.mainName);
- for (var i = 0; i < ind.length; i++) {
- var mycmd = this.dataObj[ind[i]].reader.getWSCmd();
- if (mycmd) {
- this.cmd.push(mycmd);
- } else {
- super_ind.push(ind[i]);
- }
- }
- if (super_ind.length != 0) {
- super_ind = super_ind.join(',');
- this.cmd.push("super_sub:" + this.c + "_" + this.p + ";" + super_ind + ":" + this.endXValue());
- }
- this.initWS();
- if (this.wsinit) {
- this.sendcmd();
- this.cmd = null;
- }
- }
- ModelShortWS.prototype.sendcmd = function() {
- if (this.cmd) {
- try {
- for (var i = 0; i < this.cmd.length; i++) {
- this.ws.send(this.cmd[i]);
- }
- } catch (e) {}
- }
- }
- ModelShortWS.prototype.open = function() {
- this.wsinit = true;
- this.sendcmd();
- }
- ModelShortWS.prototype.message = function(e) {
- this.lastRead = getTime();
- if (e.data == "here") {
- return;
- }
- var data = eval("(" + e.data + ")");
- this.update(data, Model.NEW);
- }
- ModelShortWS.prototype.close = function(e) {
- this.ws = null;
- this.wsinit = false;
- this.initWS();
- }
- //一般任务reader是一个很简单的东西,但是它实际上也不是非常简单,它涉及预处理。定位等。
- //现在我们考虑一般的情况,那就是main 图 和 这个指标图并不是时间对齐的。
- //我们需要通过time查找。这里,我们采用二分查找。
- //
- //基本的reader会提供两个函数,一个是通过一个start值和number 读取数据
- //一个是通过一个时间范围。读取这个时间范围内的数据。
- //
- //通过精心的组织代码,我们发现这个代码还是可以控制的。虽然,你很难想像用Javascript
- //写这样大型的绘图程序到底能否成功。
- //
- function DataReader(model, writer, name) {
- //每个datreader 对象建立的时候。有一个data write 对象
- this.model = model;
- this.controller = this.model.controller;
- /*if (name!="volumes"){
- this.setParam(this.controller.ind[name].param);
- }*/
- this.writer = writer;
- this.name = name;
- this.config = Config.getInstance();
- this.shift = 0;
- }
- DataReader.EXTEND = 1;
- DataReader.MAIN = 1 << 1;
- DataReader.prototype.setWriter = function(writer) {
- this.writer = writer;
- }
- DataReader.prototype.setParam = function(param) {
- this.param = param;
- }
- DataReader.prototype.getShift = function() {
- //为了计算精确, 从图表中多读取这样多的数据。同时,兼容K线这一端对齐的 和 非对齐的情况,这样,指标的计算只和图表数据相关 和原始数据无关。
- //为了不影响画图,最好不要影响画图
- //时间刻度一般以主图为准。
- return this.shift;
- }
- DataReader.prototype.getStart = function(number) {
- //数据指针
- var start = this.model.point();
- var endpos = this.getEndPos();
- if (endpos < 0) {
- return -1;
- }
- //alert(start);
- if (start < 0) {
- start = 0;
- }
- if (start > endpos) {
- start = endpos;
- }
- if (!number) return start;
- if (endpos - start < number) {
- start = endpos - number + 1;
- }
- if (start < 0) {
- start = 0;
- }
- if (start > endpos) {
- start = endpos - number + 1;
- }
- //修正
- this.model.point(start);
- return start;
- }
- DataReader.prototype.getEndPos = function() {
- var x = this.main.getX(this.c, this.p);
- return x.length - 1;
- }
- DataReader.prototype.startXValue = function() {
- var x = this.main.getX(this.c, this.p);
- return x[x.length - 1];
- }
- DataReader.prototype.endXValue = function() {
- var x = this.main.getX(this.c, this.p);
- return x[0];
- }
- DataReader.prototype.set = function() {
- this.c = this.model.c;
- // console.log("this.model.p:"+this.model.p);
- this.p = this.model.p;
- this.xunit = this.config.Global.xunit[this.p] * 60; //这个是根据时间决定其单位
- if (this.config[this.name] && this.config[this.name].yunit) {
- this.yunit = this.config[this.name].yunit;
- } else {
- this.yunit = this.config.get("Global.yunit." + this.c, this.config.Global.yunit.default_value); //这个是根据货币对决定其单位
- }
- if (this.writer) {
- this.store = this.writer.getStore(this.c, this.p);
- }
- this.config = Config.getInstance();
- // this.config.mainName="main";
- this.main = this.model.dataObj[this.config.mainName].writer; //这个对main是引用关系,所以只要c,p 没有切换
- this.mainData = this.model.data[this.config.mainName]; //main刚刚读取的数据
- this.step = this.xunit;
- this.maxstep = this.config.Global.maxstep; //(5个小时没有数据,那么不进行补充)
- //这个数据,依然是引用了main的最新的数据。
- }
- DataReader.prototype.getMainData = function() {
- this.mainData = this.model.data[this.config.mainName];
- return this.mainData;
- }
- DataReader.prototype.getYminmax = function(y) {
- return minmax(y);
- }
- DataReader.prototype.getWSCmd = function() {
- return false;
- }
- //抽象函数,不提供任何的功能。//主图数据
- DataReader.prototype.getDataByMain = function(readconfig) {
- this.mainData = this.getMainData();
- var nLen = this.mainData.x.length;
- if (nLen > this.model.plotnum) {
- nLen = this.model.plotnum
- }
- var start = this.mainData.x[nLen - 1];
- var end = this.mainData.x[0];
- var x = new Array();
- var y = new Array();
- var xdata = this.writer.getX(this.c, this.p);
- var ydata = this.writer.getY(this.c, this.p);
- //这个部分是数据,首先查找xdata,当然还要判断是否扩展。
- //这里的扩展方式是扩展K线图。其他的扩展,在其他的图里面表示。
- //先获取数据:
- var count = 0;
- var index = find_first_big_r(xdata, end); //查找到第一个点
- if (index == -1) {
- index = 0;
- }
- if (xdata[index] > end) index++; //去掉第一个大于的点
- for (var i = index; i < xdata.length; i++) {
- if (xdata[i] >= start) {
- x[count] = xdata[i];
- y[count] = ydata[i];
- count++;
- } else {
- break;
- }
- }
- if (readconfig & DataReader.EXTEND) {
- //多添加一个最后时间的数据,这个数据如果不存在,那么就复制前一个数据的 open 值,这个时间值肯定小于 start
- if (xdata[i]) {
- x.push(xdata[i]);
- y.push(ydata[i]);
- } else if (x[x.length - 1] > start) {
- x.push(start);
- var ylast = y[y.length - 1][Data.OPEN];
- y.push([ylast, ylast, ylast, ylast, y[y.length - 1][Data.VOLUMES]]);
- }
- return this.extendByMain(x, y);
- }
- //深度拷贝
- y = array_copy(y);
- // }
- return { x: x, y: y };
- }
- DataReader.prototype._formatData = function(x, y) {
- var data = {};
- data.x = x;
- data.y = y;
- data.xunit = this.xunit;
- data.yunit = this.yunit;
- data.maxX = x[0];
- data.minX = x[x.length - 1];
- data.maxIndex=0;
- data.minIndex=0;
- var _minmax = this.getYminmax(y);
- data.maxY = _minmax[1];
- data.minY = _minmax[0];
- data.maxIndex=_minmax[3];
- data.minIndex=_minmax[2];
- return data;
- }
- DataReader.prototype.formatData = function(x, y) {
- return this._formatData(x, y);
- }
- DataReader.prototype.last = function(index) {
- if (!index || index < 0) index = 0;
- var y = this.writer.getY(this.c, this.p);
- return y[index];
- }
- function DataWriter(model, name) {
- this.model = model;
- this.name = name;
- this.config = this.model.config;
- this.storeSet = {};
- }
- DataWriter.prototype.getStore = function(c, p) {
- this.storeSet = init_obj(this.storeSet, c, p, { x: [], y: [] });
- return this.storeSet[c][p];
- }
- DataWriter.prototype.clear = function() {
- this.storeSet = {};
- }
- DataWriter.prototype.setNewData = function(c, p, data) {
- //do nothing.
- }
- DataWriter.prototype.setDownloadData = function(c, p, data) {
- //do nothing.
- }
- DataWriter.prototype.getX = function(c, p) {
- var store = this.getStore(c, p);
- return store.x;
- }
- DataWriter.prototype.getY = function(c, p) {
- var store = this.getStore(c, p);
- return store.y;
- }
- function DataWriterbdensity(model, name) {
- sup(this, model, name);
- }
- ClassExtend(DataWriterbdensity, DataWriter);
- DataWriterbdensity.prototype.setNewData = function(c, p, data) {
- if (!is_array(data) || data.length == 0) {
- return;
- }
- var store = this.getStore(c, p);
- }
- DataWriterbdensity.prototype.notify = function(items) {
- if (items && items.length) {
- /*var typename = DataWriterProfit.nameMap[items[items.length - 1][0]];
- typename = typename.replace("/", "_").toLowerCase();
- var url = $("#music_list select[name="+typename+"]").val();
- playmusic(url);
- */
- }
- }
- DataWriterbdensity.prototype.parseItem = function(items) {
- var newarr = [];
- var type = null;
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (item[0] == "buy" && item[1] == "open") {
- type = DataWriterProfit.BUY_OPEN;
- } else if (item[0] == "buy" && item[1] == "close") {
- type = DataWriterProfit.BUY_CLOSE;
- } else if (item[0] == "sell" && item[1] == "open") {
- type = DataWriterProfit.SELL_OPEN;
- } else if (item[0] == "sell" && item[1] == "close") {
- type = DataWriterProfit.SELL_CLOSE;
- }
- if (type) {
- newarr[i] = [type, parseFloat(item[2]), item[3]];
- }
- }
- if (newarr.length == 0) {
- return false;
- }
- newarr = this.formatItem(newarr);
- return newarr;
- }
- DataWriterbdensity.prototype.formatItem = function(arr) {
- for (var i = 0; i < arr.length; i++) {}
- return arr;
- }
- DataWriterbdensity.prototype.setDownloadData = function(c, p, data) {
- //数据按照时间倒序序进行排列
- var beg, end;
- //处理指标
- if (!is_array(data.x)) {
- return;
- }
- var store = this.getStore(c, p);
- var item;
- for (var i = 0; i < data.x.length; i++) {
- //format time
- var time = formatTime(data.x[i], p);
- store.x.push(time);
- item = data.y[i]; //this.parseItem(data[i][1]);
- if (item) store.y.push(item);
- }
- }
- function DataWriterCandle(model, name) {
- sup(this, model, name);
- this.chunks = []; //数据在服务器端的[开始,结束,total,在本地数组中的,开始位置,长度,方便删除]
- }
- ClassExtend(DataWriterCandle, DataWriter);
- //重写父类.
- //写类不能像读类一样,直接读取model.c 个 model.p
- //因为,数据属于什么类,由服务器端返回的值决定
- //
- DataWriterCandle.prototype.getStore = function(c, p) {
- this.storeSet = init_obj(this.storeSet, c, p, { time: [], ohlc: [], v: [] });
- return this.storeSet[c][p];
- }
- DataWriterCandle.prototype.setDownloadDataByOffset = function(c, p, data, options) {
- //数据按照时间倒序序进行排列
- var beg, end;
- //处理指标
- if (!is_array(data.x)) {
- return;
- }
- this.c = c;
- this.p = p;
- var store = this.getStore(c, p);
- data.x = data.x.reverse();
- data.y = data.y.reverse();
- //判断offset 是否衔接,如果不衔接,那么重置所有的数据。
- //如果衔接。要判断一下左衔接 还是 右衔接。
- //如果是左衔接,并且缓存数目超过一个配置的值,那么删除一部分数据
- //每个数据用一个chunks来表示
- options.astart = 0;
- options.alen = data.x.length;
- if (this.chunks.length && options.end + 1 == this.chunks[0].start) { //右衔接[在头部加入数据]
- var len = data.x.length;
- store.time = data.x.concat(store.time);
- store.ohlc = data.y.concat(store.ohlc);
- this.shiftLeftChunk(store, options); //把chunk往左移
- } else if (this.chunks.length && this.chunks[this.chunks.length - 1].end + 1 == options.start) { //左衔接
- var len = data.x.length;
- store.time = store.time.concat(data.x);
- store.ohlc = store.ohlc.concat(data.y);
- this.shiftRightChunk(store, options);
- } else { //不衔接
- store.time = data.x;
- store.ohlc = data.y;
- this.chunks = [];
- this.chunks[0] = options;
- }
- //更新数据offset 的范围
- this.model.leftoffset = this.chunks[this.chunks.length - 1].end;
- this.model.rightoffset = this.chunks[0].start;
- }
- DataWriterCandle.prototype.shiftLeftChunk = function(store, options) {
- //update chunk data
- for (var i = 0; i < this.chunks.length; i++) {
- this.chunks[i].astart += options.alen;
- }
- this.chunks.unshift(options);
- //更新数据指针,头部数据被加入
- this.model.point(this.model.point() + options.alen);
- if (store.time.length > this.config.Global.maxStoreChunk * this.config.Global.downloadCount) {
- var chunk = this.chunks.pop();
- store.time.splice(chunk.astart);
- store.ohlc.splice(chunk.astart);
- }
- }
- DataWriterCandle.prototype.shiftRightChunk = function(store, options) {
- //处理chunk
- var lastchunk = this.chunks[this.chunks.length - 1];
- options.astart += lastchunk.astart + lastchunk.alen;
- this.chunks.push(options);
- if (store.time.length > this.config.Global.maxStoreChunk * this.config.Global.downloadCount) {
- var chunk = this.chunks.shift();
- for (var i = 0; i < this.chunks.length; i++) {
- this.chunks[i].astart -= chunk.alen;
- }
- //头部数据被删除
- store.time.splice(0, chunk.alen);
- store.ohlc.splice(0, chunk.alen);
- //更新数据指针
- var point = this.model.point();
- point -= chunk.alen;
- this.model.point(point);
- }
- }
- DataWriterCandle.prototype.setUpdateData = function(c, p, data) {
- //更新第一个数据
- if (!is_array(data.x) || data.x.length == 0) {
- return;
- }
- var store = this.getStore(c, p);
- var mintime = data.x[0];
- data.x = data.x.reverse();
- data.y = data.y.reverse();
- if (store.time.length == 0 || parseInt(data.options.prev_calculated) == 0) {
- store.time = data.x;
- store.ohlc = data.y;
- //console.log(store.time);
- return;
- }
- var i = 0;
- while (i < store.time.length && store.time[i] >= mintime) {
- i++;
- }
- if (i == store.time.length) {
- store.time = data.x;
- store.ohlc = data.y;
- } else {
- store.time.splice(0, i);
- store.ohlc.splice(0, i);
- store.time = data.x.concat(store.time);
- store.ohlc = data.y.concat(store.ohlc);
- }
- }
- /*
- DataWriterCandle.prototype.setNewData = function(c, p, data)
- {
- console.log("newdata=",data,is_array(data),data.length);
- //更新第一个数据
- if (!is_array(data) || data.length == 0)
- {
- return;
- }
- data = data.reverse();
- var store = this.getStore(c, p);
- var time = parseInt(data[0][0]);
- while (data.length && time < store.time[0])
- {
- data.shift();
- time = parseInt(data[0][0]);
- }
- if (data.length == 0)
- {
- return;
- }
- //
- for (var i = 1; i < data[0].length; i++)
- {
- data[0][i] = parseFloat(data[0][i]);
- }
- var first = data[0].slice(1);
- if (time == store.time[0])
- {
- store.time[0] = time;
- store.ohlc[0] = first;
- } else {
- store.time.unshift(time);
- store.ohlc.unshift(first);
- }
- if (isNaN(store.ohlc[0][0]))
- {
- alert("update new NaN");
- }
- //store.v[0] = parseFloat(data[0][5]);
- for (var i = 1; i < data.length; i++)
- {
- if (!is_array(data[i]))
- {
- continue;
- }
- for (var j = 1; j < data[i].length; j++)
- {
- data[i][j] = parseFloat(data[i][j]);
- }
- store.time.unshift(parseInt(data[i][0]));
- var newdata = data[i].slice(1);
- store.ohlc.unshift(newdata);
- }
- }*/
- DataWriterCandle.prototype.setNewData = function(c, p, data) {
- //更新第一个数据
- if (!is_array(data.x) || data.x.length == 0) {
- return;
- }
- var store = this.getStore(c, p);
- var time = parseInt(data.x[0]);
- while (data.x.length && time < store.time[0]) {
- data.x.shift();
- data.y.shift();
- time = parseInt(data.x[0]);
- }
- if (data.x.length == 0) {
- return;
- }
- var first = data.y[0];
- if (time == store.time[0]) {
- store.time[0] = time;
- store.ohlc[0] = data.y[0]
- } else {
- store.time.unshift(time);
- store.ohlc.unshift(data.y[0]);
- }
- if (isNaN(store.ohlc[0][0])) {
- alert("update new NaN");
- }
- for (var i = 1; i < data.x.length; i++) {
- store.time.unshift(data.x[i]);
- store.ohlc.unshift(data.y[i]);
- }
- }
- DataWriterCandle.prototype.getX = function(c, p) {
- var store = this.getStore(c, p);
- return store.time;
- }
- DataWriterCandle.prototype.getY = function(c, p) {
- var store = this.getStore(c, p);
- return store.ohlc;
- }
- DataWriterCandle.prototype.setDownloadData = function(c, p, data) {
- //数据按照时间倒序序进行排列
- var beg, end;
- //处理指标
- if (!is_array(data)) {
- if (is_array(data.x) && is_array(data.y)) {
- var newdata = [];
- for (var i = data.x.length -1; i >= 0; i--) {
- var item = [];
- item.push(data.x[i]);
- item = item.concat(data.y[i]);
- newdata.push(item);
- }
- data = newdata;
- } else {
- return;
- }
- }
- var store = this.getStore(c, p);
- for (var i = 0; i < data.length; i++) {
- if (!is_array(data[i])) {
- continue;
- }
- for (var j = 1; j < data[i].length; j++) {
- data[i][j] = parseFloat(data[i][j]);
- }
- store.time.push(parseInt(data[i][0]));
- store.ohlc.push(data[i].slice(1));
- }
- }
- function DataWriterFractals(model, name) {
- sup(this, model, name);
- }
- ClassExtend(DataWriterFractals, DataWriter);
- DataWriterFractals.prototype.setNewData = function(c, p, data) {
- if (!is_array(data) || data.length == 0) {
- return;
- }
- //data = data.reverse();
- var store = this.getStore(c, p);
- /*
- for (var i = 0; i < data.length; i++)
- {
- if (!is_array(data[i]))
- {
- continue;
- }
- var item = this.parseItem(data[i][1]);
- var newitem;
- if (item) {} else {continue;}
- var time = formatTime(data[i][0], p);
- if (store.x[0] == time) {
- //可能会有新的买卖点
- newitem = array_diff(item, store.y[0]);
- store.y[0] = item;
- } else {
- store.x.unshift(time);
- store.y.unshift(item);
- newitem = item;
- }
- this.notify(newitem);
- }
- */
- }
- DataWriterFractals.prototype.notify = function(items) {
- if (items && items.length) {
- /*var typename = DataWriterProfit.nameMap[items[items.length - 1][0]];
- typename = typename.replace("/", "_").toLowerCase();
- var url = $("#music_list select[name="+typename+"]").val();
- playmusic(url);
- */
- }
- }
- DataWriterFractals.prototype.parseItem = function(items) {
- var newarr = [];
- var type = null;
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (item[0] == "buy" && item[1] == "open") {
- type = DataWriterProfit.BUY_OPEN;
- } else if (item[0] == "buy" && item[1] == "close") {
- type = DataWriterProfit.BUY_CLOSE;
- } else if (item[0] == "sell" && item[1] == "open") {
- type = DataWriterProfit.SELL_OPEN;
- } else if (item[0] == "sell" && item[1] == "close") {
- type = DataWriterProfit.SELL_CLOSE;
- }
- if (type) {
- newarr[i] = [type, parseFloat(item[2]), item[3]];
- }
- }
- if (newarr.length == 0) {
- return false;
- }
- newarr = this.formatItem(newarr);
- return newarr;
- }
- DataWriterFractals.prototype.formatItem = function(arr) {
- for (var i = 0; i < arr.length; i++) {}
- return arr;
- }
- DataWriterFractals.prototype.setDownloadData = function(c, p, data) {
- //数据按照时间倒序序进行排列
- var beg, end;
- //处理指标
- if (!is_array(data.x)) {
- return;
- }
- var store = this.getStore(c, p);
- var item;
- for (var i = 0; i < data.x.length; i++) {
- //format time
- var time = formatTime(data.x[i], p);
- store.x.push(time);
- item = data.y[i]; //this.parseItem(data[i][1]);
- if (item) store.y.push(item);
- }
- }
- function DataWriterKshape(model, name) {
- sup(this, model, name);
- }
- ClassExtend(DataWriterKshape, DataWriter);
- DataWriterKshape.prototype.setNewData = function(c, p, data) {
- if (!is_array(data) || data.length == 0) {
- return;
- }
- //data = data.reverse();
- var store = this.getStore(c, p);
- /*
- for (var i = 0; i < data.length; i++)
- {
- if (!is_array(data[i]))
- {
- continue;
- }
- var item = this.parseItem(data[i][1]);
- var newitem;
- if (item) {} else {continue;}
- var time = formatTime(data[i][0], p);
- if (store.x[0] == time) {
- //可能会有新的买卖点
- newitem = array_diff(item, store.y[0]);
- store.y[0] = item;
- } else {
- store.x.unshift(time);
- store.y.unshift(item);
- newitem = item;
- }
- this.notify(newitem);
- }
- */
- }
- DataWriterKshape.prototype.notify = function(items) {
- if (items && items.length) {
- /*var typename = DataWriterProfit.nameMap[items[items.length - 1][0]];
- typename = typename.replace("/", "_").toLowerCase();
- var url = $("#music_list select[name="+typename+"]").val();
- playmusic(url);
- */
- }
- }
- DataWriterKshape.prototype.parseItem = function(items) {
- var newarr = [];
- var type = null;
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (item[0] == "buy" && item[1] == "open") {
- type = DataWriterProfit.BUY_OPEN;
- } else if (item[0] == "buy" && item[1] == "close") {
- type = DataWriterProfit.BUY_CLOSE;
- } else if (item[0] == "sell" && item[1] == "open") {
- type = DataWriterProfit.SELL_OPEN;
- } else if (item[0] == "sell" && item[1] == "close") {
- type = DataWriterProfit.SELL_CLOSE;
- }
- if (type) {
- newarr[i] = [type, parseFloat(item[2]), item[3]];
- }
- }
- if (newarr.length == 0) {
- return false;
- }
- newarr = this.formatItem(newarr);
- return newarr;
- }
- DataWriterKshape.prototype.formatItem = function(arr) {
- for (var i = 0; i < arr.length; i++) {}
- return arr;
- }
- DataWriterKshape.prototype.setDownloadData = function(c, p, data) {
- //数据按照时间倒序序进行排列
- var beg, end;
- //处理指标
- if (!is_array(data.x)) {
- return;
- }
- var store = this.getStore(c, p);
- var item;
- for (var i = 0; i < data.x.length; i++) {
- //format time
- var time = formatTime(data.x[i], p);
- store.x.push(time);
- item = data.y[i]; //this.parseItem(data[i][1]);
- if (item) store.y.push(item);
- }
- }
- function DataWriterMath(model, name) {
- sup(this, model, name);
- }
- ClassExtend(DataWriterMath, DataWriter);
- function DataWriterProfit(model, name) {
- sup(this, model, name);
- }
- ClassExtend(DataWriterProfit, DataWriter);
- DataWriterProfit.BUY_OPEN = 1;
- DataWriterProfit.BUY_CLOSE = 2;
- DataWriterProfit.SELL_OPEN = 3;
- DataWriterProfit.SELL_CLOSE = 4;
- DataWriterProfit.nameMap = {
- 1: "Open/Buy",
- 2: "Close/Buy",
- 3: "Open/Sell",
- 4: "Close/Sell"
- };
- DataWriterProfit.prototype.setNewData = function(c, p, data) {
- if (!is_array(data) || data.length == 0) {
- return;
- }
- data = data.reverse();
- var store = this.getStore(c, p);
- for (var i = 0; i < data.length; i++) {
- if (!is_array(data[i])) {
- continue;
- }
- var item = this.parseItem(data[i][1]);
- var newitem;
- if (item) {} else {
- continue;
- }
- var time = formatTime(data[i][0], p);
- if (store.x[0] == time) {
- //可能会有新的买卖点
- newitem = array_diff(item, store.y[0]);
- store.y[0] = item;
- } else {
- store.x.unshift(time);
- store.y.unshift(item);
- newitem = item;
- }
- this.notify(newitem);
- }
- }
- DataWriterProfit.prototype.notify = function(items) {
- if (items && items.length) {
- var typename = DataWriterProfit.nameMap[items[items.length - 1][0]];
- typename = typename.replace("/", "_").toLowerCase();
- var url = $("#music_list select[name=" + typename + "]").val();
- // playmusic(url);
- }
- }
- DataWriterProfit.prototype.parseItem = function(items) {
- var newarr = [];
- var type = null;
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (item[0] == "buy" && item[1] == "open") {
- type = DataWriterProfit.BUY_OPEN;
- } else if (item[0] == "buy" && item[1] == "close") {
- type = DataWriterProfit.BUY_CLOSE;
- } else if (item[0] == "sell" && item[1] == "open") {
- type = DataWriterProfit.SELL_OPEN;
- } else if (item[0] == "sell" && item[1] == "close") {
- type = DataWriterProfit.SELL_CLOSE;
- }
- if (type) {
- newarr[i] = [type, parseFloat(item[2]), item[3]];
- }
- }
- if (newarr.length == 0) {
- return false;
- }
- newarr = this.formatItem(newarr);
- return newarr;
- }
- DataWriterProfit.prototype.formatItem = function(arr) {
- for (var i = 0; i < arr.length; i++) {}
- return arr;
- }
- DataWriterProfit.prototype.setDownloadData = function(c, p, data) {
- //数据按照时间倒序序进行排列
- var beg, end;
- //处理指标
- if (!is_array(data)) {
- return;
- }
- var store = this.getStore(c, p);
- var item;
- for (var i = 0; i < data.length; i++) {
- if (!is_array(data[i])) {
- continue;
- }
- //format time
- var time = formatTime(data[i][0], p);
- store.x.push(time);
- item = this.parseItem(data[i][1]);
- if (item) store.y.push(item);
- }
- }
- function DataWriterTickSource(model, name) {
- sup(this, model, name);
- this.lastSource = null;
- }
- ClassExtend(DataWriterTickSource, DataWriter);
- DataWriterTickSource.prototype.setNewData = function(c, type, data) {
- if (!is_array(data) || !is_array(data[0])) return;
- this.lastSource = type;
- var store = this.getStore(c, type);
- for (var i = 0; i < data.length; i++) {
- store.x.push(parseInt(data[i][0]) * 1000 + parseInt(data[i][1]));
- store.y.push([parseFloat(data[i][2]), parseFloat(data[i][3])]);
- }
- if (store.x.length > this.maxdata) {
- store.x = store.x.slice(this.maxdata / 2);
- store.y = store.y.slice(this.maxdata / 2);
- }
- }
- function DataReaderadx(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderadx, DataReader);
- function DataReaderAjax(model, writer, name) {
- this.isinit = false;
- sup(this, model, writer, name);
- this.data = {};
- this.lastdata = {};
- }
- ClassExtend(DataReaderAjax, DataReader);
- DataReaderAjax.prototype.setParam = function(param) {
- if (this.isinit) return;
- this.isinit = true;
- var url = param[1];
- var _this = this;
- $.get(url, function(data) {
- _this.setAjaxData(data);
- }, "json");
- }
- DataReaderAjax.prototype.setAjaxData = function(data) {
- this.data = data;
- this.model.ready = true;
- this.model.controller.flag("down");
- //this.model.ready = false; //不更新图表了
- this.main = this;
- return this;
- }
- DataReaderAjax.prototype.getX = function() {
- return this.data.x;
- }
- DataReaderAjax.prototype.getY = function() {
- return this.data.y;
- }
- DataReaderAjax.prototype.getData = function(number, readconfig) {
- var start = this.getStart(number);
- this.lastdata = this.data.y[0];
- start = this.getStart(number);
- index = 0;
- var x = [];
- var y = [];
- for (var i = start; i < this.data.x.length; i++) {
- x[index] = this.data.x[i];
- y[index] = this.data.y[i];
- index++;
- if (index >= number) {
- break;
- }
- }
- var data = {};
- data.x = x;
- data.y = array_copy2d(y);
- return data;
- }
- DataReaderAjax.prototype.last = function() {
- return this.lastdata;
- }
- DataReaderAjax.prototype.close = function(index) {
- if (!index || index < 0) index = 0;
- return this.data.y[index][Data.CLOSE];
- }
- DataReaderAjax.prototype.getEndPos = function() {
- var x = this.data.x;
- return x.length - 1;
- }
- DataReaderAjax.prototype.startXValue = function() {
- var x = this.data.x;
- return x[x.length - 1];
- }
- DataReaderAjax.prototype.endXValue = function() {
- var x = this.data.x;
- return x[0];
- }
- //现在,这样处理,一旦指标被注册了,
- //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
- //后面的数据,就会绑定在K线的下载结果里面
- //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
- //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
- //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
- function DataReaderatr(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderatr, DataReader);
- //���ڣ�����������һ��ָ�걻ע���ˣ�
- //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
- //���������ݣ��ͻ�������K�ߵ����ؽ�������
- //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
- //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
- //Ȼ�����غ�����ָ��,���ؽ����Ժϲ�������������ָ�꣬����ʼ��������
- //
- //��ȡ����ͼ������
- //
- function DataReaderbdensity(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderbdensity, DataReader);
- DataReaderbdensity.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = Infinity;
- var maxIndex=0;
- var minIndex=0;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- var nIndex = 0;
- for (var i = 0; i < y.length; i++) {
- for (var j = 0; j < y[i].length; j++) {
- nIndex = (j / 4) * 4 + 2
- if (j % 4 <= 1 && y[i][nIndex] != 0) {
- var value = y[i][j];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- if (value < ymin) {
- ymin = value;
- minIndex=i;
- }
- }
- }
- }
- console.log("ymin:"+ymin+",ymax:"+ymax);
- return [ymin, ymax,minIndex,maxIndex];
- }
- //现在,这样处理,一旦指标被注册了,
- //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
- //后面的数据,就会绑定在K线的下载结果里面
- //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
- //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
- //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
- function DataReaderBolling(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderBolling, DataReader);
- //现在,这样处理,一旦指标被注册了,
- //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
- //后面的数据,就会绑定在K线的下载结果里面
- //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
- //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
- //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
- function DataReaderBollingDesity(model, writer, name) {
- sup(this, model, writer, name);
- this.sourcedata = null;
- }
- ClassExtend(DataReaderBollingDesity, DataReader);
- DataReaderBollingDesity.prototype.formatData = function(x, y) {
- var data = {};
- data.x = x;
- data.y = y;
- data.xunit = this.xunit;
- data.yunit = this.yunit;
- data.maxX = x[0];
- data.minX = x[x.length - 1];
- data.maxIndex=0;
- data.minIndex=0;
- var min = Infinity
- var max = -Infinity;
- for (var i = 0; i < y.length; i++) {
- for (var j = 0; j < y.length; j += 2) {
- if (y[i][j] == -1) {
- continue;
- }
- if (max < y[i][j]) {
- max = y[i][j];
- data.maxIndex=i;
- }
- if (min > y[i][j]) {
- min = y[i][j];
- data.minIndex=i;
- }
- }
- }
- data.maxY = max;
- data.minY = min;
- return data;
- }
- //
- //读取蜡烛图的数据
- //
- function DataReaderCandle(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderCandle, DataReader);
- //抽象函数,不提供任何的功能。
- DataReaderCandle.prototype.getDataByNumber = function(number, readconfig) {
- if (readconfig & DataReader.EXTEND) {
- //以扩展的方式读取
- return this.getDataByNumberExtend(number, readconfig);
- }
- //普通的读取方式
- //这里,如果读取到末尾了,要修正start
- var x = new Array(number);
- var y = new Array(number);;
- var index = 0;
- start = this.getStart(number);
- for (var i = start; i < this.store.time.length; i++) {
- x[index] = this.store.time[i];
- y[index] = this.store.ohlc[i];
- index++;
- if (index >= number) {
- break;
- }
- }
- if (index < number) {
- x = x.slice(0, index - 1);
- y = y.slice(0, index - 1);
- }
- //深度复制
- y = array_copy2d(y);
- return { x: x, y: y };
- }
- DataReaderCandle.prototype.getData = function(number, readconfig) {
- return this.getDataByNumber(number, readconfig);
- }
- DataReaderCandle.prototype.getDataByNumberExtend = function(number, readconfig) {
- // console.log("number:"+number);
- var x = new Array(number);
- var y = new Array(number);
- var index = 0;
- //普通的读取方式
- //这里,如果读取到末尾了,要修正start
- var start = this.getStart(number);
- var xdata = this.writer.getX(this.c, this.p);
- var ydata = this.writer.getY(this.c, this.p);
- var length = xdata.length;
- if (length == 0) {
- return { x: [], y: [] };
- }
- x[index] = xdata[start];
- y[index] = ydata[start];
- for (var i = start; i < length - 1; i++) {
- var ctime = xdata[i]; //当前时间
- var ptime = xdata[i + 1]; //前一个时间
- //1.
- if (ctime - ptime == this.step || ctime - ptime > this.maxstep) { //连续,或者相差太大。加入
- index++;
- x[index] = xdata[i + 1];
- y[index] = ydata[i + 1];
- } else { //需要补全,x值每次 加step y用 ptime对应的值
- var close = ydata[i + 1][Data.CLOSE];
- var candle = [close, close, close, close, ydata[i + 1][Data.VOLUMES]];
- for (var newtime = xdata[i] - this.step; newtime > xdata[i + 1]; newtime -= this.step) {
- index++;
- x[index] = newtime;
- y[index] = candle;
- }
- index++;
- x[index] = xdata[i + 1];
- y[index] = ydata[i + 1];
- }
- if (index + 1 >= number) {
- break;
- }
- }
- index++;
- if (index < number) {
- x = x.slice(0, index);
- y = y.slice(0, index);
- }
- y = array_copy2d(y);
- return { x: x, y: y };
- }
- //和main的时间进行对齐,对于稀疏的数据,这个非常重要
- DataReaderCandle.prototype.extendByMain = function(xdata, ydata) {
- var mainX = this.getMainData().x;
- var x = new Array();
- var y = new Array();
- var j = 0;
- //1. 如果时间值超过了Main[0],那么直接忽略
- //2. 如果某个值开始小于main[0],那么,main 开始加。直到main[i] < 这个值。
- //3. 我们的索引加
- if (xdata.length == 0 || xdata[xdata.length - 1] > mainX[mainX.length - 1]) {
- //无效,这样的情况无法进行补全。
- return { x: [], y: [] };
- }
- //计算第一个数据
- var current = 0,
- count = 0;
- var close = ydata[current][Data.CLOSE];
- candle = [close, close, close, close, ydata[current][Data.VOLUMES]];
- for (var i = 0; i < mainX.length; i++) {
- if (xdata[current] > mainX[i]) //这样的情况是无效的,从程序的条件可以看出,current 不会越界。
- {
- while (xdata[current] > mainX[i]) {
- current++;
- }
- if (!ydata[current]) {
- alert(current); //debug 的信息
- }
- close = ydata[current][Data.CLOSE];
- candle = [close, close, close, close, ydata[current][Data.VOLUMES]];
- }
- if (mainX[i] > xdata[current]) {
- y[count++] = candle;
- } else if (mainX[i] == xdata[current]) {
- y[count++] = ydata[current];
- }
- }
- x = array_copy1d(mainX);
- y = array_copy2d(y);
- return { x: x, y: y };
- }
- DataReaderCandle.prototype.close = function(index) {
- if (!index || index < 0) index = 0;
- return this.store.ohlc[index][Data.CLOSE];
- }
- DataReaderCandle.prototype.formatData = function(x, y) {
- var data = {};
- data.x = x;
- data.y = y;
- data.xunit = this.xunit;
- data.yunit = this.yunit;
- data.maxX = x[0];
- var nLen = y.length;
- if (nLen > this.model.plotnum) {
- nLen = this.model.plotnum;
- }
- data.minX = x[nLen - 1];
- data.maxIndex=0;
- data.minIndex=0;
- var min = Infinity
- var max = -Infinity;
- //console.log("model=",this.model.plotnum,x);
- for (var i = 0; i < y.length && i < this.model.plotnum; i++)
- //for(var i=y.length-1;i>=0&& (y.length-i)<=this.model.plotnum;i--)
- {
- if (y[i][Data.HIGH] > max) {
- max = y[i][Data.HIGH];
- data.maxIndex=i;
- }
- if (y[i][Data.LOW] < min) {
- min = y[i][Data.LOW];
- data.minIndex=i;
- }
- }
- data.maxY = max;
- data.minY = min;
- return data;
- }
- DataReaderCandle.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = Infinity;
- var minIndex=0;
- var maxIndex=0;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- //for(var i=y.length-1;i>=0&& (y.length-i)<=this.model.plotnum;i--)
- for (var i = 0; i < y.length && i < this.model.plotnum; i++) {
- for (var j = 0; j < 4; j++) {
- var value = y[i][j];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- if (value < ymin) {
- ymin = value;
- minIndex=i;
- }
- }
- }
- return [ymin, ymax,minIndex,maxIndex];
- }
- function PlotEasyforex(plot, canvas) {
- this.plot = plot;
- this.canvas = canvas;
- this.last = last;
- this.initMyPlot();
- }
- //X Y 轴都要根据数据,绘制图形。
- //分离 主绘图区域 的数据 和 candle的 绘制。
- //使得数据 和 绘图分离,提高复用能力。
- //
- PlotEasyforex.prototype.initMyPlot = function() {
- }
- //���ڣ�����������һ��ָ�걻ע���ˣ�
- //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
- //���������ݣ��ͻ�������K�ߵ����ؽ�������
- //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
- //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
- //Ȼ�����غ�����ָ��,���ؽ����Ժϲ�������������ָ�꣬����ʼ��������
- //
- //��ȡ����ͼ������
- //
- function DataReaderFractals(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderFractals, DataReader);
- DataReaderFractals.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = Infinity;
- var minIndex=0;
- var maxIndex=0;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- for (var i = 0; i < y.length; i++) {
- var value = y[i][1];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- if (value < ymin) {
- ymin = value;
- minmax=i;
- }
- }
- return [ymin, ymax,minIndex,maxIndex];
- }
- function DataReaderIndicators(model, writer, name) {
- sup(this, model, writer, name);
- this.data = {};
- this.lastdata = {};
- }
- ClassExtend(DataReaderIndicators, DataReader);
- DataReaderIndicators.prototype.minmax = function(start, n) {
- var high = -Infinity;
- var low = Infinity;
- for (var i = start; i < start + n && i < this.y.length; i++) {
- if (this.y[i][Data.HIGH] > high) {
- high = this.y[i][Data.HIGH];
- }
- if (this.y[i][Data.LOW] < low) {
- low = this.y[i][Data.LOW];
- }
- }
- // console.log(this.name, high, low);
- return [high, low];
- }
- DataReaderIndicators.prototype.sum = function(start, length) {
- if (this.y.length < start + length) {
- return false;
- }
- var sum = 0;
- for (var i = start; i < start + length; i++) {
- sum += this.y[i][Data.CLOSE];
- }
- return sum;
- }
- DataReaderIndicators.prototype.setParam = function(param) {
- this.param = param;
- }
- DataReaderIndicators.prototype.setDependData = function(name, data) {
- this.data[name] = data;
- }
- //大多数指标可以这样初始化。如果子类初始化不一样,可以做处理
- DataReaderIndicators.prototype.dataInit = function(name) {
- //init 先计算前n个值
- //y是一个二维数组
- if (!name) {
- name = this.param[0][0];
- }
- if (this.data[name] && this.data[name].y) {
- //[read only] 如果需要修改,请先复制。否则会改动原始数据。
- this.y = this.data[name].y;
- this.x = this.data[name].x;
- } else {
- return false;
- }
- //默认数据源是倒序排列的
- if (this.n > this.y.length) {
- return false;
- }
- if (!this.y) {
- return false;
- }
- if (this.y && this.y.length == 0) {
- return false;
- }
- return true;
- }
- //常用指标的实现
- DataReaderIndicators.prototype.wpr = function(n) {
- var data = [];
- var minmax = this.minmax(0, n);
- var low = minmax[1];
- var high = minmax[0];
- var wr;
- if (low == high) {
- wr = 0;
- } else {
- wr = 100 * (this.y[0][Data.CLOSE] - high) / (high - low);
- }
- data.push(wr);
- var index = 0;
- for (var i = 1; i < this.y.length - n; i++) {
- index = i + n - 1; //from i to index, total n number data.
- if (this.y[index][Data.LOW] > low && this.y[index][Data.HIGH] < high && this.y[i][Data.LOW] > low && this.y[i][Data.HIGH] < high) {
- //do nothing, high and low 不会变化
- } else {
- minmax = this.minmax(i, n);
- low = minmax[1];
- high = minmax[0];
- }
- if (low == high) {
- wr = 0;
- } else {
- wr = 100 * (this.y[i][Data.CLOSE] - high) / (high - low);
- }
- data.push(wr);
- }
- //后面为空的补零,这样和时间才能对齐。
- for (var i = 0; i < n; i++) {
- data.push(0);
- }
- return data;
- }
- DataReaderIndicators.prototype.ma = function(n) {
- var avg = [];
- var sum = this.sum(0, n);
- avg.push(sum / n);
- for (var i = 1; i < this.y.length - n; i++) {
- sum -= this.y[i - 1][Data.CLOSE];
- sum += this.y[i + n - 1][Data.CLOSE];
- avg.push(sum / n);
- }
- for (var i = 0; i < n; i++) {
- avg.push(0);
- }
- return avg;
- }
- DataReaderIndicators.prototype.strength = function(n) {
- var data = [];
- var high = -Infinity;
- var low = Infinity;
- var index, item;
- for (var i = 0; i < this.y.length - n; i++) {
- index = i + n - 1;
- item = this.y[i][Data.CLOSE] - this.y[index][Data.CLOSE];
- if (high < item) {
- high = item;
- }
- if (low > item) {
- low = item;
- }
- data.push(item);
- }
- for (var i = 0; i < data.length; i++) {
- data[i] = (data[i] / (high - low)) * 100;
- }
- //后面为空的补零,这样和时间才能对齐。
- for (var i = 0; i < n; i++) {
- data.push(0);
- }
- return data;
- }
- DataReaderIndicators.prototype.last = function() {
- return this.lastdata;
- }
- //���ڣ�����������һ��ָ�걻ע���ˣ�
- //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
- //���������ݣ��ͻ�������K�ߵ����ؽ�������
- //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
- //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
- //Ȼ�����غ�����ָ��,���ؽ����Ժϲ�������������ָ�꣬����ʼ��������
- //
- //��ȡ����ͼ������
- //
- function DataReaderKshape(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderKshape, DataReader);
- DataReaderKshape.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = Infinity;
- var maxIndex=0;
- var minIndex=0;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- for (var i = 0; i < y.length; i++) {
- var value = y[i][0];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- if (value < ymin) {
- ymin = value;
- minIndex=i;
- }
- }
- //console.log(ymax)
- //console.log(ymin)
- return [ymin, ymax,minIndex,maxIndex];
- }
- function DataReaderMa(data, period, shift) {
- if (!period) {
- period = 14;
- }
- if (!shift) {
- shift = 0;
- }
- this.data = data;
- this.period = period;
- $.cookie('period',period);
- this.shift = shift;
- this.X = [];
- this.Y = [];
- }
- ClassExtend(DataReaderMa, DataReader);
- DataReaderMa.prototype.calc = function(start, count, time, data) {
- //计算移动平均线
- //start:
- var sum = 0;
- var i, j;
- for (i = start, j = 0; j < count; i++, j++) {
- this.X[j] = time[i];
- }
- }
- //现在,这样处理,一旦指标被注册了,
- //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
- //后面的数据,就会绑定在K线的下载结果里面
- //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
- //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
- //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
- function DataReaderMacd(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderMacd, DataReader);
- function DataReaderMaex(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderMaex, DataReader);
- function DataReaderMath(model, writer, name) {
- this.data = {};
- this.lastdata = {};
- sup(this, model, writer, name);
- this.start = 0;
- this.end = 0;
- this.number = 0;
- this.xunit = 0;
- this.yunit = 0;
- }
- ClassExtend(DataReaderMath, DataReader);
- //对数学公式来说,只要设置一个 x轴的区间 和 要划分的 数目就可以了
- DataReaderMath.prototype.setXArea = function(start, end, number) {
- this.start = start;
- this.end = end;
- this.number = number;
- if (number <= 0) {
- return;
- }
- var x = [];
- var step = (this.end - this.start) / this.number;
- var i = this.start;
- while (i <= this.end) {
- x.push(i);
- i += step;
- }
- this.data.x = x.reverse();
- }
- DataReaderMath.prototype.setParam = function(param) {
- if (param.length >= 2) {
- param = param[1].split(",");
- for (var i = 0; i < param.length; i++) {
- param[i] = parseInt(param[i]);
- }
- this.setXArea(param[0], param[1], param[2]);
- }
- }
- DataReaderMath.prototype.last = function() {
- return this.lastdata;
- }
- DataReaderMath.prototype.getEndPos = function() {
- var x = this.data.x;
- return x.length - 1;
- }
- DataReaderMath.prototype.startXValue = function() {
- var x = this.data.x;
- return x[x.length - 1];
- }
- DataReaderMath.prototype.endXValue = function() {
- var x = this.data.x;
- return x[0];
- }
- DataReaderMath.prototype.formatData = function(x, y) {
- var data = {};
- data.x = x;
- data.y = y;
- data.maxX = x[0];
- data.minX = x[x.length - 1];
- data.maxIndex=0;
- data.minIndex=0;
- var _minmax = minmax(y);
- data.maxY = _minmax[1];
- data.minY = _minmax[0];
- data.maxIndex=_minmax[3];
- data.minIndex=_minmax[2];
- data.xunit = this.getUnit(data.minX, data.maxX);
- data.yunit = this.getUnit(data.minY, data.maxY);
- return data;
- }
- DataReaderMath.prototype.getUnit = function(min, max) {
- var step = (max - min) / this.number;
- return Math.pow(10, Math.floor(Math.log(step) / Math.LN10));
- }
- //现在,这样处理,一旦指标被注册了,
- //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
- //后面的数据,就会绑定在K线的下载结果里面
- //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
- //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
- //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
- function DataReaderOrder(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderOrder, DataReader);
- //
- //读取蜡烛图的数据
- //
- function DataReaderProfit(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderProfit, DataReader);
- DataReaderProfit.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = Infinity;
- var maxIndex=0;
- var minIndex=0;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- for (var i = 0; i < y.length; i++) {
- for (var j = 0; j < y[i].length; j++) {
- var value = y[i][j][1];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- if (value < ymin) {
- ymin = value;
- minIndex=i;
- }
- }
- }
- return [ymin, ymax,minIndex,maxIndex];
- }
- function DataReaderTickSource(model, writer, name) {
- sup(this, model, writer, name);
- this.maxdata = this.config[name].maxdata;
- this.data = {};
- this.cmd = "";
- this.number = 60;
- this.nameToId = { 'FXDD': 0, 'FXPRO': 1, 'EXNESS': 2, 'IRONFX': 3, "FXCM": 4 };
- this.idToName = ['FXDD', 'FXPRO', 'EXNESS', 'IRONFX', "FXCM"];
- this.microsecond = 0;
- this.lastStatus = { width: {}, offset: {}, time: {}, quick: { queue: {}, inquick: false } };
- this.lastdata;
- }
- ClassExtend(DataReaderTickSource, DataReader);
- DataReaderTickSource.prototype.setParam = function(param) {
- this.param = param;
- var cmd = this.param[1].split(",");
- var tmp = cmd.shift();
- tmp = tmp.split("/");
- this.bidask = tmp[0];
- this.number = parseInt(tmp[1]);
- this.microsecond = parseInt(tmp[2]);
- if (!this.c) {
- return;
- }
- var r = [];
- for (var i = 0; i < cmd.length; i++) {
- r.push(this.c + "_" + cmd[i]);
- }
- this.cmd = "tick_source:" + r.join(",");
- }
- DataReaderTickSource.prototype.getWSCmd = function() {
- this.setParam(this.param);
- return this.cmd;
- }
- DataReaderTickSource.prototype.getData = function() {
- var type, id;
- var store, len;
- var x, y, bidask;
- var data = { x: [], y: {} };
- this.lastdata = {};
- this.lastStatus.time[this.writer.lastSource] = now();
- for (var i = 0; i < this.idToName.length; i++) {
- x = [];
- y = [];
- type = this.idToName[i];
- id = this.nameToId[type];
- store = this.writer.getStore(this.c, type);
- len = store.x.length;
- if (len == 0) {
- continue;
- }
- if (this.bidask == "bid") {
- bidask = 0;
- } else if (this.bidask == "bid-ask") {
- bidask = -1;
- } else {
- bidask = 1;
- }
- this.lastdata[type] = {};
- this.lastdata[type].bidask = store.y[len - 1];
- for (var j = 0; j < this.number && j < len; j++) {
- var second = store.x[len - 1 - j];
- if (this.microsecond) {
- x[j] = second;
- } else {
- x[j] = parseInt(second / 1000) * 1000;
- }
- if (bidask < 0) {
- y[j] = (store.y[len - 1 - j][0] + store.y[len - 1 - j][1]) / 2;
- } else {
- y[j] = store.y[len - 1 - j][bidask];
- }
- }
- this.lastdata[type].x = x[0];
- this.lastdata[type].y = y[0];
- data.y[type] = { x: x, y: y };
- }
- return data;
- }
- DataReaderTickSource.prototype.formatData = function(x, y) {
- var minX = Infinity;
- var minY = Infinity;
- var maxX = -Infinity;
- var maxY = -Infinity;
- var hasdata = false;
- var len = 0;
- for (var type in y) {
- if (!is_object(y[type])) continue;
- len = y[type].x.length;
- if (len == 0) {
- continue;
- }
- hasdata = true;
- var data = this._formatData(y[type].x, y[type].y);
- if (minX > data.minX) minX = data.minX;
- if (minY > data.minY) minY = data.minY;
- if (maxX < data.maxX) maxX = data.maxX;
- if (maxY < data.maxY) maxY = data.maxY;
- }
- if (!hasdata) {
- return { x: [], y: [] };
- }
- var data = this.lastInfo();
- data.x = [minX, maxX];
- data.xunit = 1;
- data.yunit = this.yunit;
- data.minX = minX;
- data.minY = minY;
- data.maxY = maxY;
- data.maxX = maxX;
- data.y = [minY, maxY]
- data.data = y;
- return data;
- }
- DataReaderTickSource.prototype.last = function() {
- return this.lastdata;
- }
- DataReaderTickSource.prototype.lastInfo = function() {
- //计算平均值
- var avg = 0;
- var num = 0;
- var timemax = -Infinity;
- var timemin = Infinity;
- var tick_timemax = -Infinity;
- var tick_timemin = Infinity;
- var maxname, minname;
- var tick_maxname, tick_minname;
- var last = this.lastdata;
- for (var key in last) {
- if (!is_object(last[key])) {
- continue;
- }
- if (this.lastStatus.time[key] > timemax) {
- timemax = this.lastStatus.time[key];
- maxname = key;
- }
- if (this.lastStatus.time[key] < timemin) {
- timemin = this.lastStatus.time[key];
- minname = key;
- }
- if (last[key].x > tick_timemax) {
- tick_timemax = last[key].x;
- tick_maxname = key;
- }
- if (last[key].x < tick_timemin) {
- tick_timemin = last[key].x;
- tick_minname = key;
- }
- if (typeof this.lastStatus.width[key] === "undefined") {
- this.lastStatus.width[key] = 3;
- }
- num++;
- avg += last[key].y;
- }
- avg = avg / num;
- this.lastStatus.offset.local = now() - tick_timemax;
- this.lastStatus.offset.delt = timemax - timemin;
- //存在突破,要显示最后的bid ask 时间
- if (this.lastStatus.quick.inquick == true) {
- var quick = this.lastStatus.quick;
- quick.queue[this.writer.lastSource] = 1;
- qnumber = 0;
- for (var key in quick.queue) {
- if (quick.queue[key] === 1) {
- qnumber++;
- }
- }
- if (qnumber == num) {
- quick.end = maxname;
- quick.inquick = false;
- quick.delt = this.lastStatus.time[quick.end] - this.lastStatus.time[quick.start];
- }
- }
- var show = false;
- var point = Math.abs(Math.floor(last[maxname].y / this.yunit) - Math.floor(avg / this.yunit));
- if (this.lastStatus.quick.inquick == false && point >= 4) {
- show = true;
- this.lastStatus.quick = {};
- this.lastStatus.quick.bidask = {};
- this.lastStatus.quick.start = maxname;
- this.lastStatus.quick.inquick = true;
- this.lastStatus.quick.queue = {};
- this.lastStatus.quick.point = point;
- this.lastStatus.quick.queue[maxname] = 1;
- for (var key in this.lastStatus.width) {
- if (this.lastStatus.width[key] === 6) this.lastStatus.width[key] = 3;
- this.lastStatus.quick.bidask[key] = this.lastdata[key] ? this.lastdata[key].bidask : [];
- }
- this.lastStatus.width[maxname] = 6;
- }
- if (Math.abs(Math.floor(last[minname].y / this.yunit) - Math.floor(avg / this.yunit)) >= 4) {
- show = true;
- for (var key in this.lastStatus.width) {
- if (this.lastStatus.width[key] === 0.5) this.lastStatus.width[key] = 3;
- }
- this.lastStatus.width[minname] = 0.5;
- }
- this.lastStatus.show = show;
- return this.lastStatus;
- //计算最快值和最慢值
- }
- function PlotCandleBollingDesity(plot, canvas) {
- this.name = "BollingDesity";
- this.plot = plot;
- this.grid = this.plot.grid;
- this.api = plot.api;
- this.time = [];
- this.data = []; //所有的数据
- this.cdata = new Point([], []); //当前要绘制的点
- this.config = {
- Long: { Up: 0, Low: 2, Color: "Yellow" },
- Mid1: { Up: 4, Low: 6, Color: "Red" },
- Mid2: { Up: 8, Low: 10, Color: "Purple" },
- Short1: { Up: 12, Low: 14, Color: "Green" },
- Short2: { Up: 16, Low: 18, Color: "LightSeaGreen" }
- };
- this.init = false;
- this.databuf = [];
- }
- //PlotCandle 有一个指标列表,在相应的处理上,加上这个这些接口
- //提供下面的接口,用于下载数据,更新数据: 先更新time_start 和 mid_time
- //再更新剩下来的部分
- PlotCandleBollingDesity.prototype.init = function(time_start, mid_time, time_end) {
- if (time_start == mid_time) {
- this.initComplete();
- return;
- }
- var _this = this;
- $.get(this.api, { action: 'indicator', name: this.name, 'ts': time_start, 'te': mid_time }, function(data) {
- _this.processHistoryData(data);
- if (mid_time == time_end) {
- this.initComplete();
- }
- }, 'json');
- if (mid_time < time_end) {
- $.get(this.api, { action: 'indicator', name: this.name, 'ts': mid_time + 1, 'te': time_end }, function(data) {
- _this.processHistoryData(data);
- //处理原来下载的数据
- this.initComplete();
- }, 'json');
- }
- }
- PlotCandleBollingDesity.prototype.initComplete = function() {
- for (var i = 0; i < this.databuf.length; i++) {
- this.processHistoryData(this.databuf[i]);
- }
- this.databuf = [];
- this.init = true;
- }
- PlotCandleBollingDesity.prototype.draw = function() {
- var X = array_copy(this.cdata.x);
- var Y = array_copy(this.cdata.y);
- //分成5种线来绘制
- var yset = {};
- for (var i = 0; i < X.length; i++) {
- for (var key in this.config) {
- if (typeof key == "string" && key != "undefined") {
- var max_index = this.config[key].Up;
- var min_index = this.config[key].Low;
- var color = this.config[key].Color;
- if (yset[key] === undefined) {
- yset[key] = {};
- }
- if (Y[i][max_index] != 0) {
- if (yset[key].Up === undefined) {
- yset[key].Up = new Point([], [], []);
- }
- yset[key].Up.x.push(X[i]);
- yset[key].Up.y.push(Y[i][max_index]);
- yset[key].Up.z.push(Y[i][max_index + 1]);
- }
- if (Y[i][min_index] != 0) {
- if (yset[key].Low === undefined) {
- yset[key].Low = new Point([], [], []);
- }
- yset[key].Low.x.push(X[i]);
- yset[key].Low.y.push(Y[i][min_index]);
- yset[key].Low.z.push(Y[i][min_index + 1]);
- }
- }
- }
- }
- var minmax = this.getMinMaxDensity();
- for (var key in yset) {
- if (typeof key == "string" && key != "undefined") {
- if (yset[key].Up) {
- this.drawOne(yset[key].Up, this.config[key].Color, minmax);
- }
- if (yset[key].Low) {
- this.drawOne(yset[key].Low, this.config[key].Color, minmax);
- }
- }
- }
- }
- PlotCandleBollingDesity.prototype.getLineHeight = function(min, max, data) {
- for (var i = 0; i < data.length; i++) {
- data[i] = Math.floor(((data[i] - min) / (max - min)) * 5) + 1;
- }
- return data;
- }
- PlotCandleBollingDesity.prototype.drawOne = function(data, color, minmax) {
- data.y = this.grid.getY(data.y);
- data.z = this.getLineHeight(minmax[0], minmax[1], data.z);
- var ctx = this.grid.ctx;
- ctx.fillStyle = color;
- for (var i = 0; i < data.x.length; i++) {
- ctx.fillRect(data.x[i] - this.plot.box_pixel, data.y[i] - data.z[i], 2 * this.plot.box_pixel + 1, data.z[i]);
- }
- }
- PlotCandleBollingDesity.prototype.updateNew = function(time) {
- //do nothing
- }
- PlotCandleBollingDesity.prototype.down = function(time_start, time_end) {
- var _this = this;
- $.get(this.api, { action: 'indicator', name: this.name, 'ts': time_start, 'te': time_end }, function(data) {
- if (this.init) {
- _this.processHistoryData(data);
- } else {
- _this.databuf.push(data);
- }
- }, 'json');
- }
- PlotCandleBollingDesity.prototype.processHistoryData = function(data) {
- var newdata = data[this.name];
- if (!is_array(newdata) || newdata.length == 0) {
- return;
- }
- for (var i = 0; i < newdata.length; i++) {
- var item = newdata[i];
- this.time.push(parseInt(item.pop()));
- var flag = item.shift();
- if (flag == null) {
- item = null;
- } else {
- for (var j = 0; j < item.length; j++) {
- item[j] = parseFloat(item[j]);
- }
- }
- this.data.push(item);
- }
- }
- PlotCandleBollingDesity.prototype.getDrawData = function(start_index, end_index) {
- var y = this.data.slice(start_index, end_index + 1);
- this.cdata.y = [];
- this.cdata.x = [];
- for (var i = 0; i < y.length - 1; i++) {
- if (y[i] != null) {
- this.cdata.y.push(y[i]);
- this.cdata.x.push(this.plot.X[i]);
- }
- }
- return this.cdata;
- }
- PlotCandleBollingDesity.prototype.getMinMax = function() {
- var data = this.cdata.y;
- var max = -Infinity;
- var min = Infinity;
- for (var i = 0; i < data.length; i++) {
- for (var key in this.config) {
- if (typeof key == "string" && key != "undefined") {
- var max_index = this.config[key].Up;
- var min_index = this.config[key].Low;
- if (data[i][max_index] > 0 && max < data[i][max_index]) {
- max = data[i][max_index]
- }
- if (data[i][min_index] > 0 && min > data[i][min_index]) {
- min = data[i][min_index];
- }
- }
- }
- }
- return [min, max];
- }
- PlotCandleBollingDesity.prototype.getMinMaxDensity = function() {
- var data = this.cdata.y;
- var max = -Infinity;
- var min = Infinity;
- for (var i = 0; i < data.length; i++) {
- for (var key in this.config) {
- if (typeof key == "string" && key != "undefined") {
- var max_index = this.config[key].Up;
- var min_index = this.config[key].Low;
- max = Math.max(max, data[i][max_index + 1], data[i][min_index + 1]);
- min = Math.min(min, data[i][max_index + 1], data[i][min_index + 1]);
- }
- }
- }
- return [min, max];
- }
- //arr 从小到大
- //reverse = true arr 从大到小
- function bsearch(arr, match, reverse) {
- var start = 0;
- var end = arr.length - 1;
- if (!reverse) {
- reverse = false;
- }
- while (start <= end) {
- mid = Math.floor((end - start) / 2) + start;
- if (arr[mid] > match) {
- if (reverse) {
- start = mid + 1;
- } else {
- end = mid - 1;
- }
- } else if (arr[mid] < match) {
- if (reverse) {
- end = mid - 1;
- } else {
- start = mid + 1;
- }
- } else { //macth
- return mid;
- }
- }
- return -1;
- }
- //
- //读取蜡烛图的数据
- //
- function DataReaderTrendLine(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderTrendLine, DataReader);
- DataReaderTrendLine.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = Infinity;
- var maxIndex=0;
- var minIndex=0;
- //console.log("DataReaderTrendLine.prototype.getYminmax");
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- for (var i = 0; i < y.length; i++) {
- var value = y[i][0];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- if (value < ymin) {
- ymin = value;
- minIndex=i;
- }
- }
- return [ymin, ymax,minIndex,maxIndex];
- }
- //���ڣ�����������һ��ָ�걻ע���ˣ�
- //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
- //���������ݣ��ͻ�������K�ߵ����ؽ�������
- //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
- //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
- //Ȼ�����غ�����ָ��,���ؽ����Ժϲ�������������ָ�꣬����ʼ��������
- //
- //��ȡ����ͼ������
- //
- function DataReadervolumes(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReadervolumes, DataReader);
- DataReadervolumes.prototype.getDataByMain = function(readconfig) {
- this.mainData = this.getMainData();
- //var start = this.mainData.x[this.mainData.x.length - 1];
- //var end = this.mainData.x[0];
- var x = new Array();
- var y = new Array();
- for (var i = 0; i < this.mainData.x.length && i < this.model.plotnum; i++) {
- x.push(this.mainData.x[i]);
- if (this.mainData.y[i][Data.OPEN] <= this.mainData.y[i][Data.CLOSE]) {
- y.push([this.mainData.y[i][4]]);
- } else {
- y.push([this.mainData.y[i][4], 0]);
- }
- }
- y = array_copy(y);
- return { x: x, y: y };
- }
- DataReadervolumes.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = 0;
- var minIndex=0;
- var maxIndex=0;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- for (var i = 0; i < y.length && i < this.model.plotnum; i++)
- //for(var i=y.length-1;i>=0&& (y.length-i)<=this.model.plotnum;i--)
- {
- var value = y[i][0];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- }
- return [0, ymax,minIndex,maxIndex];
- }
- //���ڣ�����������һ��ָ�걻ע���ˣ�
- //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
- //���������ݣ��ͻ�������K�ߵ����ؽ�������
- //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
- //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
- //Ȼ�����غ�����ָ��,���ؽ����Ժϲ�������������ָ�꣬����ʼ��������
- //
- //��ȡ����ͼ������
- //
- function DataReadervolumes2(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReadervolumes2, DataReader);
- DataReadervolumes2.prototype.getDataByMain = function(readconfig) {
- this.mainData = this.getMainData();
- var x = new Array();
- var y = new Array();
- for (var i = 0; i < this.mainData.x.length && i < this.model.plotnum; i++) {
- x.push(this.mainData.x[i]);
- y.push([this.mainData.y[i][5]]);
- }
- y = array_copy(y);
- return { x: x, y: y };
- }
- DataReadervolumes2.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = Infinity;
- var minIndex=0;
- var maxIndex=0;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- //for(var i=y.length-1;i>=0&& (y.length-i)<=this.model.plotnum;i--)
- for (var i = 0; i < y.length && i < this.model.plotnum; i++) {
- var value = y[i][0];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- if (value < ymin) {
- ymin = value;
- minIndex=i;
- }
- }
- return [0, ymax,minIndex,maxIndex];
- }
- function DataReaderWave(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderWave, DataReader);
- //���ڣ�����������һ��ָ�걻ע���ˣ�
- //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
- //���������ݣ��ͻ�������K�ߵ����ؽ�������
- //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
- //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
- //Ȼ�����غ�����ָ��,���ؽ����Ժϲ�������������ָ�꣬����ʼ��������
- //
- //��ȡ����ͼ������
- //
- function DataReaderwdensity(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderwdensity, DataReader);
- DataReaderwdensity.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var ymin = Infinity;
- var minIndex=0;
- var maxIndex=0;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- for (var i = 0; i < y.length; i++) {
- for (var j = 0; j < y[i].length / 2; j++) {
- if (y[i][j * 2] != 0 && y[i][j * 2 + 1] != 0) {
- var value = y[i][j * 2];
- if (value > ymax) {
- ymax = value;
- maxIndex=i;
- }
- if (value < ymin) {
- ymin = value;
- minIndex=i;
- }
- }
- }
- }
- return [ymin, ymax,minIndex,maxIndex];
- }
- //现在,这样处理,一旦指标被注册了,
- //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
- //后面的数据,就会绑定在K线的下载结果里面
- //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
- //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
- //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
- function DataReaderWpr(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderWpr, DataReader);
- function DataReaderMathCos(model, writer, name) {
- sup(this, model, writer, name);
- this.setXArea(-10, 10, 100);
- }
- ClassExtend(DataReaderMathCos, DataReaderMath);
- DataReaderMathCos.prototype.getData = function() {
- if (this.number <= 0 || this.start == this.end) {
- return { x: [], y: [] };
- }
- var y = [];
- var x = this.data.x;
- for (var i = 0; i < x.length; i++) {
- y.push(Math.cos(x[i]));
- }
- this.lastdata = y[0];
- this.data.y = y;
- return this.data;
- }
- function DataReaderMathSin(model, writer, name) {
- sup(this, model, writer, name);
- this.setXArea(-10, 10, 100);
- }
- ClassExtend(DataReaderMathSin, DataReaderMath);
- DataReaderMathSin.prototype.getData = function() {
- if (this.number <= 0 || this.start == this.end) {
- return { x: [], y: [] };
- }
- var x = this.data.x;
- var y = [];
- for (var i = 0; i < x.length; i++) {
- y.push(Math.sin(x[i]));
- }
- this.lastdata = y[0];
- this.data.y = y;
- return this.data;
- }
- function DataReaderIndicatorsBolling(model, writer, name) {
- sup(this, model, writer, name);
- this.nPeriod = 12;
- this.nDev = 2;
- this.vlast = [0, 0, 0];
- }
- ClassExtend(DataReaderIndicatorsBolling, DataReaderIndicators);
- DataReaderIndicatorsBolling.prototype.setParam = function(param) {
- //这个函数里面做一定的初始化工作。特别是shift
- this.param = param;
- n = param[1].split(",");
- this.nPeriod = parseInt(n[0]);
- this.nDev = parseInt(n[1]);
- this.shift = this.nPeriod;
- }
- DataReaderIndicatorsBolling.prototype.getData = function() {
- var mx = this.model.maindata.x;
- var my = this.model.maindata.y
- if (mx.length < this.nPeriod) {
- return { x: [], y: [] };
- }
- var sum = 0;
- for (var i = 0; i < this.nPeriod; i++) {
- sum += my[i][Data.CLOSE];
- }
- var avg = [];
- var matime = [];
- var sma = 0.0,
- dev = 0.0;
- sma = sum / this.nPeriod;
- for (var i = 0; i < this.nPeriod; i++) {
- dev += Math.pow((my[i][Data.CLOSE] - sma), 2);
- }
- dev = Math.sqrt(dev / this.nPeriod);
- avg.push([sma, (sma + this.nDev * dev), (sma - this.nDev * dev)]);
- matime.push(mx[0]);
- for (var i = 1; i <= (mx.length - this.nPeriod) && i < this.model.plotnum; i++) {
- sum -= my[i - 1][Data.CLOSE];
- sum += my[i + this.nPeriod - 1][Data.CLOSE];
- sma = sum / this.nPeriod;
- dev = 0;
- for (var j = 0; j < this.nPeriod; j++) {
- dev += Math.pow((my[i + j][Data.CLOSE] - sma), 2);
- }
- dev = Math.sqrt(dev / this.nPeriod);
- avg.push([sma, (sma + this.nDev * dev), (sma - this.nDev * dev)]);
- matime.push(mx[i]);
- }
- this.vlast = [sma, (sma + this.nDev * dev), (sma - this.nDev * dev)];
- return { x: matime, y: avg };
- }
- DataReaderIndicatorsBolling.prototype.last = function() {
- return this.vlast;
- }
- function DataReaderIndicatorsDWPR(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderIndicatorsDWPR, DataReaderIndicators);
- //对指标,数据部分由
- DataReaderIndicatorsDWPR.prototype.setN = function(n) {
- this.n = parseInt(n);
- this.shift = parseInt(n);
- }
- DataReaderIndicatorsDWPR.prototype.setParam = function(param) {
- //这个函数里面做一定的初始化工作。特别是shift
- this.param = param;
- this.n = param[1].split(",");
- this.n[0] = parseInt(this.n[0]);
- this.n[1] = parseInt(this.n[1]);
- this.reffer = this.param[0];
- this.shift = Math.max(this.n[0], this.n[1]);
- }
- DataReaderIndicatorsDWPR.prototype.getData = function() {
- //
- if (!this.dataInit(this.reffer[0])) {
- return { x: [], y: [] };
- }
- var data1 = this.wpr(this.n[0]);
- if (!this.dataInit(this.reffer[1])) {
- return { x: [], y: [] };
- }
- var data2 = this.wpr(this.n[1]);
- if (data1.length != data2.length) {
- return { x: [], y: [] };
- }
- var data = [];
- for (var i = 0; i < data1.length; i++) {
- data[i] = data1[i] - data2[i];
- }
- this.lastdata = data[0];
- return { x: this.x, y: data };
- }
- function DataReaderIndicatorsKDJ(model, writer, name) {
- sup(this, model, writer, name);
- this.nPeriod = 9;
- this.factor_1 = 2.0 / 3.0;
- this.factor_2 = 1.0 / 3.0;
- this.vlast = [0, 0, 0];
- }
- ClassExtend(DataReaderIndicatorsKDJ, DataReaderIndicators);
- DataReaderIndicatorsKDJ.prototype.setParam = function(param) {
- //这个函数里面做一定的初始化工作。特别是shift
- this.param = param;
- n = param[1].split(",");
- this.nPeriod = parseInt(n[0]);
- this.shift = this.nPeriod;
- }
- DataReaderIndicatorsKDJ.prototype.getData = function() {
- var mx = this.model.maindata.x.reverse();
- var my = this.model.maindata.y.reverse();
- if (mx.length < this.nPeriod) {
- return { x: [], y: [] };
- }
- var k, d, j, rsv;
- var yvalue = [];
- var matime = [];
- var cn, ln, hn;
- var kpre = 50;
- var dpre = 50;
- for (i = this.nPeriod - 1; i < mx.length; i++) {
- ln = Infinity;
- hn = -Infinity;
- cn = my[i][Data.CLOSE];
- for (j = 0; j < this.nPeriod; j++) {
- if (ln > my[i - j][Data.LOW]) {
- ln = my[i - j][Data.LOW];
- }
- if (hn < my[i - j][Data.HIGH]) {
- hn = my[i - j][Data.HIGH];
- }
- }
- if ((hn - ln) == 0) {
- rsv = 50;
- } else {
- rsv = (cn - ln) / (hn - ln) * 100;
- }
- k = this.factor_1 * kpre + this.factor_2 * rsv;
- d = this.factor_1 * dpre + this.factor_2 * k;
- j = 3 * d - 2 * k;
- kpre = k;
- dpre = d;
- yvalue.push([k, d, j]);
- matime.push(mx[i]);
- }
- matime = matime.reverse();
- yvalue = yvalue.reverse();
- this.vlast = [k, d, j];
- return { x: matime, y: yvalue };
- }
- DataReaderIndicatorsKDJ.prototype.last = function() {
- return this.vlast;
- }
- function DataReaderIndicatorsMa(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderIndicatorsMa, DataReaderIndicators);
- //对指标,数据部分由
- DataReaderIndicatorsMa.prototype.setN = function(n) {
- this.n = parseInt(n);
- this.shift = parseInt(n);
- }
- DataReaderIndicatorsMa.prototype.setParam = function(param) {
- //这个函数里面做一定的初始化工作。特别是shift
- this.param = param;
- this.setN(this.param[1]);
- }
- DataReaderIndicatorsMa.prototype.getData = function() {
- var mx = this.model.maindata.x;
- var my = this.model.maindata.y
- if (mx.length < this.n) {
- return { x: [], y: [] };
- }
- var sum = 0;
- //---- initial accumulation
- //移动平均线的做法:前n个平均数目,那可以从 0 遍历到 length - this.n
- //和一般求解指标不同,我这里采用倒过来求解的办法
- //先初始化平均值
- for (var i = 0; i < this.n; i++) {
- sum += my[i][Data.CLOSE];
- }
- var avg = [];
- var matime = [];
- avg.push(sum / this.n);
- matime.push(mx[0]);
- for (var i = 1; i <= (mx.length - this.n) && i < this.model.plotnum; i++) {
- sum -= my[i - 1][Data.CLOSE];
- sum += my[i + this.n - 1][Data.CLOSE];
- avg.push(sum / this.n);
- matime.push(mx[i]);
- }
- //后面为空的补零,这样和时间才能对齐。
- /*for (var i = 0; i < this.n; i++)
- {
- avg.push(0);
- }*/
- this.lastdata = avg[0];
- return { x: matime, y: avg };
- }
- function DataReaderIndicatorsMacd(model, writer, name) {
- sup(this, model, writer, name);
- this.nFastPeriod = 12;
- this.nSlowPeriod = 26;
- this.nSignalPeriod = 9;
- this.vlast = [0, 0];
- }
- ClassExtend(DataReaderIndicatorsMacd, DataReaderIndicators);
- DataReaderIndicatorsMacd.prototype.setParam = function(param) {
- //这个函数里面做一定的初始化工作。特别是shift
- this.param = param;
- n = param[1].split(",");
- this.nFastPeriod = parseInt(n[0]);
- this.nSlowPeriod = parseInt(n[1]);
- if (this.nFastPeriod > this.nSlowPeriod) {
- nTmp = this.nFastPeriod;
- this.nFastPeriod = this.nSlowPeriod;
- this.nSlowPeriod = nTmp;
- }
- this.nSignalPeriod = parseInt(n[2]);
- this.shift = this.nSlowPeriod + this.nSignalPeriod;
- }
- DataReaderIndicatorsMacd.prototype.getData = function() {
- var mx = this.model.maindata.x;
- var my = this.model.maindata.y
- if (mx.length < this.shift) {
- return { x: [], y: [] };
- }
- var sumfast = 0.0;
- for (var i = 1; i <= this.nFastPeriod; i++) {
- sumfast += my[mx.length - i][Data.CLOSE];
- }
- var sumslow = sumfast;
- var vfast = sumfast / this.nFastPeriod;
- var prfast = 2.0 / (this.nFastPeriod + 1.0);
- for (var i = this.nFastPeriod + 1; i <= this.nSlowPeriod; i++) {
- sumslow += my[mx.length - i][Data.CLOSE];
- vfast = vfast * (1 - prfast) + prfast * my[mx.length - i][Data.CLOSE];
- }
- var vslow = sumslow / this.nSlowPeriod;
- var prslow = 2.0 / (this.nSlowPeriod + 1.0);
- var matime = [];
- var macdy = [];
- matime.push(mx[mx.length - this.nSlowPeriod]);
- macdy.push([vfast - vslow, NaN]);
- var summacd = vfast - vslow;
- for (var i = this.nSlowPeriod + 1; i < this.nSlowPeriod + this.nSignalPeriod; i++) {
- vfast = vfast * (1 - prfast) + prfast * my[mx.length - i][Data.CLOSE];
- vslow = vslow * (1 - prslow) + prslow * my[mx.length - i][Data.CLOSE];
- summacd += vfast - vslow;
- matime.push(mx[mx.length - i]);
- if (i < (this.nSlowPeriod + this.nSignalPeriod - 1)) {
- macdy.push([vfast - vslow, NaN]);
- } else {
- macdy.push([vfast - vslow, summacd / this.nSignalPeriod]);
- }
- }
- for (var i = this.nSlowPeriod + this.nSignalPeriod; i <= mx.length; i++) {
- vfast = vfast * (1 - prfast) + prfast * my[mx.length - i][Data.CLOSE];
- vslow = vslow * (1 - prslow) + prslow * my[mx.length - i][Data.CLOSE];
- summacd += vfast - vslow;
- summacd -= macdy[macdy.length - this.nSignalPeriod][0];
- matime.push(mx[mx.length - i]);
- macdy.push([vfast - vslow, summacd / this.nSignalPeriod]);
- }
- this.vlast = [vfast - vslow, summacd / this.nSignalPeriod]
- return { x: matime, y: macdy };
- }
- DataReaderIndicatorsMacd.prototype.last = function() {
- return this.vlast;
- }
- // DataReaderIndicatorsMacd.prototype.getYminmax = function(y) {
- // var ymax = -Infinity;
- // var ymin = Infinity;
- // if (!y) {
- // return [ymin, ymax];
- // }
- // for (var i = 1; i <= y.length && i <= this.model.plotnum; i++) {
- // for (var j = 0; j < y[y.length - i].length; j++) {
- // var value = y[y.length - i][j];
- // if (!isNaN(value)) {
- // if (value > ymax) {
- // ymax = value;
- // }
- // if (value < ymin) {
- // ymin = value;
- // }
- // }
- // }
- // }
- // return [ymin, ymax];
- // }
- DataReaderIndicatorsMacd.prototype.getYminmax = function(y) {
- var ymax = -Infinity;
- var maxIndex=0;
- var minIndex=0;
- var ymin = Infinity;
- if (!y) {
- return [ymin, ymax,minIndex,maxIndex];
- }
- for (var i = 1; i <= y.length && i <= this.model.plotnum; i++) {
- for (var j = 0; j < y[y.length - i].length; j++) {
- var value = y[y.length - i][j];
- if (!isNaN(value)) {
- if (value > ymax) {
- maxIndex=i;
- ymax = value;
- }
- if (value < ymin) {
- minIndex=i;
- ymin = value;
- }
- }
- }
- }
- return [ymin, ymax,minIndex,maxIndex];
- }
- function DataReaderIndicatorsMaTrend(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderIndicatorsMaTrend, DataReaderIndicators);
- DataReaderIndicatorsMaTrend.prototype.setParam = function(param) {
- //这个函数里面做一定的初始化工作。特别是shift
- this.param = param;
- this.n = param[1].split(",");
- for (var i = 0; i < this.n.length; i++) {
- this.n[i] = parseInt(this.n[i]);
- }
- this.n = this.n.sort(function(a, b) {
- return a - b
- });
- this.reffer = this.param[0];
- this.shift = Math.max.apply(this, this.n);
- }
- DataReaderIndicatorsMaTrend.prototype.getData = function() {
- var ma = [];
- var trend = [];
- if (!this.dataInit()) {
- return { x: [], y: [] };
- }
- for (var i = 0; i < this.n.length; i++) {
- // alert(this.n[i]);
- ma[i] = this.ma(this.n[i]);
- }
- var num, delt;
- for (var i = 0; i < this.y.length - 1; i++) {
- num = 0;
- delt = 0;
- for (var j = 0; j < this.n.length; j++) {
- if (ma[j][i] > ma[j][i + 1]) {
- num++;
- } else if (ma[j][i] < ma[j][i + 1]) {
- num--;
- }
- delt++;
- for (var k = j + 1; k < this.n.length; k++) {
- if (ma[j][i] > ma[k][i]) {
- num++;
- } else if (ma[j][i] < ma[k][i]) {
- num--;
- }
- delt++;
- }
- }
- num = num / delt;
- trend[i] = num;
- }
- trend[this.y.length - 1] = 0;
- this.lastdata = trend[0];
- return { x: this.x, y: trend };
- }
- function DataReaderIndicatorsRSI(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderIndicatorsRSI, DataReaderIndicators);
- //对指标,数据部分由
- DataReaderIndicatorsRSI.prototype.setN = function(n) {
- this.n = parseInt(n);
- this.shift = parseInt(n);
- }
- DataReaderIndicatorsRSI.prototype.setParam = function(param) {
- //这个函数里面做一定的初始化工作。特别是shift
- this.param = param;
- this.reffer = this.param[0];
- this.setN(param[1]);
- }
- DataReaderIndicatorsRSI.prototype.empty = function() {
- return {
- x: [],
- y: []
- };
- }
- DataReaderIndicatorsRSI.prototype.getData = function() {
- if (!this.dataInit(this.reffer[1])) {
- return this.empty();
- }
- var K = this.strength(this.n);
- if (!this.dataInit(this.reffer[0])) {
- return this.empty();
- }
- var E = this.strength(this.n);
- if (K.length != E.length) {
- return this.empty();
- }
- var H = [];
- for (var i = 0; i < K.length; i++) {
- H[i] = (K[i] - E[i] + 200) / 4;
- }
- this.lastdata = H[0];
- return { x: this.x, y: H };
- }
- function DataReaderIndicatorsWPR(model, writer, name) {
- sup(this, model, writer, name);
- }
- ClassExtend(DataReaderIndicatorsWPR, DataReaderIndicators);
- //对指标,数据部分由
- DataReaderIndicatorsWPR.prototype.setN = function(n) {
- this.n = parseInt(n);
- this.shift = parseInt(n);
- }
- DataReaderIndicatorsWPR.prototype.setParam = function(param) {
- //这个函数里面做一定的初始化工作。特别是shift
- this.param = param;
- this.setN(this.param[1]);
- }
- DataReaderIndicatorsWPR.prototype.getData = function() {
- if (!this.dataInit()) {
- return { x: [], y: [] };
- }
- var data = this.wpr(this.n);
- this.lastdata = data[0];
- return { x: this.x, y: data };
- }
- function html5chart(api,type,period) {
- if (type&&period) {
- $('#'+type.toLowerCase()).addClass('active');
- //$.clearCookie();
- api.initPair(type, period);
- $.cookie('symbol', type);
- $.cookie('period',period);
- // $.cookie('period',period);
- // var indstr="main:ma|main|5|color=black:ma|main|10|color=yellow:ma|main|20|color=red:ma|main|30|color=green:";
- // api.setInd(indstr);
- api.initInd('MAC');
- // console.log($('li[name="ETH"]'));
- } else {
- $.cookie('symbol', 'BCCBTC');
- $.cookie('period', 'H1');
- // sessionStorage.setItem('period','H1');
- api.initPair('BCCBTC', "H1");
- api.initInd('MAC');
- }
- return;
- }
|