2
0

talib.go 145 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989
  1. package sentio
  2. /*
  3. Copyright 2016 Mark Chenoweth
  4. Licensed under terms of MIT license (see LICENSE)
  5. */
  6. import (
  7. "errors"
  8. "math"
  9. )
  10. // MaType - Moving average type
  11. type MaType int
  12. type moneyFlow struct {
  13. positive float64
  14. negative float64
  15. }
  16. // Kinds of moving averages
  17. const (
  18. SMA MaType = iota
  19. EMA
  20. WMA
  21. DEMA
  22. TEMA
  23. TRIMA
  24. KAMA
  25. MAMA
  26. T3MA
  27. )
  28. /* Overlap Studies */
  29. // BBands - Bollinger Bands
  30. // upperband, middleband, lowerband = BBands(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
  31. func BBands(inReal []float64, inTimePeriod int, inNbDevUp float64, inNbDevDn float64, inMAType MaType) ([]float64, []float64, []float64) {
  32. outRealUpperBand := make([]float64, len(inReal))
  33. outRealMiddleBand := Ma(inReal, inTimePeriod, inMAType)
  34. outRealLowerBand := make([]float64, len(inReal))
  35. tempBuffer2 := StdDev(inReal, inTimePeriod, 1.0)
  36. if inNbDevUp == inNbDevDn {
  37. if inNbDevUp == 1.0 {
  38. for i := 0; i < len(inReal); i++ {
  39. tempReal := tempBuffer2[i]
  40. tempReal2 := outRealMiddleBand[i]
  41. outRealUpperBand[i] = tempReal2 + tempReal
  42. outRealLowerBand[i] = tempReal2 - tempReal
  43. }
  44. } else {
  45. for i := 0; i < len(inReal); i++ {
  46. tempReal := tempBuffer2[i] * inNbDevUp
  47. tempReal2 := outRealMiddleBand[i]
  48. outRealUpperBand[i] = tempReal2 + tempReal
  49. outRealLowerBand[i] = tempReal2 - tempReal
  50. }
  51. }
  52. } else if inNbDevUp == 1.0 {
  53. for i := 0; i < len(inReal); i++ {
  54. tempReal := tempBuffer2[i]
  55. tempReal2 := outRealMiddleBand[i]
  56. outRealUpperBand[i] = tempReal2 + tempReal
  57. outRealLowerBand[i] = tempReal2 - (tempReal * inNbDevDn)
  58. }
  59. } else if inNbDevDn == 1.0 {
  60. for i := 0; i < len(inReal); i++ {
  61. tempReal := tempBuffer2[i]
  62. tempReal2 := outRealMiddleBand[i]
  63. outRealLowerBand[i] = tempReal2 - tempReal
  64. outRealUpperBand[i] = tempReal2 + (tempReal * inNbDevUp)
  65. }
  66. } else {
  67. for i := 0; i < len(inReal); i++ {
  68. tempReal := tempBuffer2[i]
  69. tempReal2 := outRealMiddleBand[i]
  70. outRealUpperBand[i] = tempReal2 + (tempReal * inNbDevUp)
  71. outRealLowerBand[i] = tempReal2 - (tempReal * inNbDevDn)
  72. }
  73. }
  74. return outRealUpperBand, outRealMiddleBand, outRealLowerBand
  75. }
  76. // Dema - Double Exponential Moving Average
  77. func Dema(inReal []float64, inTimePeriod int) []float64 {
  78. outReal := make([]float64, len(inReal))
  79. firstEMA := Ema(inReal, inTimePeriod)
  80. secondEMA := Ema(firstEMA[inTimePeriod-1:], inTimePeriod)
  81. for outIdx, secondEMAIdx := (inTimePeriod*2)-2, inTimePeriod-1; outIdx < len(inReal); outIdx, secondEMAIdx = outIdx+1, secondEMAIdx+1 {
  82. outReal[outIdx] = (2.0 * firstEMA[outIdx]) - secondEMA[secondEMAIdx]
  83. }
  84. return outReal
  85. }
  86. // Ema - Exponential Moving Average
  87. func ema(inReal []float64, inTimePeriod int, k1 float64) []float64 {
  88. outReal := make([]float64, len(inReal))
  89. lookbackTotal := inTimePeriod - 1
  90. startIdx := lookbackTotal
  91. today := startIdx - lookbackTotal
  92. i := inTimePeriod
  93. tempReal := 0.0
  94. for i > 0 {
  95. tempReal += inReal[today]
  96. today++
  97. i--
  98. }
  99. prevMA := tempReal / float64(inTimePeriod)
  100. for today <= startIdx {
  101. prevMA = ((inReal[today] - prevMA) * k1) + prevMA
  102. today++
  103. }
  104. outReal[startIdx] = prevMA
  105. outIdx := startIdx + 1
  106. for today < len(inReal) {
  107. prevMA = ((inReal[today] - prevMA) * k1) + prevMA
  108. outReal[outIdx] = prevMA
  109. today++
  110. outIdx++
  111. }
  112. return outReal
  113. }
  114. // Ema - Exponential Moving Average
  115. func Ema(inReal []float64, inTimePeriod int) []float64 {
  116. k := 2.0 / float64(inTimePeriod+1)
  117. outReal := ema(inReal, inTimePeriod, k)
  118. return outReal
  119. }
  120. // HtTrendline - Hilbert Transform - Instantaneous Trendline (lookback=63)
  121. func HtTrendline(inReal []float64) []float64 {
  122. outReal := make([]float64, len(inReal))
  123. a := 0.0962
  124. b := 0.5769
  125. detrenderOdd := make([]float64, 3)
  126. detrenderEven := make([]float64, 3)
  127. q1Odd := make([]float64, 3)
  128. q1Even := make([]float64, 3)
  129. jIOdd := make([]float64, 3)
  130. jIEven := make([]float64, 3)
  131. jQOdd := make([]float64, 3)
  132. jQEven := make([]float64, 3)
  133. smoothPriceIdx := 0
  134. maxIdxSmoothPrice := (50 - 1)
  135. smoothPrice := make([]float64, maxIdxSmoothPrice+1)
  136. iTrend1 := 0.0
  137. iTrend2 := 0.0
  138. iTrend3 := 0.0
  139. tempReal := math.Atan(1)
  140. rad2Deg := 45.0 / tempReal
  141. lookbackTotal := 63
  142. startIdx := lookbackTotal
  143. trailingWMAIdx := startIdx - lookbackTotal
  144. today := trailingWMAIdx
  145. tempReal = inReal[today]
  146. today++
  147. periodWMASub := tempReal
  148. periodWMASum := tempReal
  149. tempReal = inReal[today]
  150. today++
  151. periodWMASub += tempReal
  152. periodWMASum += tempReal * 2.0
  153. tempReal = inReal[today]
  154. today++
  155. periodWMASub += tempReal
  156. periodWMASum += tempReal * 3.0
  157. trailingWMAValue := 0.0
  158. i := 34
  159. for ok := true; ok; {
  160. tempReal = inReal[today]
  161. today++
  162. periodWMASub += tempReal
  163. periodWMASub -= trailingWMAValue
  164. periodWMASum += tempReal * 4.0
  165. trailingWMAValue = inReal[trailingWMAIdx]
  166. trailingWMAIdx++
  167. //smoothedValue := periodWMASum * 0.1
  168. periodWMASum -= periodWMASub
  169. i--
  170. ok = i != 0
  171. }
  172. hilbertIdx := 0
  173. detrender := 0.0
  174. prevDetrenderOdd := 0.0
  175. prevDetrenderEven := 0.0
  176. prevDetrenderInputOdd := 0.0
  177. prevDetrenderInputEven := 0.0
  178. q1 := 0.0
  179. prevq1Odd := 0.0
  180. prevq1Even := 0.0
  181. prevq1InputOdd := 0.0
  182. prevq1InputEven := 0.0
  183. jI := 0.0
  184. prevJIOdd := 0.0
  185. prevJIEven := 0.0
  186. prevJIInputOdd := 0.0
  187. prevJIInputEven := 0.0
  188. jQ := 0.0
  189. prevJQOdd := 0.0
  190. prevJQEven := 0.0
  191. prevJQInputOdd := 0.0
  192. prevJQInputEven := 0.0
  193. period := 0.0
  194. outIdx := 63
  195. previ2 := 0.0
  196. prevq2 := 0.0
  197. Re := 0.0
  198. Im := 0.0
  199. i1ForOddPrev3 := 0.0
  200. i1ForEvenPrev3 := 0.0
  201. i1ForOddPrev2 := 0.0
  202. i1ForEvenPrev2 := 0.0
  203. smoothPeriod := 0.0
  204. q2 := 0.0
  205. i2 := 0.0
  206. for today < len(inReal) {
  207. adjustedPrevPeriod := (0.075 * period) + 0.54
  208. todayValue := inReal[today]
  209. periodWMASub += todayValue
  210. periodWMASub -= trailingWMAValue
  211. periodWMASum += todayValue * 4.0
  212. trailingWMAValue = inReal[trailingWMAIdx]
  213. trailingWMAIdx++
  214. smoothedValue := periodWMASum * 0.1
  215. periodWMASum -= periodWMASub
  216. smoothPrice[smoothPriceIdx] = smoothedValue
  217. if (today % 2) == 0 {
  218. hilbertTempReal := a * smoothedValue
  219. detrender = -detrenderEven[hilbertIdx]
  220. detrenderEven[hilbertIdx] = hilbertTempReal
  221. detrender += hilbertTempReal
  222. detrender -= prevDetrenderEven
  223. prevDetrenderEven = b * prevDetrenderInputEven
  224. detrender += prevDetrenderEven
  225. prevDetrenderInputEven = smoothedValue
  226. detrender *= adjustedPrevPeriod
  227. hilbertTempReal = a * detrender
  228. q1 = -q1Even[hilbertIdx]
  229. q1Even[hilbertIdx] = hilbertTempReal
  230. q1 += hilbertTempReal
  231. q1 -= prevq1Even
  232. prevq1Even = b * prevq1InputEven
  233. q1 += prevq1Even
  234. prevq1InputEven = detrender
  235. q1 *= adjustedPrevPeriod
  236. hilbertTempReal = a * i1ForEvenPrev3
  237. jI = -jIEven[hilbertIdx]
  238. jIEven[hilbertIdx] = hilbertTempReal
  239. jI += hilbertTempReal
  240. jI -= prevJIEven
  241. prevJIEven = b * prevJIInputEven
  242. jI += prevJIEven
  243. prevJIInputEven = i1ForEvenPrev3
  244. jI *= adjustedPrevPeriod
  245. hilbertTempReal = a * q1
  246. jQ = -jQEven[hilbertIdx]
  247. jQEven[hilbertIdx] = hilbertTempReal
  248. jQ += hilbertTempReal
  249. jQ -= prevJQEven
  250. prevJQEven = b * prevJQInputEven
  251. jQ += prevJQEven
  252. prevJQInputEven = q1
  253. jQ *= adjustedPrevPeriod
  254. hilbertIdx++
  255. if hilbertIdx == 3 {
  256. hilbertIdx = 0
  257. }
  258. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  259. i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
  260. i1ForOddPrev3 = i1ForOddPrev2
  261. i1ForOddPrev2 = detrender
  262. } else {
  263. hilbertTempReal := a * smoothedValue
  264. detrender = -detrenderOdd[hilbertIdx]
  265. detrenderOdd[hilbertIdx] = hilbertTempReal
  266. detrender += hilbertTempReal
  267. detrender -= prevDetrenderOdd
  268. prevDetrenderOdd = b * prevDetrenderInputOdd
  269. detrender += prevDetrenderOdd
  270. prevDetrenderInputOdd = smoothedValue
  271. detrender *= adjustedPrevPeriod
  272. hilbertTempReal = a * detrender
  273. q1 = -q1Odd[hilbertIdx]
  274. q1Odd[hilbertIdx] = hilbertTempReal
  275. q1 += hilbertTempReal
  276. q1 -= prevq1Odd
  277. prevq1Odd = b * prevq1InputOdd
  278. q1 += prevq1Odd
  279. prevq1InputOdd = detrender
  280. q1 *= adjustedPrevPeriod
  281. hilbertTempReal = a * i1ForOddPrev3
  282. jI = -jIOdd[hilbertIdx]
  283. jIOdd[hilbertIdx] = hilbertTempReal
  284. jI += hilbertTempReal
  285. jI -= prevJIOdd
  286. prevJIOdd = b * prevJIInputOdd
  287. jI += prevJIOdd
  288. prevJIInputOdd = i1ForOddPrev3
  289. jI *= adjustedPrevPeriod
  290. hilbertTempReal = a * q1
  291. jQ = -jQOdd[hilbertIdx]
  292. jQOdd[hilbertIdx] = hilbertTempReal
  293. jQ += hilbertTempReal
  294. jQ -= prevJQOdd
  295. prevJQOdd = b * prevJQInputOdd
  296. jQ += prevJQOdd
  297. prevJQInputOdd = q1
  298. jQ *= adjustedPrevPeriod
  299. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  300. i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
  301. i1ForEvenPrev3 = i1ForEvenPrev2
  302. i1ForEvenPrev2 = detrender
  303. }
  304. Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
  305. Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
  306. prevq2 = q2
  307. previ2 = i2
  308. tempReal = period
  309. if (Im != 0.0) && (Re != 0.0) {
  310. period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
  311. }
  312. tempReal2 := 1.5 * tempReal
  313. if period > tempReal2 {
  314. period = tempReal2
  315. }
  316. tempReal2 = 0.67 * tempReal
  317. if period < tempReal2 {
  318. period = tempReal2
  319. }
  320. if period < 6 {
  321. period = 6
  322. } else if period > 50 {
  323. period = 50
  324. }
  325. period = (0.2 * period) + (0.8 * tempReal)
  326. smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
  327. DCPeriod := smoothPeriod + 0.5
  328. DCPeriodInt := math.Floor(DCPeriod)
  329. idx := today
  330. tempReal = 0.0
  331. for i := 0; i < int(DCPeriodInt); i++ {
  332. tempReal += inReal[idx]
  333. idx--
  334. }
  335. if DCPeriodInt > 0 {
  336. tempReal = tempReal / (DCPeriodInt * 1.0)
  337. }
  338. tempReal2 = (4.0*tempReal + 3.0*iTrend1 + 2.0*iTrend2 + iTrend3) / 10.0
  339. iTrend3 = iTrend2
  340. iTrend2 = iTrend1
  341. iTrend1 = tempReal
  342. if today >= startIdx {
  343. outReal[outIdx] = tempReal2
  344. outIdx++
  345. }
  346. smoothPriceIdx++
  347. if smoothPriceIdx > maxIdxSmoothPrice {
  348. smoothPriceIdx = 0
  349. }
  350. today++
  351. }
  352. return outReal
  353. }
  354. // Kama - Kaufman Adaptive Moving Average
  355. func Kama(inReal []float64, inTimePeriod int) []float64 {
  356. outReal := make([]float64, len(inReal))
  357. constMax := 2.0 / (30.0 + 1.0)
  358. constDiff := 2.0/(2.0+1.0) - constMax
  359. lookbackTotal := inTimePeriod
  360. startIdx := lookbackTotal
  361. sumROC1 := 0.0
  362. today := startIdx - lookbackTotal
  363. trailingIdx := today
  364. i := inTimePeriod
  365. for i > 0 {
  366. tempReal := inReal[today]
  367. today++
  368. tempReal -= inReal[today]
  369. sumROC1 += math.Abs(tempReal)
  370. i--
  371. }
  372. prevKAMA := inReal[today-1]
  373. tempReal := inReal[today]
  374. tempReal2 := inReal[trailingIdx]
  375. trailingIdx++
  376. periodROC := tempReal - tempReal2
  377. trailingValue := tempReal2
  378. if (sumROC1 <= periodROC) || (((-(0.00000000000001)) < sumROC1) && (sumROC1 < (0.00000000000001))) {
  379. tempReal = 1.0
  380. } else {
  381. tempReal = math.Abs(periodROC / sumROC1)
  382. }
  383. tempReal = (tempReal * constDiff) + constMax
  384. tempReal *= tempReal
  385. prevKAMA = ((inReal[today] - prevKAMA) * tempReal) + prevKAMA
  386. today++
  387. for today <= startIdx {
  388. tempReal = inReal[today]
  389. tempReal2 = inReal[trailingIdx]
  390. trailingIdx++
  391. periodROC = tempReal - tempReal2
  392. sumROC1 -= math.Abs(trailingValue - tempReal2)
  393. sumROC1 += math.Abs(tempReal - inReal[today-1])
  394. trailingValue = tempReal2
  395. if (sumROC1 <= periodROC) || (((-(0.00000000000001)) < sumROC1) && (sumROC1 < (0.00000000000001))) {
  396. tempReal = 1.0
  397. } else {
  398. tempReal = math.Abs(periodROC / sumROC1)
  399. }
  400. tempReal = (tempReal * constDiff) + constMax
  401. tempReal *= tempReal
  402. prevKAMA = ((inReal[today] - prevKAMA) * tempReal) + prevKAMA
  403. today++
  404. }
  405. outReal[inTimePeriod] = prevKAMA
  406. outIdx := inTimePeriod + 1
  407. for today < len(inReal) {
  408. tempReal = inReal[today]
  409. tempReal2 = inReal[trailingIdx]
  410. trailingIdx++
  411. periodROC = tempReal - tempReal2
  412. sumROC1 -= math.Abs(trailingValue - tempReal2)
  413. sumROC1 += math.Abs(tempReal - inReal[today-1])
  414. trailingValue = tempReal2
  415. if (sumROC1 <= periodROC) || (((-(0.00000000000001)) < sumROC1) && (sumROC1 < (0.00000000000001))) {
  416. tempReal = 1.0
  417. } else {
  418. tempReal = math.Abs(periodROC / sumROC1)
  419. }
  420. tempReal = (tempReal * constDiff) + constMax
  421. tempReal *= tempReal
  422. prevKAMA = ((inReal[today] - prevKAMA) * tempReal) + prevKAMA
  423. today++
  424. outReal[outIdx] = prevKAMA
  425. outIdx++
  426. }
  427. return outReal
  428. }
  429. // Ma - Moving average
  430. func Ma(inReal []float64, inTimePeriod int, inMAType MaType) []float64 {
  431. outReal := make([]float64, len(inReal))
  432. if inTimePeriod == 1 {
  433. copy(outReal, inReal)
  434. return outReal
  435. }
  436. switch inMAType {
  437. case SMA:
  438. outReal = Sma(inReal, inTimePeriod)
  439. case EMA:
  440. outReal = Ema(inReal, inTimePeriod)
  441. case WMA:
  442. outReal = Wma(inReal, inTimePeriod)
  443. case DEMA:
  444. outReal = Dema(inReal, inTimePeriod)
  445. case TEMA:
  446. outReal = Tema(inReal, inTimePeriod)
  447. case TRIMA:
  448. outReal = Trima(inReal, inTimePeriod)
  449. case KAMA:
  450. outReal = Kama(inReal, inTimePeriod)
  451. case MAMA:
  452. outReal, _ = Mama(inReal, 0.5, 0.05)
  453. case T3MA:
  454. outReal = T3(inReal, inTimePeriod, 0.7)
  455. }
  456. return outReal
  457. }
  458. // Mama - MESA Adaptive Moving Average (lookback=32)
  459. func Mama(inReal []float64, inFastLimit float64, inSlowLimit float64) ([]float64, []float64) {
  460. outMAMA := make([]float64, len(inReal))
  461. outFAMA := make([]float64, len(inReal))
  462. a := 0.0962
  463. b := 0.5769
  464. detrenderOdd := make([]float64, 3)
  465. detrenderEven := make([]float64, 3)
  466. q1Odd := make([]float64, 3)
  467. q1Even := make([]float64, 3)
  468. jIOdd := make([]float64, 3)
  469. jIEven := make([]float64, 3)
  470. jQOdd := make([]float64, 3)
  471. jQEven := make([]float64, 3)
  472. rad2Deg := 180.0 / (4.0 * math.Atan(1))
  473. lookbackTotal := 32
  474. startIdx := lookbackTotal
  475. trailingWMAIdx := startIdx - lookbackTotal
  476. today := trailingWMAIdx
  477. tempReal := inReal[today]
  478. today++
  479. periodWMASub := tempReal
  480. periodWMASum := tempReal
  481. tempReal = inReal[today]
  482. today++
  483. periodWMASub += tempReal
  484. periodWMASum += tempReal * 2.0
  485. tempReal = inReal[today]
  486. today++
  487. periodWMASub += tempReal
  488. periodWMASum += tempReal * 3.0
  489. trailingWMAValue := 0.0
  490. i := 9
  491. smoothedValue := 0.0
  492. for ok := true; ok; {
  493. tempReal = inReal[today]
  494. today++
  495. periodWMASub += tempReal
  496. periodWMASub -= trailingWMAValue
  497. periodWMASum += tempReal * 4.0
  498. trailingWMAValue = inReal[trailingWMAIdx]
  499. trailingWMAIdx++
  500. smoothedValue = periodWMASum * 0.1
  501. periodWMASum -= periodWMASub
  502. i--
  503. ok = i != 0
  504. }
  505. hilbertIdx := 0
  506. detrenderOdd[0] = 0.0
  507. detrenderOdd[1] = 0.0
  508. detrenderOdd[2] = 0.0
  509. detrenderEven[0] = 0.0
  510. detrenderEven[1] = 0.0
  511. detrenderEven[2] = 0.0
  512. detrender := 0.0
  513. prevDetrenderOdd := 0.0
  514. prevDetrenderEven := 0.0
  515. prevDetrenderInputOdd := 0.0
  516. prevDetrenderInputEven := 0.0
  517. q1Odd[0] = 0.0
  518. q1Odd[1] = 0.0
  519. q1Odd[2] = 0.0
  520. q1Even[0] = 0.0
  521. q1Even[1] = 0.0
  522. q1Even[2] = 0.0
  523. q1 := 0.0
  524. prevq1Odd := 0.0
  525. prevq1Even := 0.0
  526. prevq1InputOdd := 0.0
  527. prevq1InputEven := 0.0
  528. jIOdd[0] = 0.0
  529. jIOdd[1] = 0.0
  530. jIOdd[2] = 0.0
  531. jIEven[0] = 0.0
  532. jIEven[1] = 0.0
  533. jIEven[2] = 0.0
  534. jI := 0.0
  535. prevjIOdd := 0.0
  536. prevjIEven := 0.0
  537. prevjIInputOdd := 0.0
  538. prevjIInputEven := 0.0
  539. jQOdd[0] = 0.0
  540. jQOdd[1] = 0.0
  541. jQOdd[2] = 0.0
  542. jQEven[0] = 0.0
  543. jQEven[1] = 0.0
  544. jQEven[2] = 0.0
  545. jQ := 0.0
  546. prevjQOdd := 0.0
  547. prevjQEven := 0.0
  548. prevjQInputOdd := 0.0
  549. prevjQInputEven := 0.0
  550. period := 0.0
  551. outIdx := startIdx
  552. previ2, prevq2 := 0.0, 0.0
  553. Re, Im := 0.0, 0.0
  554. mama, fama := 0.0, 0.0
  555. i1ForOddPrev3, i1ForEvenPrev3 := 0.0, 0.0
  556. i1ForOddPrev2, i1ForEvenPrev2 := 0.0, 0.0
  557. prevPhase := 0.0
  558. adjustedPrevPeriod := 0.0
  559. todayValue := 0.0
  560. hilbertTempReal := 0.0
  561. for today < len(inReal) {
  562. adjustedPrevPeriod = (0.075 * period) + 0.54
  563. todayValue = inReal[today]
  564. periodWMASub += todayValue
  565. periodWMASub -= trailingWMAValue
  566. periodWMASum += todayValue * 4.0
  567. trailingWMAValue = inReal[trailingWMAIdx]
  568. trailingWMAIdx++
  569. smoothedValue = periodWMASum * 0.1
  570. periodWMASum -= periodWMASub
  571. q2, i2 := 0.0, 0.0
  572. tempReal2 := 0.0
  573. if (today % 2) == 0 {
  574. hilbertTempReal = a * smoothedValue
  575. detrender = -detrenderEven[hilbertIdx]
  576. detrenderEven[hilbertIdx] = hilbertTempReal
  577. detrender += hilbertTempReal
  578. detrender -= prevDetrenderEven
  579. prevDetrenderEven = b * prevDetrenderInputEven
  580. detrender += prevDetrenderEven
  581. prevDetrenderInputEven = smoothedValue
  582. detrender *= adjustedPrevPeriod
  583. hilbertTempReal = a * detrender
  584. q1 = -q1Even[hilbertIdx]
  585. q1Even[hilbertIdx] = hilbertTempReal
  586. q1 += hilbertTempReal
  587. q1 -= prevq1Even
  588. prevq1Even = b * prevq1InputEven
  589. q1 += prevq1Even
  590. prevq1InputEven = detrender
  591. q1 *= adjustedPrevPeriod
  592. hilbertTempReal = a * i1ForEvenPrev3
  593. jI = -jIEven[hilbertIdx]
  594. jIEven[hilbertIdx] = hilbertTempReal
  595. jI += hilbertTempReal
  596. jI -= prevjIEven
  597. prevjIEven = b * prevjIInputEven
  598. jI += prevjIEven
  599. prevjIInputEven = i1ForEvenPrev3
  600. jI *= adjustedPrevPeriod
  601. hilbertTempReal = a * q1
  602. jQ = -jQEven[hilbertIdx]
  603. jQEven[hilbertIdx] = hilbertTempReal
  604. jQ += hilbertTempReal
  605. jQ -= prevjQEven
  606. prevjQEven = b * prevjQInputEven
  607. jQ += prevjQEven
  608. prevjQInputEven = q1
  609. jQ *= adjustedPrevPeriod
  610. hilbertIdx++
  611. if hilbertIdx == 3 {
  612. hilbertIdx = 0
  613. }
  614. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  615. i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
  616. i1ForOddPrev3 = i1ForOddPrev2
  617. i1ForOddPrev2 = detrender
  618. if i1ForEvenPrev3 != 0.0 {
  619. tempReal2 = (math.Atan(q1/i1ForEvenPrev3) * rad2Deg)
  620. } else {
  621. tempReal2 = 0.0
  622. }
  623. } else {
  624. hilbertTempReal = a * smoothedValue
  625. detrender = -detrenderOdd[hilbertIdx]
  626. detrenderOdd[hilbertIdx] = hilbertTempReal
  627. detrender += hilbertTempReal
  628. detrender -= prevDetrenderOdd
  629. prevDetrenderOdd = b * prevDetrenderInputOdd
  630. detrender += prevDetrenderOdd
  631. prevDetrenderInputOdd = smoothedValue
  632. detrender *= adjustedPrevPeriod
  633. hilbertTempReal = a * detrender
  634. q1 = -q1Odd[hilbertIdx]
  635. q1Odd[hilbertIdx] = hilbertTempReal
  636. q1 += hilbertTempReal
  637. q1 -= prevq1Odd
  638. prevq1Odd = b * prevq1InputOdd
  639. q1 += prevq1Odd
  640. prevq1InputOdd = detrender
  641. q1 *= adjustedPrevPeriod
  642. hilbertTempReal = a * i1ForOddPrev3
  643. jI = -jIOdd[hilbertIdx]
  644. jIOdd[hilbertIdx] = hilbertTempReal
  645. jI += hilbertTempReal
  646. jI -= prevjIOdd
  647. prevjIOdd = b * prevjIInputOdd
  648. jI += prevjIOdd
  649. prevjIInputOdd = i1ForOddPrev3
  650. jI *= adjustedPrevPeriod
  651. hilbertTempReal = a * q1
  652. jQ = -jQOdd[hilbertIdx]
  653. jQOdd[hilbertIdx] = hilbertTempReal
  654. jQ += hilbertTempReal
  655. jQ -= prevjQOdd
  656. prevjQOdd = b * prevjQInputOdd
  657. jQ += prevjQOdd
  658. prevjQInputOdd = q1
  659. jQ *= adjustedPrevPeriod
  660. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  661. i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
  662. i1ForEvenPrev3 = i1ForEvenPrev2
  663. i1ForEvenPrev2 = detrender
  664. if i1ForOddPrev3 != 0.0 {
  665. tempReal2 = (math.Atan(q1/i1ForOddPrev3) * rad2Deg)
  666. } else {
  667. tempReal2 = 0.0
  668. }
  669. }
  670. tempReal = prevPhase - tempReal2
  671. prevPhase = tempReal2
  672. if tempReal < 1.0 {
  673. tempReal = 1.0
  674. }
  675. if tempReal > 1.0 {
  676. tempReal = inFastLimit / tempReal
  677. if tempReal < inSlowLimit {
  678. tempReal = inSlowLimit
  679. }
  680. } else {
  681. tempReal = inFastLimit
  682. }
  683. mama = (tempReal * todayValue) + ((1 - tempReal) * mama)
  684. tempReal *= 0.5
  685. fama = (tempReal * mama) + ((1 - tempReal) * fama)
  686. if today >= startIdx {
  687. outMAMA[outIdx] = mama
  688. outFAMA[outIdx] = fama
  689. outIdx++
  690. }
  691. Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
  692. Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
  693. prevq2 = q2
  694. previ2 = i2
  695. tempReal = period
  696. if (Im != 0.0) && (Re != 0.0) {
  697. period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
  698. }
  699. tempReal2 = 1.5 * tempReal
  700. if period > tempReal2 {
  701. period = tempReal2
  702. }
  703. tempReal2 = 0.67 * tempReal
  704. if period < tempReal2 {
  705. period = tempReal2
  706. }
  707. if period < 6 {
  708. period = 6
  709. } else if period > 50 {
  710. period = 50
  711. }
  712. period = (0.2 * period) + (0.8 * tempReal)
  713. today++
  714. }
  715. return outMAMA, outFAMA
  716. }
  717. // MaVp - Moving average with variable period
  718. func MaVp(inReal []float64, inPeriods []float64, inMinPeriod int, inMaxPeriod int, inMAType MaType) []float64 {
  719. outReal := make([]float64, len(inReal))
  720. startIdx := inMaxPeriod - 1
  721. outputSize := len(inReal)
  722. localPeriodArray := make([]float64, outputSize)
  723. for i := startIdx; i < outputSize; i++ {
  724. tempInt := int(inPeriods[i])
  725. if tempInt < inMinPeriod {
  726. tempInt = inMinPeriod
  727. } else if tempInt > inMaxPeriod {
  728. tempInt = inMaxPeriod
  729. }
  730. localPeriodArray[i] = float64(tempInt)
  731. }
  732. for i := startIdx; i < outputSize; i++ {
  733. curPeriod := int(localPeriodArray[i])
  734. if curPeriod != 0 {
  735. localOutputArray := Ma(inReal, curPeriod, inMAType)
  736. outReal[i] = localOutputArray[i]
  737. for j := i + 1; j < outputSize; j++ {
  738. if localPeriodArray[j] == float64(curPeriod) {
  739. localPeriodArray[j] = 0
  740. outReal[j] = localOutputArray[j]
  741. }
  742. }
  743. }
  744. }
  745. return outReal
  746. }
  747. // MidPoint - MidPoint over period
  748. func MidPoint(inReal []float64, inTimePeriod int) []float64 {
  749. outReal := make([]float64, len(inReal))
  750. nbInitialElementNeeded := inTimePeriod - 1
  751. startIdx := nbInitialElementNeeded
  752. outIdx := inTimePeriod - 1
  753. today := startIdx
  754. trailingIdx := startIdx - nbInitialElementNeeded
  755. for today < len(inReal) {
  756. lowest := inReal[trailingIdx]
  757. trailingIdx++
  758. highest := lowest
  759. for i := trailingIdx; i <= today; i++ {
  760. tmp := inReal[i]
  761. if tmp < lowest {
  762. lowest = tmp
  763. } else if tmp > highest {
  764. highest = tmp
  765. }
  766. }
  767. outReal[outIdx] = (highest + lowest) / 2.0
  768. outIdx++
  769. today++
  770. }
  771. return outReal
  772. }
  773. // MidPrice - Midpoint Price over period
  774. func MidPrice(inHigh []float64, inLow []float64, inTimePeriod int) []float64 {
  775. outReal := make([]float64, len(inHigh))
  776. nbInitialElementNeeded := inTimePeriod - 1
  777. startIdx := nbInitialElementNeeded
  778. outIdx := inTimePeriod - 1
  779. today := startIdx
  780. trailingIdx := startIdx - nbInitialElementNeeded
  781. for today < len(inHigh) {
  782. lowest := inLow[trailingIdx]
  783. highest := inHigh[trailingIdx]
  784. trailingIdx++
  785. for i := trailingIdx; i <= today; i++ {
  786. tmp := inLow[i]
  787. if tmp < lowest {
  788. lowest = tmp
  789. }
  790. tmp = inHigh[i]
  791. if tmp > highest {
  792. highest = tmp
  793. }
  794. }
  795. outReal[outIdx] = (highest + lowest) / 2.0
  796. outIdx++
  797. today++
  798. }
  799. return outReal
  800. }
  801. // Sar - Parabolic SAR
  802. // real = Sar(high, low, acceleration=0, maximum=0)
  803. func Sar(inHigh []float64, inLow []float64, inAcceleration float64, inMaximum float64) []float64 {
  804. outReal := make([]float64, len(inHigh))
  805. af := inAcceleration
  806. if af > inMaximum {
  807. af, inAcceleration = inMaximum, inMaximum
  808. }
  809. epTemp := MinusDM(inHigh, inLow, 1)
  810. isLong := 1
  811. if epTemp[1] > 0 {
  812. isLong = 0
  813. }
  814. startIdx := 1
  815. outIdx := startIdx
  816. todayIdx := startIdx
  817. newHigh := inHigh[todayIdx-1]
  818. newLow := inLow[todayIdx-1]
  819. sar, ep := 0.0, 0.0
  820. if isLong == 1 {
  821. ep = inHigh[todayIdx]
  822. sar = newLow
  823. } else {
  824. ep = inLow[todayIdx]
  825. sar = newHigh
  826. }
  827. newLow = inLow[todayIdx]
  828. newHigh = inHigh[todayIdx]
  829. prevLow := 0.0
  830. prevHigh := 0.0
  831. for todayIdx < len(inHigh) {
  832. prevLow = newLow
  833. prevHigh = newHigh
  834. newLow = inLow[todayIdx]
  835. newHigh = inHigh[todayIdx]
  836. todayIdx++
  837. if isLong == 1 {
  838. if newLow <= sar {
  839. isLong = 0
  840. sar = ep
  841. if sar < prevHigh {
  842. sar = prevHigh
  843. }
  844. if sar < newHigh {
  845. sar = newHigh
  846. }
  847. outReal[outIdx] = sar
  848. outIdx++
  849. af = inAcceleration
  850. ep = newLow
  851. sar = sar + af*(ep-sar)
  852. if sar < prevHigh {
  853. sar = prevHigh
  854. }
  855. if sar < newHigh {
  856. sar = newHigh
  857. }
  858. } else {
  859. outReal[outIdx] = sar
  860. outIdx++
  861. if newHigh > ep {
  862. ep = newHigh
  863. af += inAcceleration
  864. if af > inMaximum {
  865. af = inMaximum
  866. }
  867. }
  868. sar = sar + af*(ep-sar)
  869. if sar > prevLow {
  870. sar = prevLow
  871. }
  872. if sar > newLow {
  873. sar = newLow
  874. }
  875. }
  876. } else {
  877. if newHigh >= sar {
  878. isLong = 1
  879. sar = ep
  880. if sar > prevLow {
  881. sar = prevLow
  882. }
  883. if sar > newLow {
  884. sar = newLow
  885. }
  886. outReal[outIdx] = sar
  887. outIdx++
  888. af = inAcceleration
  889. ep = newHigh
  890. sar = sar + af*(ep-sar)
  891. if sar > prevLow {
  892. sar = prevLow
  893. }
  894. if sar > newLow {
  895. sar = newLow
  896. }
  897. } else {
  898. outReal[outIdx] = sar
  899. outIdx++
  900. if newLow < ep {
  901. ep = newLow
  902. af += inAcceleration
  903. if af > inMaximum {
  904. af = inMaximum
  905. }
  906. }
  907. sar = sar + af*(ep-sar)
  908. if sar < prevHigh {
  909. sar = prevHigh
  910. }
  911. if sar < newHigh {
  912. sar = newHigh
  913. }
  914. }
  915. }
  916. }
  917. return outReal
  918. }
  919. // SarExt - Parabolic SAR - Extended
  920. // real = SAREXT(high, low, startvalue=0, offsetonreverse=0, accelerationinitlong=0, accelerationlong=0, accelerationmaxlong=0, accelerationinitshort=0, accelerationshort=0, accelerationmaxshort=0)
  921. func SarExt(inHigh []float64, inLow []float64,
  922. inStartValue float64,
  923. inOffsetOnReverse float64,
  924. inAccelerationInitLong float64,
  925. inAccelerationLong float64,
  926. inAccelerationMaxLong float64,
  927. inAccelerationInitShort float64,
  928. inAccelerationShort float64,
  929. inAccelerationMaxShort float64) []float64 {
  930. outReal := make([]float64, len(inHigh))
  931. startIdx := 1
  932. afLong := inAccelerationInitLong
  933. afShort := inAccelerationInitShort
  934. if afLong > inAccelerationMaxLong {
  935. afLong, inAccelerationInitLong = inAccelerationMaxLong, inAccelerationMaxLong
  936. }
  937. if inAccelerationLong > inAccelerationMaxLong {
  938. inAccelerationLong = inAccelerationMaxLong
  939. }
  940. if afShort > inAccelerationMaxShort {
  941. afShort, inAccelerationInitShort = inAccelerationMaxShort, inAccelerationMaxShort
  942. }
  943. if inAccelerationShort > inAccelerationMaxShort {
  944. inAccelerationShort = inAccelerationMaxShort
  945. }
  946. isLong := 0
  947. if inStartValue == 0 {
  948. epTemp := MinusDM(inHigh, inLow, 1)
  949. if epTemp[1] > 0 {
  950. isLong = 0
  951. } else {
  952. isLong = 1
  953. }
  954. } else if inStartValue > 0 {
  955. isLong = 1
  956. }
  957. outIdx := startIdx
  958. todayIdx := startIdx
  959. newHigh := inHigh[todayIdx-1]
  960. newLow := inLow[todayIdx-1]
  961. ep := 0.0
  962. sar := 0.0
  963. if inStartValue == 0 {
  964. if isLong == 1 {
  965. ep = inHigh[todayIdx]
  966. sar = newLow
  967. } else {
  968. ep = inLow[todayIdx]
  969. sar = newHigh
  970. }
  971. } else if inStartValue > 0 {
  972. ep = inHigh[todayIdx]
  973. sar = inStartValue
  974. } else {
  975. ep = inLow[todayIdx]
  976. sar = math.Abs(inStartValue)
  977. }
  978. newLow = inLow[todayIdx]
  979. newHigh = inHigh[todayIdx]
  980. prevLow := 0.0
  981. prevHigh := 0.0
  982. for todayIdx < len(inHigh) {
  983. prevLow = newLow
  984. prevHigh = newHigh
  985. newLow = inLow[todayIdx]
  986. newHigh = inHigh[todayIdx]
  987. todayIdx++
  988. if isLong == 1 {
  989. if newLow <= sar {
  990. isLong = 0
  991. sar = ep
  992. if sar < prevHigh {
  993. sar = prevHigh
  994. }
  995. if sar < newHigh {
  996. sar = newHigh
  997. }
  998. if inOffsetOnReverse != 0.0 {
  999. sar += sar * inOffsetOnReverse
  1000. }
  1001. outReal[outIdx] = -sar
  1002. outIdx++
  1003. afShort = inAccelerationInitShort
  1004. ep = newLow
  1005. sar = sar + afShort*(ep-sar)
  1006. if sar < prevHigh {
  1007. sar = prevHigh
  1008. }
  1009. if sar < newHigh {
  1010. sar = newHigh
  1011. }
  1012. } else {
  1013. outReal[outIdx] = sar
  1014. outIdx++
  1015. if newHigh > ep {
  1016. ep = newHigh
  1017. afLong += inAccelerationLong
  1018. if afLong > inAccelerationMaxLong {
  1019. afLong = inAccelerationMaxLong
  1020. }
  1021. }
  1022. sar = sar + afLong*(ep-sar)
  1023. if sar > prevLow {
  1024. sar = prevLow
  1025. }
  1026. if sar > newLow {
  1027. sar = newLow
  1028. }
  1029. }
  1030. } else {
  1031. if newHigh >= sar {
  1032. isLong = 1
  1033. sar = ep
  1034. if sar > prevLow {
  1035. sar = prevLow
  1036. }
  1037. if sar > newLow {
  1038. sar = newLow
  1039. }
  1040. if inOffsetOnReverse != 0.0 {
  1041. sar -= sar * inOffsetOnReverse
  1042. }
  1043. outReal[outIdx] = sar
  1044. outIdx++
  1045. afLong = inAccelerationInitLong
  1046. ep = newHigh
  1047. sar = sar + afLong*(ep-sar)
  1048. if sar > prevLow {
  1049. sar = prevLow
  1050. }
  1051. if sar > newLow {
  1052. sar = newLow
  1053. }
  1054. } else {
  1055. outReal[outIdx] = -sar
  1056. outIdx++
  1057. if newLow < ep {
  1058. ep = newLow
  1059. afShort += inAccelerationShort
  1060. if afShort > inAccelerationMaxShort {
  1061. afShort = inAccelerationMaxShort
  1062. }
  1063. }
  1064. sar = sar + afShort*(ep-sar)
  1065. if sar < prevHigh {
  1066. sar = prevHigh
  1067. }
  1068. if sar < newHigh {
  1069. sar = newHigh
  1070. }
  1071. }
  1072. }
  1073. }
  1074. return outReal
  1075. }
  1076. // Sma - Simple Moving Average
  1077. func Sma(inReal []float64, inTimePeriod int) []float64 {
  1078. outReal := make([]float64, len(inReal))
  1079. lookbackTotal := inTimePeriod - 1
  1080. startIdx := lookbackTotal
  1081. periodTotal := 0.0
  1082. trailingIdx := startIdx - lookbackTotal
  1083. i := trailingIdx
  1084. if inTimePeriod > 1 {
  1085. for i < startIdx {
  1086. periodTotal += inReal[i]
  1087. i++
  1088. }
  1089. }
  1090. outIdx := startIdx
  1091. for ok := true; ok; {
  1092. periodTotal += inReal[i]
  1093. tempReal := periodTotal
  1094. periodTotal -= inReal[trailingIdx]
  1095. outReal[outIdx] = tempReal / float64(inTimePeriod)
  1096. trailingIdx++
  1097. i++
  1098. outIdx++
  1099. ok = i < len(outReal)
  1100. }
  1101. return outReal
  1102. }
  1103. // T3 - Triple Exponential Moving Average (T3) (lookback=6*inTimePeriod)
  1104. func T3(inReal []float64, inTimePeriod int, inVFactor float64) []float64 {
  1105. outReal := make([]float64, len(inReal))
  1106. lookbackTotal := 6 * (inTimePeriod - 1)
  1107. startIdx := lookbackTotal
  1108. today := startIdx - lookbackTotal
  1109. k := 2.0 / (float64(inTimePeriod) + 1.0)
  1110. oneMinusK := 1.0 - k
  1111. tempReal := inReal[today]
  1112. today++
  1113. for i := inTimePeriod - 1; i > 0; i-- {
  1114. tempReal += inReal[today]
  1115. today++
  1116. }
  1117. e1 := tempReal / float64(inTimePeriod)
  1118. tempReal = e1
  1119. for i := inTimePeriod - 1; i > 0; i-- {
  1120. e1 = (k * inReal[today]) + (oneMinusK * e1)
  1121. tempReal += e1
  1122. today++
  1123. }
  1124. e2 := tempReal / float64(inTimePeriod)
  1125. tempReal = e2
  1126. for i := inTimePeriod - 1; i > 0; i-- {
  1127. e1 = (k * inReal[today]) + (oneMinusK * e1)
  1128. e2 = (k * e1) + (oneMinusK * e2)
  1129. tempReal += e2
  1130. today++
  1131. }
  1132. e3 := tempReal / float64(inTimePeriod)
  1133. tempReal = e3
  1134. for i := inTimePeriod - 1; i > 0; i-- {
  1135. e1 = (k * inReal[today]) + (oneMinusK * e1)
  1136. e2 = (k * e1) + (oneMinusK * e2)
  1137. e3 = (k * e2) + (oneMinusK * e3)
  1138. tempReal += e3
  1139. today++
  1140. }
  1141. e4 := tempReal / float64(inTimePeriod)
  1142. tempReal = e4
  1143. for i := inTimePeriod - 1; i > 0; i-- {
  1144. e1 = (k * inReal[today]) + (oneMinusK * e1)
  1145. e2 = (k * e1) + (oneMinusK * e2)
  1146. e3 = (k * e2) + (oneMinusK * e3)
  1147. e4 = (k * e3) + (oneMinusK * e4)
  1148. tempReal += e4
  1149. today++
  1150. }
  1151. e5 := tempReal / float64(inTimePeriod)
  1152. tempReal = e5
  1153. for i := inTimePeriod - 1; i > 0; i-- {
  1154. e1 = (k * inReal[today]) + (oneMinusK * e1)
  1155. e2 = (k * e1) + (oneMinusK * e2)
  1156. e3 = (k * e2) + (oneMinusK * e3)
  1157. e4 = (k * e3) + (oneMinusK * e4)
  1158. e5 = (k * e4) + (oneMinusK * e5)
  1159. tempReal += e5
  1160. today++
  1161. }
  1162. e6 := tempReal / float64(inTimePeriod)
  1163. for today <= startIdx {
  1164. e1 = (k * inReal[today]) + (oneMinusK * e1)
  1165. e2 = (k * e1) + (oneMinusK * e2)
  1166. e3 = (k * e2) + (oneMinusK * e3)
  1167. e4 = (k * e3) + (oneMinusK * e4)
  1168. e5 = (k * e4) + (oneMinusK * e5)
  1169. e6 = (k * e5) + (oneMinusK * e6)
  1170. today++
  1171. }
  1172. tempReal = inVFactor * inVFactor
  1173. c1 := -(tempReal * inVFactor)
  1174. c2 := 3.0 * (tempReal - c1)
  1175. c3 := -6.0*tempReal - 3.0*(inVFactor-c1)
  1176. c4 := 1.0 + 3.0*inVFactor - c1 + 3.0*tempReal
  1177. outIdx := lookbackTotal
  1178. outReal[outIdx] = c1*e6 + c2*e5 + c3*e4 + c4*e3
  1179. outIdx++
  1180. for today < len(inReal) {
  1181. e1 = (k * inReal[today]) + (oneMinusK * e1)
  1182. e2 = (k * e1) + (oneMinusK * e2)
  1183. e3 = (k * e2) + (oneMinusK * e3)
  1184. e4 = (k * e3) + (oneMinusK * e4)
  1185. e5 = (k * e4) + (oneMinusK * e5)
  1186. e6 = (k * e5) + (oneMinusK * e6)
  1187. outReal[outIdx] = c1*e6 + c2*e5 + c3*e4 + c4*e3
  1188. outIdx++
  1189. today++
  1190. }
  1191. return outReal
  1192. }
  1193. // Tema - Triple Exponential Moving Average
  1194. func Tema(inReal []float64, inTimePeriod int) []float64 {
  1195. outReal := make([]float64, len(inReal))
  1196. firstEMA := Ema(inReal, inTimePeriod)
  1197. secondEMA := Ema(firstEMA[inTimePeriod-1:], inTimePeriod)
  1198. thirdEMA := Ema(secondEMA[inTimePeriod-1:], inTimePeriod)
  1199. outIdx := (inTimePeriod * 3) - 3
  1200. secondEMAIdx := (inTimePeriod * 2) - 2
  1201. thirdEMAIdx := inTimePeriod - 1
  1202. for outIdx < len(inReal) {
  1203. outReal[outIdx] = thirdEMA[thirdEMAIdx] + ((3.0 * firstEMA[outIdx]) - (3.0 * secondEMA[secondEMAIdx]))
  1204. outIdx++
  1205. secondEMAIdx++
  1206. thirdEMAIdx++
  1207. }
  1208. return outReal
  1209. }
  1210. // Trima - Triangular Moving Average
  1211. func Trima(inReal []float64, inTimePeriod int) []float64 {
  1212. outReal := make([]float64, len(inReal))
  1213. lookbackTotal := inTimePeriod - 1
  1214. startIdx := lookbackTotal
  1215. outIdx := inTimePeriod - 1
  1216. var factor float64
  1217. if inTimePeriod%2 == 1 {
  1218. i := inTimePeriod >> 1
  1219. factor = (float64(i) + 1.0) * (float64(i) + 1.0)
  1220. factor = 1.0 / factor
  1221. trailingIdx := startIdx - lookbackTotal
  1222. middleIdx := trailingIdx + i
  1223. todayIdx := middleIdx + i
  1224. numerator := 0.0
  1225. numeratorSub := 0.0
  1226. for i := middleIdx; i >= trailingIdx; i-- {
  1227. tempReal := inReal[i]
  1228. numeratorSub += tempReal
  1229. numerator += numeratorSub
  1230. }
  1231. numeratorAdd := 0.0
  1232. middleIdx++
  1233. for i := middleIdx; i <= todayIdx; i++ {
  1234. tempReal := inReal[i]
  1235. numeratorAdd += tempReal
  1236. numerator += numeratorAdd
  1237. }
  1238. outIdx = inTimePeriod - 1
  1239. tempReal := inReal[trailingIdx]
  1240. trailingIdx++
  1241. outReal[outIdx] = numerator * factor
  1242. outIdx++
  1243. todayIdx++
  1244. for todayIdx < len(inReal) {
  1245. numerator -= numeratorSub
  1246. numeratorSub -= tempReal
  1247. tempReal = inReal[middleIdx]
  1248. middleIdx++
  1249. numeratorSub += tempReal
  1250. numerator += numeratorAdd
  1251. numeratorAdd -= tempReal
  1252. tempReal = inReal[todayIdx]
  1253. todayIdx++
  1254. numeratorAdd += tempReal
  1255. numerator += tempReal
  1256. tempReal = inReal[trailingIdx]
  1257. trailingIdx++
  1258. outReal[outIdx] = numerator * factor
  1259. outIdx++
  1260. }
  1261. } else {
  1262. i := (inTimePeriod >> 1)
  1263. factor = float64(i) * (float64(i) + 1)
  1264. factor = 1.0 / factor
  1265. trailingIdx := startIdx - lookbackTotal
  1266. middleIdx := trailingIdx + i - 1
  1267. todayIdx := middleIdx + i
  1268. numerator := 0.0
  1269. numeratorSub := 0.0
  1270. for i := middleIdx; i >= trailingIdx; i-- {
  1271. tempReal := inReal[i]
  1272. numeratorSub += tempReal
  1273. numerator += numeratorSub
  1274. }
  1275. numeratorAdd := 0.0
  1276. middleIdx++
  1277. for i := middleIdx; i <= todayIdx; i++ {
  1278. tempReal := inReal[i]
  1279. numeratorAdd += tempReal
  1280. numerator += numeratorAdd
  1281. }
  1282. outIdx = inTimePeriod - 1
  1283. tempReal := inReal[trailingIdx]
  1284. trailingIdx++
  1285. outReal[outIdx] = numerator * factor
  1286. outIdx++
  1287. todayIdx++
  1288. for todayIdx < len(inReal) {
  1289. numerator -= numeratorSub
  1290. numeratorSub -= tempReal
  1291. tempReal = inReal[middleIdx]
  1292. middleIdx++
  1293. numeratorSub += tempReal
  1294. numeratorAdd -= tempReal
  1295. numerator += numeratorAdd
  1296. tempReal = inReal[todayIdx]
  1297. todayIdx++
  1298. numeratorAdd += tempReal
  1299. numerator += tempReal
  1300. tempReal = inReal[trailingIdx]
  1301. trailingIdx++
  1302. outReal[outIdx] = numerator * factor
  1303. outIdx++
  1304. }
  1305. }
  1306. return outReal
  1307. }
  1308. // Wma - Weighted Moving Average
  1309. func Wma(inReal []float64, inTimePeriod int) []float64 {
  1310. outReal := make([]float64, len(inReal))
  1311. lookbackTotal := inTimePeriod - 1
  1312. startIdx := lookbackTotal
  1313. if inTimePeriod == 1 {
  1314. copy(outReal, inReal)
  1315. return outReal
  1316. }
  1317. divider := (inTimePeriod * (inTimePeriod + 1)) >> 1
  1318. outIdx := inTimePeriod - 1
  1319. trailingIdx := startIdx - lookbackTotal
  1320. periodSum, periodSub := 0.0, 0.0
  1321. inIdx := trailingIdx
  1322. i := 1
  1323. for inIdx < startIdx {
  1324. tempReal := inReal[inIdx]
  1325. periodSub += tempReal
  1326. periodSum += tempReal * float64(i)
  1327. inIdx++
  1328. i++
  1329. }
  1330. trailingValue := 0.0
  1331. for inIdx < len(inReal) {
  1332. tempReal := inReal[inIdx]
  1333. periodSub += tempReal
  1334. periodSub -= trailingValue
  1335. periodSum += tempReal * float64(inTimePeriod)
  1336. trailingValue = inReal[trailingIdx]
  1337. outReal[outIdx] = periodSum / float64(divider)
  1338. periodSum -= periodSub
  1339. inIdx++
  1340. trailingIdx++
  1341. outIdx++
  1342. }
  1343. return outReal
  1344. }
  1345. /* Momentum Indicators */
  1346. // Adx - Average Directional Movement Index
  1347. func Adx(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  1348. outReal := make([]float64, len(inClose))
  1349. inTimePeriodF := float64(inTimePeriod)
  1350. lookbackTotal := (2 * inTimePeriod) - 1
  1351. startIdx := lookbackTotal
  1352. outIdx := inTimePeriod
  1353. prevMinusDM := 0.0
  1354. prevPlusDM := 0.0
  1355. prevTR := 0.0
  1356. today := startIdx - lookbackTotal
  1357. prevHigh := inHigh[today]
  1358. prevLow := inLow[today]
  1359. prevClose := inClose[today]
  1360. for i := inTimePeriod - 1; i > 0; i-- {
  1361. today++
  1362. tempReal := inHigh[today]
  1363. diffP := tempReal - prevHigh
  1364. prevHigh = tempReal
  1365. tempReal = inLow[today]
  1366. diffM := prevLow - tempReal
  1367. prevLow = tempReal
  1368. if (diffM > 0) && (diffP < diffM) {
  1369. prevMinusDM += diffM
  1370. } else if (diffP > 0) && (diffP > diffM) {
  1371. prevPlusDM += diffP
  1372. }
  1373. tempReal = prevHigh - prevLow
  1374. tempReal2 := math.Abs(prevHigh - prevClose)
  1375. if tempReal2 > tempReal {
  1376. tempReal = tempReal2
  1377. }
  1378. tempReal2 = math.Abs(prevLow - prevClose)
  1379. if tempReal2 > tempReal {
  1380. tempReal = tempReal2
  1381. }
  1382. prevTR += tempReal
  1383. prevClose = inClose[today]
  1384. }
  1385. sumDX := 0.0
  1386. for i := inTimePeriod; i > 0; i-- {
  1387. today++
  1388. tempReal := inHigh[today]
  1389. diffP := tempReal - prevHigh
  1390. prevHigh = tempReal
  1391. tempReal = inLow[today]
  1392. diffM := prevLow - tempReal
  1393. prevLow = tempReal
  1394. prevMinusDM -= prevMinusDM / inTimePeriodF
  1395. prevPlusDM -= prevPlusDM / inTimePeriodF
  1396. if (diffM > 0) && (diffP < diffM) {
  1397. prevMinusDM += diffM
  1398. } else if (diffP > 0) && (diffP > diffM) {
  1399. prevPlusDM += diffP
  1400. }
  1401. tempReal = prevHigh - prevLow
  1402. tempReal2 := math.Abs(prevHigh - prevClose)
  1403. if tempReal2 > tempReal {
  1404. tempReal = tempReal2
  1405. }
  1406. tempReal2 = math.Abs(prevLow - prevClose)
  1407. if tempReal2 > tempReal {
  1408. tempReal = tempReal2
  1409. }
  1410. prevTR = prevTR - (prevTR / inTimePeriodF) + tempReal
  1411. prevClose = inClose[today]
  1412. if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
  1413. minusDI := (100.0 * (prevMinusDM / prevTR))
  1414. plusDI := (100.0 * (prevPlusDM / prevTR))
  1415. tempReal = minusDI + plusDI
  1416. if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
  1417. sumDX += (100.0 * (math.Abs(minusDI-plusDI) / tempReal))
  1418. }
  1419. }
  1420. }
  1421. prevADX := (sumDX / inTimePeriodF)
  1422. outReal[startIdx] = prevADX
  1423. outIdx = startIdx + 1
  1424. today++
  1425. for today < len(inClose) {
  1426. tempReal := inHigh[today]
  1427. diffP := tempReal - prevHigh
  1428. prevHigh = tempReal
  1429. tempReal = inLow[today]
  1430. diffM := prevLow - tempReal
  1431. prevLow = tempReal
  1432. prevMinusDM -= prevMinusDM / inTimePeriodF
  1433. prevPlusDM -= prevPlusDM / inTimePeriodF
  1434. if (diffM > 0) && (diffP < diffM) {
  1435. prevMinusDM += diffM
  1436. } else if (diffP > 0) && (diffP > diffM) {
  1437. prevPlusDM += diffP
  1438. }
  1439. tempReal = prevHigh - prevLow
  1440. tempReal2 := math.Abs(prevHigh - prevClose)
  1441. if tempReal2 > tempReal {
  1442. tempReal = tempReal2
  1443. }
  1444. tempReal2 = math.Abs(prevLow - prevClose)
  1445. if tempReal2 > tempReal {
  1446. tempReal = tempReal2
  1447. }
  1448. prevTR = prevTR - (prevTR / inTimePeriodF) + tempReal
  1449. prevClose = inClose[today]
  1450. if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
  1451. minusDI := (100.0 * (prevMinusDM / prevTR))
  1452. plusDI := (100.0 * (prevPlusDM / prevTR))
  1453. tempReal = minusDI + plusDI
  1454. if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
  1455. tempReal = (100.0 * (math.Abs(minusDI-plusDI) / tempReal))
  1456. prevADX = (((prevADX * (inTimePeriodF - 1)) + tempReal) / inTimePeriodF)
  1457. }
  1458. }
  1459. outReal[outIdx] = prevADX
  1460. outIdx++
  1461. today++
  1462. }
  1463. return outReal
  1464. }
  1465. // AdxR - Average Directional Movement Index Rating
  1466. func AdxR(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  1467. outReal := make([]float64, len(inClose))
  1468. startIdx := (2 * inTimePeriod) - 1
  1469. tmpadx := Adx(inHigh, inLow, inClose, inTimePeriod)
  1470. i := startIdx
  1471. j := startIdx + inTimePeriod - 1
  1472. for outIdx := startIdx + inTimePeriod - 1; outIdx < len(inClose); outIdx, i, j = outIdx+1, i+1, j+1 {
  1473. outReal[outIdx] = ((tmpadx[i] + tmpadx[j]) / 2.0)
  1474. }
  1475. return outReal
  1476. }
  1477. // Apo - Absolute Price Oscillator
  1478. func Apo(inReal []float64, inFastPeriod int, inSlowPeriod int, inMAType MaType) []float64 {
  1479. if inSlowPeriod < inFastPeriod {
  1480. inSlowPeriod, inFastPeriod = inFastPeriod, inSlowPeriod
  1481. }
  1482. tempBuffer := Ma(inReal, inFastPeriod, inMAType)
  1483. outReal := Ma(inReal, inSlowPeriod, inMAType)
  1484. for i := inSlowPeriod - 1; i < len(inReal); i++ {
  1485. outReal[i] = tempBuffer[i] - outReal[i]
  1486. }
  1487. return outReal
  1488. }
  1489. // Aroon - Aroon
  1490. // aroondown, aroonup = AROON(high, low, timeperiod=14)
  1491. func Aroon(inHigh []float64, inLow []float64, inTimePeriod int) ([]float64, []float64) {
  1492. outAroonUp := make([]float64, len(inHigh))
  1493. outAroonDown := make([]float64, len(inHigh))
  1494. startIdx := inTimePeriod
  1495. outIdx := startIdx
  1496. today := startIdx
  1497. trailingIdx := startIdx - inTimePeriod
  1498. lowestIdx := -1
  1499. highestIdx := -1
  1500. lowest := 0.0
  1501. highest := 0.0
  1502. factor := 100.0 / float64(inTimePeriod)
  1503. for today < len(inHigh) {
  1504. tmp := inLow[today]
  1505. if lowestIdx < trailingIdx {
  1506. lowestIdx = trailingIdx
  1507. lowest = inLow[lowestIdx]
  1508. i := lowestIdx
  1509. i++
  1510. for i <= today {
  1511. tmp = inLow[i]
  1512. if tmp <= lowest {
  1513. lowestIdx = i
  1514. lowest = tmp
  1515. }
  1516. i++
  1517. }
  1518. } else if tmp <= lowest {
  1519. lowestIdx = today
  1520. lowest = tmp
  1521. }
  1522. tmp = inHigh[today]
  1523. if highestIdx < trailingIdx {
  1524. highestIdx = trailingIdx
  1525. highest = inHigh[highestIdx]
  1526. i := highestIdx
  1527. i++
  1528. for i <= today {
  1529. tmp = inHigh[i]
  1530. if tmp >= highest {
  1531. highestIdx = i
  1532. highest = tmp
  1533. }
  1534. i++
  1535. }
  1536. } else if tmp >= highest {
  1537. highestIdx = today
  1538. highest = tmp
  1539. }
  1540. outAroonUp[outIdx] = factor * float64(inTimePeriod-(today-highestIdx))
  1541. outAroonDown[outIdx] = factor * float64(inTimePeriod-(today-lowestIdx))
  1542. outIdx++
  1543. trailingIdx++
  1544. today++
  1545. }
  1546. return outAroonDown, outAroonUp
  1547. }
  1548. // AroonOsc - Aroon Oscillator
  1549. func AroonOsc(inHigh []float64, inLow []float64, inTimePeriod int) []float64 {
  1550. outReal := make([]float64, len(inHigh))
  1551. startIdx := inTimePeriod
  1552. outIdx := startIdx
  1553. today := startIdx
  1554. trailingIdx := startIdx - inTimePeriod
  1555. lowestIdx := -1
  1556. highestIdx := -1
  1557. lowest := 0.0
  1558. highest := 0.0
  1559. factor := 100.0 / float64(inTimePeriod)
  1560. for today < len(inHigh) {
  1561. tmp := inLow[today]
  1562. if lowestIdx < trailingIdx {
  1563. lowestIdx = trailingIdx
  1564. lowest = inLow[lowestIdx]
  1565. i := lowestIdx
  1566. i++
  1567. for i <= today {
  1568. tmp = inLow[i]
  1569. if tmp <= lowest {
  1570. lowestIdx = i
  1571. lowest = tmp
  1572. }
  1573. i++
  1574. }
  1575. } else if tmp <= lowest {
  1576. lowestIdx = today
  1577. lowest = tmp
  1578. }
  1579. tmp = inHigh[today]
  1580. if highestIdx < trailingIdx {
  1581. highestIdx = trailingIdx
  1582. highest = inHigh[highestIdx]
  1583. i := highestIdx
  1584. i++
  1585. for i <= today {
  1586. tmp = inHigh[i]
  1587. if tmp >= highest {
  1588. highestIdx = i
  1589. highest = tmp
  1590. }
  1591. i++
  1592. }
  1593. } else if tmp >= highest {
  1594. highestIdx = today
  1595. highest = tmp
  1596. }
  1597. aroon := factor * float64(highestIdx-lowestIdx)
  1598. outReal[outIdx] = aroon
  1599. outIdx++
  1600. trailingIdx++
  1601. today++
  1602. }
  1603. return outReal
  1604. }
  1605. // Bop - Balance Of Power
  1606. func Bop(inOpen []float64, inHigh []float64, inLow []float64, inClose []float64) []float64 {
  1607. outReal := make([]float64, len(inClose))
  1608. for i := 0; i < len(inClose); i++ {
  1609. tempReal := inHigh[i] - inLow[i]
  1610. if tempReal < (0.00000000000001) {
  1611. outReal[i] = 0.0
  1612. } else {
  1613. outReal[i] = (inClose[i] - inOpen[i]) / tempReal
  1614. }
  1615. }
  1616. return outReal
  1617. }
  1618. // Cmo - Chande Momentum Oscillator
  1619. func Cmo(inReal []float64, inTimePeriod int) []float64 {
  1620. outReal := make([]float64, len(inReal))
  1621. lookbackTotal := inTimePeriod
  1622. startIdx := lookbackTotal
  1623. outIdx := startIdx
  1624. if inTimePeriod == 1 {
  1625. copy(outReal, inReal)
  1626. return outReal
  1627. }
  1628. today := startIdx - lookbackTotal
  1629. prevValue := inReal[today]
  1630. prevGain := 0.0
  1631. prevLoss := 0.0
  1632. today++
  1633. for i := inTimePeriod; i > 0; i-- {
  1634. tempValue1 := inReal[today]
  1635. tempValue2 := tempValue1 - prevValue
  1636. prevValue = tempValue1
  1637. if tempValue2 < 0 {
  1638. prevLoss -= tempValue2
  1639. } else {
  1640. prevGain += tempValue2
  1641. }
  1642. today++
  1643. }
  1644. prevLoss /= float64(inTimePeriod)
  1645. prevGain /= float64(inTimePeriod)
  1646. if today > startIdx {
  1647. tempValue1 := prevGain + prevLoss
  1648. if !(((-(0.00000000000001)) < tempValue1) && (tempValue1 < (0.00000000000001))) {
  1649. outReal[outIdx] = 100.0 * ((prevGain - prevLoss) / tempValue1)
  1650. } else {
  1651. outReal[outIdx] = 0.0
  1652. }
  1653. outIdx++
  1654. } else {
  1655. for today < startIdx {
  1656. tempValue1 := inReal[today]
  1657. tempValue2 := tempValue1 - prevValue
  1658. prevValue = tempValue1
  1659. prevLoss *= float64(inTimePeriod - 1)
  1660. prevGain *= float64(inTimePeriod - 1)
  1661. if tempValue2 < 0 {
  1662. prevLoss -= tempValue2
  1663. } else {
  1664. prevGain += tempValue2
  1665. }
  1666. prevLoss /= float64(inTimePeriod)
  1667. prevGain /= float64(inTimePeriod)
  1668. today++
  1669. }
  1670. }
  1671. for today < len(inReal) {
  1672. tempValue1 := inReal[today]
  1673. today++
  1674. tempValue2 := tempValue1 - prevValue
  1675. prevValue = tempValue1
  1676. prevLoss *= float64(inTimePeriod - 1)
  1677. prevGain *= float64(inTimePeriod - 1)
  1678. if tempValue2 < 0 {
  1679. prevLoss -= tempValue2
  1680. } else {
  1681. prevGain += tempValue2
  1682. }
  1683. prevLoss /= float64(inTimePeriod)
  1684. prevGain /= float64(inTimePeriod)
  1685. tempValue1 = prevGain + prevLoss
  1686. if !(((-(0.00000000000001)) < tempValue1) && (tempValue1 < (0.00000000000001))) {
  1687. outReal[outIdx] = 100.0 * ((prevGain - prevLoss) / tempValue1)
  1688. } else {
  1689. outReal[outIdx] = 0.0
  1690. }
  1691. outIdx++
  1692. }
  1693. return outReal
  1694. }
  1695. // Cci - Commodity Channel Index
  1696. func Cci(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  1697. outReal := make([]float64, len(inClose))
  1698. circBufferIdx := 0
  1699. lookbackTotal := inTimePeriod - 1
  1700. startIdx := lookbackTotal
  1701. circBuffer := make([]float64, inTimePeriod)
  1702. maxIdxCircBuffer := (inTimePeriod - 1)
  1703. i := startIdx - lookbackTotal
  1704. if inTimePeriod > 1 {
  1705. for i < startIdx {
  1706. circBuffer[circBufferIdx] = (inHigh[i] + inLow[i] + inClose[i]) / 3
  1707. i++
  1708. circBufferIdx++
  1709. if circBufferIdx > maxIdxCircBuffer {
  1710. circBufferIdx = 0
  1711. }
  1712. }
  1713. }
  1714. outIdx := inTimePeriod - 1
  1715. for i < len(inClose) {
  1716. lastValue := (inHigh[i] + inLow[i] + inClose[i]) / 3
  1717. circBuffer[circBufferIdx] = lastValue
  1718. theAverage := 0.0
  1719. for j := 0; j < inTimePeriod; j++ {
  1720. theAverage += circBuffer[j]
  1721. }
  1722. theAverage /= float64(inTimePeriod)
  1723. tempReal2 := 0.0
  1724. for j := 0; j < inTimePeriod; j++ {
  1725. tempReal2 += math.Abs(circBuffer[j] - theAverage)
  1726. }
  1727. tempReal := lastValue - theAverage
  1728. if (tempReal != 0.0) && (tempReal2 != 0.0) {
  1729. outReal[outIdx] = tempReal / (0.015 * (tempReal2 / float64(inTimePeriod)))
  1730. } else {
  1731. outReal[outIdx] = 0.0
  1732. }
  1733. {
  1734. circBufferIdx++
  1735. if circBufferIdx > maxIdxCircBuffer {
  1736. circBufferIdx = 0
  1737. }
  1738. }
  1739. outIdx++
  1740. i++
  1741. }
  1742. return outReal
  1743. }
  1744. // Dx - Directional Movement Index
  1745. func Dx(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  1746. outReal := make([]float64, len(inClose))
  1747. lookbackTotal := 2
  1748. if inTimePeriod > 1 {
  1749. lookbackTotal = inTimePeriod
  1750. }
  1751. startIdx := lookbackTotal
  1752. outIdx := startIdx
  1753. prevMinusDM := 0.0
  1754. prevPlusDM := 0.0
  1755. prevTR := 0.0
  1756. today := startIdx - lookbackTotal
  1757. prevHigh := inHigh[today]
  1758. prevLow := inLow[today]
  1759. prevClose := inClose[today]
  1760. i := inTimePeriod - 1
  1761. for i > 0 {
  1762. i--
  1763. today++
  1764. tempReal := inHigh[today]
  1765. diffP := tempReal - prevHigh
  1766. prevHigh = tempReal
  1767. tempReal = inLow[today]
  1768. diffM := prevLow - tempReal
  1769. prevLow = tempReal
  1770. if (diffM > 0) && (diffP < diffM) {
  1771. prevMinusDM += diffM
  1772. } else if (diffP > 0) && (diffP > diffM) {
  1773. prevPlusDM += diffP
  1774. }
  1775. tempReal = prevHigh - prevLow
  1776. tempReal2 := math.Abs(prevHigh - prevClose)
  1777. if tempReal2 > tempReal {
  1778. tempReal = tempReal2
  1779. }
  1780. tempReal2 = math.Abs(prevLow - prevClose)
  1781. if tempReal2 > tempReal {
  1782. tempReal = tempReal2
  1783. }
  1784. prevTR += tempReal
  1785. prevClose = inClose[today]
  1786. }
  1787. if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
  1788. minusDI := (100.0 * (prevMinusDM / prevTR))
  1789. plusDI := (100.0 * (prevPlusDM / prevTR))
  1790. tempReal := minusDI + plusDI
  1791. if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
  1792. outReal[outIdx] = (100.0 * (math.Abs(minusDI-plusDI) / tempReal))
  1793. } else {
  1794. outReal[outIdx] = 0.0
  1795. }
  1796. } else {
  1797. outReal[outIdx] = 0.0
  1798. }
  1799. outIdx = startIdx
  1800. for today < len(inClose)-1 {
  1801. today++
  1802. tempReal := inHigh[today]
  1803. diffP := tempReal - prevHigh
  1804. prevHigh = tempReal
  1805. tempReal = inLow[today]
  1806. diffM := prevLow - tempReal
  1807. prevLow = tempReal
  1808. prevMinusDM -= prevMinusDM / float64(inTimePeriod)
  1809. prevPlusDM -= prevPlusDM / float64(inTimePeriod)
  1810. if (diffM > 0) && (diffP < diffM) {
  1811. prevMinusDM += diffM
  1812. } else if (diffP > 0) && (diffP > diffM) {
  1813. prevPlusDM += diffP
  1814. }
  1815. tempReal = prevHigh - prevLow
  1816. tempReal2 := math.Abs(prevHigh - prevClose)
  1817. if tempReal2 > tempReal {
  1818. tempReal = tempReal2
  1819. }
  1820. tempReal2 = math.Abs(prevLow - prevClose)
  1821. if tempReal2 > tempReal {
  1822. tempReal = tempReal2
  1823. }
  1824. prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
  1825. prevClose = inClose[today]
  1826. if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
  1827. minusDI := (100.0 * (prevMinusDM / prevTR))
  1828. plusDI := (100.0 * (prevPlusDM / prevTR))
  1829. tempReal = minusDI + plusDI
  1830. if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
  1831. outReal[outIdx] = (100.0 * (math.Abs(minusDI-plusDI) / tempReal))
  1832. } else {
  1833. outReal[outIdx] = outReal[outIdx-1]
  1834. }
  1835. } else {
  1836. outReal[outIdx] = outReal[outIdx-1]
  1837. }
  1838. outIdx++
  1839. }
  1840. return outReal
  1841. }
  1842. // Macd - Moving Average Convergence/Divergence
  1843. // unstable period ~= 100
  1844. func Macd(inReal []float64, inFastPeriod int, inSlowPeriod int, inSignalPeriod int) ([]float64, []float64, []float64) {
  1845. if inSlowPeriod < inFastPeriod {
  1846. inSlowPeriod, inFastPeriod = inFastPeriod, inSlowPeriod
  1847. }
  1848. k1 := 0.0
  1849. k2 := 0.0
  1850. if inSlowPeriod != 0 {
  1851. k1 = 2.0 / float64(inSlowPeriod+1)
  1852. } else {
  1853. inSlowPeriod = 26
  1854. k1 = 0.075
  1855. }
  1856. if inFastPeriod != 0 {
  1857. k2 = 2.0 / float64(inFastPeriod+1)
  1858. } else {
  1859. inFastPeriod = 12
  1860. k2 = 0.15
  1861. }
  1862. lookbackSignal := inSignalPeriod - 1
  1863. lookbackTotal := lookbackSignal
  1864. lookbackTotal += (inSlowPeriod - 1)
  1865. fastEMABuffer := ema(inReal, inFastPeriod, k2)
  1866. slowEMABuffer := ema(inReal, inSlowPeriod, k1)
  1867. for i := 0; i < len(fastEMABuffer); i++ {
  1868. fastEMABuffer[i] = fastEMABuffer[i] - slowEMABuffer[i]
  1869. }
  1870. outMACD := make([]float64, len(inReal))
  1871. for i := lookbackTotal - 1; i < len(fastEMABuffer); i++ {
  1872. outMACD[i] = fastEMABuffer[i]
  1873. }
  1874. outMACDSignal := ema(outMACD, inSignalPeriod, (2.0 / float64(inSignalPeriod+1)))
  1875. outMACDHist := make([]float64, len(inReal))
  1876. for i := lookbackTotal; i < len(outMACDHist); i++ {
  1877. outMACDHist[i] = outMACD[i] - outMACDSignal[i]
  1878. }
  1879. return outMACD, outMACDSignal, outMACDHist
  1880. }
  1881. // MacdExt - MACD with controllable MA type
  1882. // unstable period ~= 100
  1883. func MacdExt(inReal []float64, inFastPeriod int, inFastMAType MaType, inSlowPeriod int, inSlowMAType MaType, inSignalPeriod int, inSignalMAType MaType) ([]float64, []float64, []float64) {
  1884. lookbackLargest := 0
  1885. if inFastPeriod < inSlowPeriod {
  1886. lookbackLargest = inSlowPeriod
  1887. } else {
  1888. lookbackLargest = inFastPeriod
  1889. }
  1890. lookbackTotal := (inSignalPeriod - 1) + (lookbackLargest - 1)
  1891. outMACD := make([]float64, len(inReal))
  1892. outMACDSignal := make([]float64, len(inReal))
  1893. outMACDHist := make([]float64, len(inReal))
  1894. slowMABuffer := Ma(inReal, inSlowPeriod, inSlowMAType)
  1895. fastMABuffer := Ma(inReal, inFastPeriod, inFastMAType)
  1896. tempBuffer1 := make([]float64, len(inReal))
  1897. for i := 0; i < len(slowMABuffer); i++ {
  1898. tempBuffer1[i] = fastMABuffer[i] - slowMABuffer[i]
  1899. }
  1900. tempBuffer2 := Ma(tempBuffer1, inSignalPeriod, inSignalMAType)
  1901. for i := lookbackTotal; i < len(outMACDHist); i++ {
  1902. outMACD[i] = tempBuffer1[i]
  1903. outMACDSignal[i] = tempBuffer2[i]
  1904. outMACDHist[i] = outMACD[i] - outMACDSignal[i]
  1905. }
  1906. return outMACD, outMACDSignal, outMACDHist
  1907. }
  1908. // MacdFix - MACD Fix 12/26
  1909. // unstable period ~= 100
  1910. func MacdFix(inReal []float64, inSignalPeriod int) ([]float64, []float64, []float64) {
  1911. return Macd(inReal, 0, 0, inSignalPeriod)
  1912. }
  1913. // MinusDI - Minus Directional Indicator
  1914. func MinusDI(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  1915. outReal := make([]float64, len(inClose))
  1916. lookbackTotal := 1
  1917. if inTimePeriod > 1 {
  1918. lookbackTotal = inTimePeriod
  1919. }
  1920. startIdx := lookbackTotal
  1921. outIdx := startIdx
  1922. prevHigh := 0.0
  1923. prevLow := 0.0
  1924. prevClose := 0.0
  1925. if inTimePeriod <= 1 {
  1926. today := startIdx - 1
  1927. prevHigh = inHigh[today]
  1928. prevLow = inLow[today]
  1929. prevClose = inClose[today]
  1930. for today < len(inClose)-1 {
  1931. today++
  1932. tempReal := inHigh[today]
  1933. diffP := tempReal - prevHigh
  1934. prevHigh = tempReal
  1935. tempReal = inLow[today]
  1936. diffM := prevLow - tempReal
  1937. prevLow = tempReal
  1938. if (diffM > 0) && (diffP < diffM) {
  1939. tempReal = prevHigh - prevLow
  1940. tempReal2 := math.Abs(prevHigh - prevClose)
  1941. if tempReal2 > tempReal {
  1942. tempReal = tempReal2
  1943. }
  1944. tempReal2 = math.Abs(prevLow - prevClose)
  1945. if tempReal2 > tempReal {
  1946. tempReal = tempReal2
  1947. }
  1948. if ((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001)) {
  1949. outReal[outIdx] = 0.0
  1950. } else {
  1951. outReal[outIdx] = diffM / tempReal
  1952. }
  1953. outIdx++
  1954. } else {
  1955. outReal[outIdx] = 0.0
  1956. outIdx++
  1957. }
  1958. prevClose = inClose[today]
  1959. }
  1960. return outReal
  1961. }
  1962. prevMinusDM := 0.0
  1963. prevTR := 0.0
  1964. today := startIdx - lookbackTotal
  1965. prevHigh = inHigh[today]
  1966. prevLow = inLow[today]
  1967. prevClose = inClose[today]
  1968. i := inTimePeriod - 1
  1969. for i > 0 {
  1970. i--
  1971. today++
  1972. tempReal := inHigh[today]
  1973. diffP := tempReal - prevHigh
  1974. prevHigh = tempReal
  1975. tempReal = inLow[today]
  1976. diffM := prevLow - tempReal
  1977. prevLow = tempReal
  1978. if (diffM > 0) && (diffP < diffM) {
  1979. prevMinusDM += diffM
  1980. }
  1981. tempReal = prevHigh - prevLow
  1982. tempReal2 := math.Abs(prevHigh - prevClose)
  1983. if tempReal2 > tempReal {
  1984. tempReal = tempReal2
  1985. }
  1986. tempReal2 = math.Abs(prevLow - prevClose)
  1987. if tempReal2 > tempReal {
  1988. tempReal = tempReal2
  1989. }
  1990. prevTR += tempReal
  1991. prevClose = inClose[today]
  1992. }
  1993. i = 1
  1994. for i != 0 {
  1995. i--
  1996. today++
  1997. tempReal := inHigh[today]
  1998. diffP := tempReal - prevHigh
  1999. prevHigh = tempReal
  2000. tempReal = inLow[today]
  2001. diffM := prevLow - tempReal
  2002. prevLow = tempReal
  2003. if (diffM > 0) && (diffP < diffM) {
  2004. prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod)) + diffM
  2005. } else {
  2006. prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod))
  2007. }
  2008. tempReal = prevHigh - prevLow
  2009. tempReal2 := math.Abs(prevHigh - prevClose)
  2010. if tempReal2 > tempReal {
  2011. tempReal = tempReal2
  2012. }
  2013. tempReal2 = math.Abs(prevLow - prevClose)
  2014. if tempReal2 > tempReal {
  2015. tempReal = tempReal2
  2016. }
  2017. prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
  2018. prevClose = inClose[today]
  2019. }
  2020. if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
  2021. outReal[startIdx] = (100.0 * (prevMinusDM / prevTR))
  2022. } else {
  2023. outReal[startIdx] = 0.0
  2024. }
  2025. outIdx = startIdx + 1
  2026. for today < len(inClose)-1 {
  2027. today++
  2028. tempReal := inHigh[today]
  2029. diffP := tempReal - prevHigh
  2030. prevHigh = tempReal
  2031. tempReal = inLow[today]
  2032. diffM := prevLow - tempReal
  2033. prevLow = tempReal
  2034. if (diffM > 0) && (diffP < diffM) {
  2035. prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod)) + diffM
  2036. } else {
  2037. prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod))
  2038. }
  2039. tempReal = prevHigh - prevLow
  2040. tempReal2 := math.Abs(prevHigh - prevClose)
  2041. if tempReal2 > tempReal {
  2042. tempReal = tempReal2
  2043. }
  2044. tempReal2 = math.Abs(prevLow - prevClose)
  2045. if tempReal2 > tempReal {
  2046. tempReal = tempReal2
  2047. }
  2048. prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
  2049. prevClose = inClose[today]
  2050. if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
  2051. outReal[outIdx] = (100.0 * (prevMinusDM / prevTR))
  2052. } else {
  2053. outReal[outIdx] = 0.0
  2054. }
  2055. outIdx++
  2056. }
  2057. return outReal
  2058. }
  2059. // MinusDM - Minus Directional Movement
  2060. func MinusDM(inHigh []float64, inLow []float64, inTimePeriod int) []float64 {
  2061. outReal := make([]float64, len(inHigh))
  2062. lookbackTotal := 1
  2063. if inTimePeriod > 1 {
  2064. lookbackTotal = inTimePeriod - 1
  2065. }
  2066. startIdx := lookbackTotal
  2067. outIdx := startIdx
  2068. today := startIdx
  2069. prevHigh := 0.0
  2070. prevLow := 0.0
  2071. if inTimePeriod <= 1 {
  2072. today = startIdx - 1
  2073. prevHigh = inHigh[today]
  2074. prevLow = inLow[today]
  2075. for today < len(inHigh)-1 {
  2076. today++
  2077. tempReal := inHigh[today]
  2078. diffP := tempReal - prevHigh
  2079. prevHigh = tempReal
  2080. tempReal = inLow[today]
  2081. diffM := prevLow - tempReal
  2082. prevLow = tempReal
  2083. if (diffM > 0) && (diffP < diffM) {
  2084. outReal[outIdx] = diffM
  2085. } else {
  2086. outReal[outIdx] = 0
  2087. }
  2088. outIdx++
  2089. }
  2090. return outReal
  2091. }
  2092. prevMinusDM := 0.0
  2093. today = startIdx - lookbackTotal
  2094. prevHigh = inHigh[today]
  2095. prevLow = inLow[today]
  2096. i := inTimePeriod - 1
  2097. for i > 0 {
  2098. i--
  2099. today++
  2100. tempReal := inHigh[today]
  2101. diffP := tempReal - prevHigh
  2102. prevHigh = tempReal
  2103. tempReal = inLow[today]
  2104. diffM := prevLow - tempReal
  2105. prevLow = tempReal
  2106. if (diffM > 0) && (diffP < diffM) {
  2107. prevMinusDM += diffM
  2108. }
  2109. }
  2110. i = 0
  2111. for i != 0 {
  2112. i--
  2113. today++
  2114. tempReal := inHigh[today]
  2115. diffP := tempReal - prevHigh
  2116. prevHigh = tempReal
  2117. tempReal = inLow[today]
  2118. diffM := prevLow - tempReal
  2119. prevLow = tempReal
  2120. if (diffM > 0) && (diffP < diffM) {
  2121. prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod)) + diffM
  2122. } else {
  2123. prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod))
  2124. }
  2125. }
  2126. outReal[startIdx] = prevMinusDM
  2127. outIdx = startIdx + 1
  2128. for today < len(inHigh)-1 {
  2129. today++
  2130. tempReal := inHigh[today]
  2131. diffP := tempReal - prevHigh
  2132. prevHigh = tempReal
  2133. tempReal = inLow[today]
  2134. diffM := prevLow - tempReal
  2135. prevLow = tempReal
  2136. if (diffM > 0) && (diffP < diffM) {
  2137. prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod)) + diffM
  2138. } else {
  2139. prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod))
  2140. }
  2141. outReal[outIdx] = prevMinusDM
  2142. outIdx++
  2143. }
  2144. return outReal
  2145. }
  2146. // Mfi - Money Flow Index
  2147. func Mfi(inHigh []float64, inLow []float64, inClose []float64, inVolume []float64, inTimePeriod int) []float64 {
  2148. outReal := make([]float64, len(inClose))
  2149. mflowIdx := 0
  2150. maxIdxMflow := (50 - 1)
  2151. mflow := make([]moneyFlow, inTimePeriod)
  2152. maxIdxMflow = inTimePeriod - 1
  2153. lookbackTotal := inTimePeriod
  2154. startIdx := lookbackTotal
  2155. outIdx := startIdx
  2156. today := startIdx - lookbackTotal
  2157. prevValue := (inHigh[today] + inLow[today] + inClose[today]) / 3.0
  2158. posSumMF := 0.0
  2159. negSumMF := 0.0
  2160. today++
  2161. for i := inTimePeriod; i > 0; i-- {
  2162. tempValue1 := (inHigh[today] + inLow[today] + inClose[today]) / 3.0
  2163. tempValue2 := tempValue1 - prevValue
  2164. prevValue = tempValue1
  2165. tempValue1 *= inVolume[today]
  2166. today++
  2167. if tempValue2 < 0 {
  2168. (mflow[mflowIdx]).negative = tempValue1
  2169. negSumMF += tempValue1
  2170. (mflow[mflowIdx]).positive = 0.0
  2171. } else if tempValue2 > 0 {
  2172. (mflow[mflowIdx]).positive = tempValue1
  2173. posSumMF += tempValue1
  2174. (mflow[mflowIdx]).negative = 0.0
  2175. } else {
  2176. (mflow[mflowIdx]).positive = 0.0
  2177. (mflow[mflowIdx]).negative = 0.0
  2178. }
  2179. mflowIdx++
  2180. if mflowIdx > maxIdxMflow {
  2181. mflowIdx = 0
  2182. }
  2183. }
  2184. if today > startIdx {
  2185. tempValue1 := posSumMF + negSumMF
  2186. if tempValue1 < 1.0 {
  2187. } else {
  2188. outReal[outIdx] = 100.0 * (posSumMF / tempValue1)
  2189. outIdx++
  2190. }
  2191. } else {
  2192. for today < startIdx {
  2193. posSumMF -= mflow[mflowIdx].positive
  2194. negSumMF -= mflow[mflowIdx].negative
  2195. tempValue1 := (inHigh[today] + inLow[today] + inClose[today]) / 3.0
  2196. tempValue2 := tempValue1 - prevValue
  2197. prevValue = tempValue1
  2198. tempValue1 *= inVolume[today]
  2199. today++
  2200. if tempValue2 < 0 {
  2201. (mflow[mflowIdx]).negative = tempValue1
  2202. negSumMF += tempValue1
  2203. (mflow[mflowIdx]).positive = 0.0
  2204. } else if tempValue2 > 0 {
  2205. (mflow[mflowIdx]).positive = tempValue1
  2206. posSumMF += tempValue1
  2207. (mflow[mflowIdx]).negative = 0.0
  2208. } else {
  2209. (mflow[mflowIdx]).positive = 0.0
  2210. (mflow[mflowIdx]).negative = 0.0
  2211. }
  2212. mflowIdx++
  2213. if mflowIdx > maxIdxMflow {
  2214. mflowIdx = 0
  2215. }
  2216. }
  2217. }
  2218. for today < len(inClose) {
  2219. posSumMF -= (mflow[mflowIdx]).positive
  2220. negSumMF -= (mflow[mflowIdx]).negative
  2221. tempValue1 := (inHigh[today] + inLow[today] + inClose[today]) / 3.0
  2222. tempValue2 := tempValue1 - prevValue
  2223. prevValue = tempValue1
  2224. tempValue1 *= inVolume[today]
  2225. today++
  2226. if tempValue2 < 0 {
  2227. (mflow[mflowIdx]).negative = tempValue1
  2228. negSumMF += tempValue1
  2229. (mflow[mflowIdx]).positive = 0.0
  2230. } else if tempValue2 > 0 {
  2231. (mflow[mflowIdx]).positive = tempValue1
  2232. posSumMF += tempValue1
  2233. (mflow[mflowIdx]).negative = 0.0
  2234. } else {
  2235. (mflow[mflowIdx]).positive = 0.0
  2236. (mflow[mflowIdx]).negative = 0.0
  2237. }
  2238. tempValue1 = posSumMF + negSumMF
  2239. if tempValue1 < 1.0 {
  2240. outReal[outIdx] = 0.0
  2241. } else {
  2242. outReal[outIdx] = 100.0 * (posSumMF / tempValue1)
  2243. }
  2244. outIdx++
  2245. mflowIdx++
  2246. if mflowIdx > maxIdxMflow {
  2247. mflowIdx = 0
  2248. }
  2249. }
  2250. return outReal
  2251. }
  2252. // Mom - Momentum
  2253. func Mom(inReal []float64, inTimePeriod int) []float64 {
  2254. outReal := make([]float64, len(inReal))
  2255. inIdx, outIdx, trailingIdx := inTimePeriod, inTimePeriod, 0
  2256. for inIdx < len(inReal) {
  2257. outReal[outIdx] = inReal[inIdx] - inReal[trailingIdx]
  2258. inIdx, outIdx, trailingIdx = inIdx+1, outIdx+1, trailingIdx+1
  2259. }
  2260. return outReal
  2261. }
  2262. // PlusDI - Plus Directional Indicator
  2263. func PlusDI(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  2264. outReal := make([]float64, len(inClose))
  2265. lookbackTotal := 1
  2266. if inTimePeriod > 1 {
  2267. lookbackTotal = inTimePeriod
  2268. }
  2269. startIdx := lookbackTotal
  2270. outIdx := startIdx
  2271. prevHigh := 0.0
  2272. prevLow := 0.0
  2273. prevClose := 0.0
  2274. if inTimePeriod <= 1 {
  2275. today := startIdx - 1
  2276. prevHigh = inHigh[today]
  2277. prevLow = inLow[today]
  2278. prevClose = inClose[today]
  2279. for today < len(inClose)-1 {
  2280. today++
  2281. tempReal := inHigh[today]
  2282. diffP := tempReal - prevHigh
  2283. prevHigh = tempReal
  2284. tempReal = inLow[today]
  2285. diffM := prevLow - tempReal
  2286. prevLow = tempReal
  2287. if (diffP > 0) && (diffP > diffM) {
  2288. tempReal = prevHigh - prevLow
  2289. tempReal2 := math.Abs(prevHigh - prevClose)
  2290. if tempReal2 > tempReal {
  2291. tempReal = tempReal2
  2292. }
  2293. tempReal2 = math.Abs(prevLow - prevClose)
  2294. if tempReal2 > tempReal {
  2295. tempReal = tempReal2
  2296. }
  2297. if ((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001)) {
  2298. outReal[outIdx] = 0.0
  2299. } else {
  2300. outReal[outIdx] = diffP / tempReal
  2301. }
  2302. outIdx++
  2303. } else {
  2304. outReal[outIdx] = 0.0
  2305. outIdx++
  2306. }
  2307. prevClose = inClose[today]
  2308. }
  2309. return outReal
  2310. }
  2311. prevPlusDM := 0.0
  2312. prevTR := 0.0
  2313. today := startIdx - lookbackTotal
  2314. prevHigh = inHigh[today]
  2315. prevLow = inLow[today]
  2316. prevClose = inClose[today]
  2317. i := inTimePeriod - 1
  2318. for i > 0 {
  2319. i--
  2320. today++
  2321. tempReal := inHigh[today]
  2322. diffP := tempReal - prevHigh
  2323. prevHigh = tempReal
  2324. tempReal = inLow[today]
  2325. diffM := prevLow - tempReal
  2326. prevLow = tempReal
  2327. if (diffP > 0) && (diffP > diffM) {
  2328. prevPlusDM += diffP
  2329. }
  2330. tempReal = prevHigh - prevLow
  2331. tempReal2 := math.Abs(prevHigh - prevClose)
  2332. if tempReal2 > tempReal {
  2333. tempReal = tempReal2
  2334. }
  2335. tempReal2 = math.Abs(prevLow - prevClose)
  2336. if tempReal2 > tempReal {
  2337. tempReal = tempReal2
  2338. }
  2339. prevTR += tempReal
  2340. prevClose = inClose[today]
  2341. }
  2342. i = 1
  2343. for i != 0 {
  2344. i--
  2345. today++
  2346. tempReal := inHigh[today]
  2347. diffP := tempReal - prevHigh
  2348. prevHigh = tempReal
  2349. tempReal = inLow[today]
  2350. diffM := prevLow - tempReal
  2351. prevLow = tempReal
  2352. if (diffP > 0) && (diffP > diffM) {
  2353. prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod)) + diffP
  2354. } else {
  2355. prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod))
  2356. }
  2357. tempReal = prevHigh - prevLow
  2358. tempReal2 := math.Abs(prevHigh - prevClose)
  2359. if tempReal2 > tempReal {
  2360. tempReal = tempReal2
  2361. }
  2362. tempReal2 = math.Abs(prevLow - prevClose)
  2363. if tempReal2 > tempReal {
  2364. tempReal = tempReal2
  2365. }
  2366. prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
  2367. prevClose = inClose[today]
  2368. }
  2369. if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
  2370. outReal[startIdx] = (100.0 * (prevPlusDM / prevTR))
  2371. } else {
  2372. outReal[startIdx] = 0.0
  2373. }
  2374. outIdx = startIdx + 1
  2375. for today < len(inClose)-1 {
  2376. today++
  2377. tempReal := inHigh[today]
  2378. diffP := tempReal - prevHigh
  2379. prevHigh = tempReal
  2380. tempReal = inLow[today]
  2381. diffM := prevLow - tempReal
  2382. prevLow = tempReal
  2383. if (diffP > 0) && (diffP > diffM) {
  2384. prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod)) + diffP
  2385. } else {
  2386. prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod))
  2387. }
  2388. tempReal = prevHigh - prevLow
  2389. tempReal2 := math.Abs(prevHigh - prevClose)
  2390. if tempReal2 > tempReal {
  2391. tempReal = tempReal2
  2392. }
  2393. tempReal2 = math.Abs(prevLow - prevClose)
  2394. if tempReal2 > tempReal {
  2395. tempReal = tempReal2
  2396. }
  2397. prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
  2398. prevClose = inClose[today]
  2399. if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
  2400. outReal[outIdx] = (100.0 * (prevPlusDM / prevTR))
  2401. } else {
  2402. outReal[outIdx] = 0.0
  2403. }
  2404. outIdx++
  2405. }
  2406. return outReal
  2407. }
  2408. // PlusDM - Plus Directional Movement
  2409. func PlusDM(inHigh []float64, inLow []float64, inTimePeriod int) []float64 {
  2410. outReal := make([]float64, len(inHigh))
  2411. lookbackTotal := 1
  2412. if inTimePeriod > 1 {
  2413. lookbackTotal = inTimePeriod - 1
  2414. }
  2415. startIdx := lookbackTotal
  2416. outIdx := startIdx
  2417. today := startIdx
  2418. prevHigh := 0.0
  2419. prevLow := 0.0
  2420. if inTimePeriod <= 1 {
  2421. today = startIdx - 1
  2422. prevHigh = inHigh[today]
  2423. prevLow = inLow[today]
  2424. for today < len(inHigh)-1 {
  2425. today++
  2426. tempReal := inHigh[today]
  2427. diffP := tempReal - prevHigh
  2428. prevHigh = tempReal
  2429. tempReal = inLow[today]
  2430. diffM := prevLow - tempReal
  2431. prevLow = tempReal
  2432. if (diffP > 0) && (diffP > diffM) {
  2433. outReal[outIdx] = diffP
  2434. } else {
  2435. outReal[outIdx] = 0
  2436. }
  2437. outIdx++
  2438. }
  2439. return outReal
  2440. }
  2441. prevPlusDM := 0.0
  2442. today = startIdx - lookbackTotal
  2443. prevHigh = inHigh[today]
  2444. prevLow = inLow[today]
  2445. i := inTimePeriod - 1
  2446. for i > 0 {
  2447. i--
  2448. today++
  2449. tempReal := inHigh[today]
  2450. diffP := tempReal - prevHigh
  2451. prevHigh = tempReal
  2452. tempReal = inLow[today]
  2453. diffM := prevLow - tempReal
  2454. prevLow = tempReal
  2455. if (diffP > 0) && (diffP > diffM) {
  2456. prevPlusDM += diffP
  2457. }
  2458. }
  2459. i = 0
  2460. for i != 0 {
  2461. i--
  2462. today++
  2463. tempReal := inHigh[today]
  2464. diffP := tempReal - prevHigh
  2465. prevHigh = tempReal
  2466. tempReal = inLow[today]
  2467. diffM := prevLow - tempReal
  2468. prevLow = tempReal
  2469. if (diffP > 0) && (diffP > diffM) {
  2470. prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod)) + diffP
  2471. } else {
  2472. prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod))
  2473. }
  2474. }
  2475. outReal[startIdx] = prevPlusDM
  2476. outIdx = startIdx + 1
  2477. for today < len(inHigh)-1 {
  2478. today++
  2479. tempReal := inHigh[today]
  2480. diffP := tempReal - prevHigh
  2481. prevHigh = tempReal
  2482. tempReal = inLow[today]
  2483. diffM := prevLow - tempReal
  2484. prevLow = tempReal
  2485. if (diffP > 0) && (diffP > diffM) {
  2486. prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod)) + diffP
  2487. } else {
  2488. prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod))
  2489. }
  2490. outReal[outIdx] = prevPlusDM
  2491. outIdx++
  2492. }
  2493. return outReal
  2494. }
  2495. // Ppo - Percentage Price Oscillator
  2496. func Ppo(inReal []float64, inFastPeriod int, inSlowPeriod int, inMAType MaType) []float64 {
  2497. if inSlowPeriod < inFastPeriod {
  2498. inSlowPeriod, inFastPeriod = inFastPeriod, inSlowPeriod
  2499. }
  2500. tempBuffer := Ma(inReal, inFastPeriod, inMAType)
  2501. outReal := Ma(inReal, inSlowPeriod, inMAType)
  2502. for i := inSlowPeriod - 1; i < len(inReal); i++ {
  2503. tempReal := outReal[i]
  2504. if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
  2505. outReal[i] = ((tempBuffer[i] - tempReal) / tempReal) * 100.0
  2506. } else {
  2507. outReal[i] = 0.0
  2508. }
  2509. }
  2510. return outReal
  2511. }
  2512. // Rocp - Rate of change Percentage: (price-prevPrice)/prevPrice
  2513. func Rocp(inReal []float64, inTimePeriod int) []float64 {
  2514. outReal := make([]float64, len(inReal))
  2515. if inTimePeriod < 1 {
  2516. return outReal
  2517. }
  2518. startIdx := inTimePeriod
  2519. outIdx := startIdx
  2520. inIdx := startIdx
  2521. trailingIdx := startIdx - inTimePeriod
  2522. for inIdx < len(outReal) {
  2523. tempReal := inReal[trailingIdx]
  2524. if tempReal != 0.0 {
  2525. outReal[outIdx] = (inReal[inIdx] - tempReal) / tempReal
  2526. } else {
  2527. outReal[outIdx] = 0.0
  2528. }
  2529. trailingIdx++
  2530. outIdx++
  2531. inIdx++
  2532. }
  2533. return outReal
  2534. }
  2535. // Roc - Rate of change : ((price/prevPrice)-1)*100
  2536. func Roc(inReal []float64, inTimePeriod int) []float64 {
  2537. outReal := make([]float64, len(inReal))
  2538. startIdx := inTimePeriod
  2539. outIdx := inTimePeriod
  2540. inIdx := startIdx
  2541. trailingIdx := startIdx - inTimePeriod
  2542. for inIdx < len(inReal) {
  2543. tempReal := inReal[trailingIdx]
  2544. if tempReal != 0.0 {
  2545. outReal[outIdx] = ((inReal[inIdx] / tempReal) - 1.0) * 100.0
  2546. } else {
  2547. outReal[outIdx] = 0.0
  2548. }
  2549. trailingIdx++
  2550. outIdx++
  2551. inIdx++
  2552. }
  2553. return outReal
  2554. }
  2555. // Rocr - Rate of change ratio: (price/prevPrice)
  2556. func Rocr(inReal []float64, inTimePeriod int) []float64 {
  2557. outReal := make([]float64, len(inReal))
  2558. startIdx := inTimePeriod
  2559. outIdx := inTimePeriod
  2560. inIdx := startIdx
  2561. trailingIdx := startIdx - inTimePeriod
  2562. for inIdx < len(inReal) {
  2563. tempReal := inReal[trailingIdx]
  2564. if tempReal != 0.0 {
  2565. outReal[outIdx] = (inReal[inIdx] / tempReal)
  2566. } else {
  2567. outReal[outIdx] = 0.0
  2568. }
  2569. trailingIdx++
  2570. outIdx++
  2571. inIdx++
  2572. }
  2573. return outReal
  2574. }
  2575. // Rocr100 - Rate of change ratio 100 scale: (price/prevPrice)*100
  2576. func Rocr100(inReal []float64, inTimePeriod int) []float64 {
  2577. outReal := make([]float64, len(inReal))
  2578. startIdx := inTimePeriod
  2579. outIdx := inTimePeriod
  2580. inIdx := startIdx
  2581. trailingIdx := startIdx - inTimePeriod
  2582. for inIdx < len(inReal) {
  2583. tempReal := inReal[trailingIdx]
  2584. if tempReal != 0.0 {
  2585. outReal[outIdx] = (inReal[inIdx] / tempReal) * 100.0
  2586. } else {
  2587. outReal[outIdx] = 0.0
  2588. }
  2589. trailingIdx++
  2590. outIdx++
  2591. inIdx++
  2592. }
  2593. return outReal
  2594. }
  2595. // Rsi - Relative strength index
  2596. func Rsi(inReal []float64, inTimePeriod int) []float64 {
  2597. outReal := make([]float64, len(inReal))
  2598. if inTimePeriod < 2 {
  2599. return outReal
  2600. }
  2601. // variable declarations
  2602. tempValue1 := 0.0
  2603. tempValue2 := 0.0
  2604. outIdx := inTimePeriod
  2605. today := 0
  2606. prevValue := inReal[today]
  2607. prevGain := 0.0
  2608. prevLoss := 0.0
  2609. today++
  2610. for i := inTimePeriod; i > 0; i-- {
  2611. tempValue1 = inReal[today]
  2612. today++
  2613. tempValue2 = tempValue1 - prevValue
  2614. prevValue = tempValue1
  2615. if tempValue2 < 0 {
  2616. prevLoss -= tempValue2
  2617. } else {
  2618. prevGain += tempValue2
  2619. }
  2620. }
  2621. prevLoss /= float64(inTimePeriod)
  2622. prevGain /= float64(inTimePeriod)
  2623. if today > 0 {
  2624. tempValue1 = prevGain + prevLoss
  2625. if !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) {
  2626. outReal[outIdx] = 100.0 * (prevGain / tempValue1)
  2627. } else {
  2628. outReal[outIdx] = 0.0
  2629. }
  2630. outIdx++
  2631. } else {
  2632. for today < 0 {
  2633. tempValue1 = inReal[today]
  2634. tempValue2 = tempValue1 - prevValue
  2635. prevValue = tempValue1
  2636. prevLoss *= float64(inTimePeriod - 1)
  2637. prevGain *= float64(inTimePeriod - 1)
  2638. if tempValue2 < 0 {
  2639. prevLoss -= tempValue2
  2640. } else {
  2641. prevGain += tempValue2
  2642. }
  2643. prevLoss /= float64(inTimePeriod)
  2644. prevGain /= float64(inTimePeriod)
  2645. today++
  2646. }
  2647. }
  2648. for today < len(inReal) {
  2649. tempValue1 = inReal[today]
  2650. today++
  2651. tempValue2 = tempValue1 - prevValue
  2652. prevValue = tempValue1
  2653. prevLoss *= float64(inTimePeriod - 1)
  2654. prevGain *= float64(inTimePeriod - 1)
  2655. if tempValue2 < 0 {
  2656. prevLoss -= tempValue2
  2657. } else {
  2658. prevGain += tempValue2
  2659. }
  2660. prevLoss /= float64(inTimePeriod)
  2661. prevGain /= float64(inTimePeriod)
  2662. tempValue1 = prevGain + prevLoss
  2663. if !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) {
  2664. outReal[outIdx] = 100.0 * (prevGain / tempValue1)
  2665. } else {
  2666. outReal[outIdx] = 0.0
  2667. }
  2668. outIdx++
  2669. }
  2670. return outReal
  2671. }
  2672. // Stoch - Stochastic
  2673. func Stoch(inHigh []float64, inLow []float64, inClose []float64, inFastKPeriod int, inSlowKPeriod int, inSlowKMAType MaType, inSlowDPeriod int, inSlowDMAType MaType) ([]float64, []float64) {
  2674. outSlowK := make([]float64, len(inClose))
  2675. outSlowD := make([]float64, len(inClose))
  2676. lookbackK := inFastKPeriod - 1
  2677. lookbackKSlow := inSlowKPeriod - 1
  2678. lookbackDSlow := inSlowDPeriod - 1
  2679. lookbackTotal := lookbackK + lookbackDSlow + lookbackKSlow
  2680. startIdx := lookbackTotal
  2681. outIdx := 0
  2682. trailingIdx := startIdx - lookbackTotal
  2683. today := trailingIdx + lookbackK
  2684. lowestIdx, highestIdx := -1, -1
  2685. diff, highest, lowest := 0.0, 0.0, 0.0
  2686. tempBuffer := make([]float64, len(inClose)-today+1)
  2687. for today < len(inClose) {
  2688. tmp := inLow[today]
  2689. if lowestIdx < trailingIdx {
  2690. lowestIdx = trailingIdx
  2691. lowest = inLow[lowestIdx]
  2692. i := lowestIdx + 1
  2693. for i <= today {
  2694. tmp := inLow[i]
  2695. if tmp < lowest {
  2696. lowestIdx = i
  2697. lowest = tmp
  2698. }
  2699. i++
  2700. }
  2701. diff = (highest - lowest) / 100.0
  2702. } else if tmp <= lowest {
  2703. lowestIdx = today
  2704. lowest = tmp
  2705. diff = (highest - lowest) / 100.0
  2706. }
  2707. tmp = inHigh[today]
  2708. if highestIdx < trailingIdx {
  2709. highestIdx = trailingIdx
  2710. highest = inHigh[highestIdx]
  2711. i := highestIdx + 1
  2712. for i <= today {
  2713. tmp := inHigh[i]
  2714. if tmp > highest {
  2715. highestIdx = i
  2716. highest = tmp
  2717. }
  2718. i++
  2719. }
  2720. diff = (highest - lowest) / 100.0
  2721. } else if tmp >= highest {
  2722. highestIdx = today
  2723. highest = tmp
  2724. diff = (highest - lowest) / 100.0
  2725. }
  2726. if diff != 0.0 {
  2727. tempBuffer[outIdx] = (inClose[today] - lowest) / diff
  2728. } else {
  2729. tempBuffer[outIdx] = 0.0
  2730. }
  2731. outIdx++
  2732. trailingIdx++
  2733. today++
  2734. }
  2735. tempBuffer1 := Ma(tempBuffer, inSlowKPeriod, inSlowKMAType)
  2736. tempBuffer2 := Ma(tempBuffer1, inSlowDPeriod, inSlowDMAType)
  2737. //for i, j := lookbackK, lookbackTotal; j < len(inClose); i, j = i+1, j+1 {
  2738. for i, j := lookbackDSlow+lookbackKSlow, lookbackTotal; j < len(inClose); i, j = i+1, j+1 {
  2739. outSlowK[j] = tempBuffer1[i]
  2740. outSlowD[j] = tempBuffer2[i]
  2741. }
  2742. return outSlowK, outSlowD
  2743. }
  2744. // StochF - Stochastic Fast
  2745. func StochF(inHigh []float64, inLow []float64, inClose []float64, inFastKPeriod int, inFastDPeriod int, inFastDMAType MaType) ([]float64, []float64) {
  2746. outFastK := make([]float64, len(inClose))
  2747. outFastD := make([]float64, len(inClose))
  2748. lookbackK := inFastKPeriod - 1
  2749. lookbackFastD := inFastDPeriod - 1
  2750. lookbackTotal := lookbackK + lookbackFastD
  2751. startIdx := lookbackTotal
  2752. outIdx := 0
  2753. trailingIdx := startIdx - lookbackTotal
  2754. today := trailingIdx + lookbackK
  2755. lowestIdx, highestIdx := -1, -1
  2756. diff, highest, lowest := 0.0, 0.0, 0.0
  2757. tempBuffer := make([]float64, (len(inClose) - today + 1))
  2758. for today < len(inClose) {
  2759. tmp := inLow[today]
  2760. if lowestIdx < trailingIdx {
  2761. lowestIdx = trailingIdx
  2762. lowest = inLow[lowestIdx]
  2763. i := lowestIdx
  2764. i++
  2765. for i <= today {
  2766. tmp = inLow[i]
  2767. if tmp < lowest {
  2768. lowestIdx = i
  2769. lowest = tmp
  2770. }
  2771. i++
  2772. }
  2773. diff = (highest - lowest) / 100.0
  2774. } else if tmp <= lowest {
  2775. lowestIdx = today
  2776. lowest = tmp
  2777. diff = (highest - lowest) / 100.0
  2778. }
  2779. tmp = inHigh[today]
  2780. if highestIdx < trailingIdx {
  2781. highestIdx = trailingIdx
  2782. highest = inHigh[highestIdx]
  2783. i := highestIdx
  2784. i++
  2785. for i <= today {
  2786. tmp = inHigh[i]
  2787. if tmp > highest {
  2788. highestIdx = i
  2789. highest = tmp
  2790. }
  2791. i++
  2792. }
  2793. diff = (highest - lowest) / 100.0
  2794. } else if tmp >= highest {
  2795. highestIdx = today
  2796. highest = tmp
  2797. diff = (highest - lowest) / 100.0
  2798. }
  2799. if diff != 0.0 {
  2800. tempBuffer[outIdx] = (inClose[today] - lowest) / diff
  2801. } else {
  2802. tempBuffer[outIdx] = 0.0
  2803. }
  2804. outIdx++
  2805. trailingIdx++
  2806. today++
  2807. }
  2808. tempBuffer1 := Ma(tempBuffer, inFastDPeriod, inFastDMAType)
  2809. for i, j := lookbackFastD, lookbackTotal; j < len(inClose); i, j = i+1, j+1 {
  2810. outFastK[j] = tempBuffer[i]
  2811. outFastD[j] = tempBuffer1[i]
  2812. }
  2813. return outFastK, outFastD
  2814. }
  2815. // StochRsi - Stochastic Relative Strength Index
  2816. func StochRsi(inReal []float64, inTimePeriod int, inFastKPeriod int, inFastDPeriod int, inFastDMAType MaType) ([]float64, []float64) {
  2817. outFastK := make([]float64, len(inReal))
  2818. outFastD := make([]float64, len(inReal))
  2819. lookbackSTOCHF := (inFastKPeriod - 1) + (inFastDPeriod - 1)
  2820. lookbackTotal := inTimePeriod + lookbackSTOCHF
  2821. startIdx := lookbackTotal
  2822. tempRSIBuffer := Rsi(inReal, inTimePeriod)
  2823. tempk, tempd := StochF(tempRSIBuffer, tempRSIBuffer, tempRSIBuffer, inFastKPeriod, inFastDPeriod, inFastDMAType)
  2824. for i := startIdx; i < len(inReal); i++ {
  2825. outFastK[i] = tempk[i]
  2826. outFastD[i] = tempd[i]
  2827. }
  2828. return outFastK, outFastD
  2829. }
  2830. // Trix - 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
  2831. func Trix(inReal []float64, inTimePeriod int) []float64 {
  2832. tmpReal := Ema(inReal, inTimePeriod)
  2833. tmpReal = Ema(tmpReal[inTimePeriod-1:], inTimePeriod)
  2834. tmpReal = Ema(tmpReal[inTimePeriod-1:], inTimePeriod)
  2835. tmpReal = Roc(tmpReal, 1)
  2836. outReal := make([]float64, len(inReal))
  2837. for i, j := inTimePeriod, ((inTimePeriod-1)*3)+1; j < len(outReal); i, j = i+1, j+1 {
  2838. outReal[j] = tmpReal[i]
  2839. }
  2840. return outReal
  2841. }
  2842. // UltOsc - Ultimate Oscillator
  2843. func UltOsc(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod1 int, inTimePeriod2 int, inTimePeriod3 int) []float64 {
  2844. outReal := make([]float64, len(inClose))
  2845. usedFlag := make([]int, 3)
  2846. periods := make([]int, 3)
  2847. sortedPeriods := make([]int, 3)
  2848. periods[0] = inTimePeriod1
  2849. periods[1] = inTimePeriod2
  2850. periods[2] = inTimePeriod3
  2851. for i := 0; i < 3; i++ {
  2852. longestPeriod := 0
  2853. longestIndex := 0
  2854. for j := 0; j < 3; j++ {
  2855. if (usedFlag[j] == 0) && (periods[j] > longestPeriod) {
  2856. longestPeriod = periods[j]
  2857. longestIndex = j
  2858. }
  2859. }
  2860. usedFlag[longestIndex] = 1
  2861. sortedPeriods[i] = longestPeriod
  2862. }
  2863. inTimePeriod1 = sortedPeriods[2]
  2864. inTimePeriod2 = sortedPeriods[1]
  2865. inTimePeriod3 = sortedPeriods[0]
  2866. lookbackTotal := 0
  2867. if inTimePeriod1 > inTimePeriod2 {
  2868. lookbackTotal = inTimePeriod1
  2869. }
  2870. if inTimePeriod3 > lookbackTotal {
  2871. lookbackTotal = inTimePeriod3
  2872. }
  2873. lookbackTotal++
  2874. startIdx := lookbackTotal - 1
  2875. a1Total := 0.0
  2876. b1Total := 0.0
  2877. for i := startIdx - inTimePeriod1 + 1; i < startIdx; i++ {
  2878. tempLT := inLow[i]
  2879. tempHT := inHigh[i]
  2880. tempCY := inClose[i-1]
  2881. trueLow := 0.0
  2882. if tempLT < tempCY {
  2883. trueLow = tempLT
  2884. } else {
  2885. trueLow = tempCY
  2886. }
  2887. closeMinusTrueLow := inClose[i] - trueLow
  2888. trueRange := tempHT - tempLT
  2889. tempDouble := math.Abs(tempCY - tempHT)
  2890. if tempDouble > trueRange {
  2891. trueRange = tempDouble
  2892. }
  2893. tempDouble = math.Abs(tempCY - tempLT)
  2894. if tempDouble > trueRange {
  2895. trueRange = tempDouble
  2896. }
  2897. a1Total += closeMinusTrueLow
  2898. b1Total += trueRange
  2899. }
  2900. a2Total := 0.0
  2901. b2Total := 0.0
  2902. for i := startIdx - inTimePeriod2 + 1; i < startIdx; i++ {
  2903. tempLT := inLow[i]
  2904. tempHT := inHigh[i]
  2905. tempCY := inClose[i-1]
  2906. trueLow := 0.0
  2907. if tempLT < tempCY {
  2908. trueLow = tempLT
  2909. } else {
  2910. trueLow = tempCY
  2911. }
  2912. closeMinusTrueLow := inClose[i] - trueLow
  2913. trueRange := tempHT - tempLT
  2914. tempDouble := math.Abs(tempCY - tempHT)
  2915. if tempDouble > trueRange {
  2916. trueRange = tempDouble
  2917. }
  2918. tempDouble = math.Abs(tempCY - tempLT)
  2919. if tempDouble > trueRange {
  2920. trueRange = tempDouble
  2921. }
  2922. a2Total += closeMinusTrueLow
  2923. b2Total += trueRange
  2924. }
  2925. a3Total := 0.0
  2926. b3Total := 0.0
  2927. for i := startIdx - inTimePeriod3 + 1; i < startIdx; i++ {
  2928. tempLT := inLow[i]
  2929. tempHT := inHigh[i]
  2930. tempCY := inClose[i-1]
  2931. trueLow := 0.0
  2932. if tempLT < tempCY {
  2933. trueLow = tempLT
  2934. } else {
  2935. trueLow = tempCY
  2936. }
  2937. closeMinusTrueLow := inClose[i] - trueLow
  2938. trueRange := tempHT - tempLT
  2939. tempDouble := math.Abs(tempCY - tempHT)
  2940. if tempDouble > trueRange {
  2941. trueRange = tempDouble
  2942. }
  2943. tempDouble = math.Abs(tempCY - tempLT)
  2944. if tempDouble > trueRange {
  2945. trueRange = tempDouble
  2946. }
  2947. a3Total += closeMinusTrueLow
  2948. b3Total += trueRange
  2949. }
  2950. //today := startIdx
  2951. //outIdx := startIdx
  2952. //trailingIdx1 := today - inTimePeriod1 + 1
  2953. //trailingIdx2 := today - inTimePeriod2 + 1
  2954. //trailingIdx3 := today - inTimePeriod3 + 1
  2955. today := startIdx
  2956. outIdx := startIdx
  2957. trailingIdx1 := today - inTimePeriod1 + 1
  2958. trailingIdx2 := today - inTimePeriod2 + 1
  2959. trailingIdx3 := today - inTimePeriod3 + 1
  2960. for today < len(inClose) {
  2961. tempLT := inLow[today]
  2962. tempHT := inHigh[today]
  2963. tempCY := inClose[today-1]
  2964. trueLow := 0.0
  2965. if tempLT < tempCY {
  2966. trueLow = tempLT
  2967. } else {
  2968. trueLow = tempCY
  2969. }
  2970. closeMinusTrueLow := inClose[today] - trueLow
  2971. trueRange := tempHT - tempLT
  2972. tempDouble := math.Abs(tempCY - tempHT)
  2973. if tempDouble > trueRange {
  2974. trueRange = tempDouble
  2975. }
  2976. tempDouble = math.Abs(tempCY - tempLT)
  2977. if tempDouble > trueRange {
  2978. trueRange = tempDouble
  2979. }
  2980. a1Total += closeMinusTrueLow
  2981. a2Total += closeMinusTrueLow
  2982. a3Total += closeMinusTrueLow
  2983. b1Total += trueRange
  2984. b2Total += trueRange
  2985. b3Total += trueRange
  2986. output := 0.0
  2987. if !(((-(0.00000000000001)) < b1Total) && (b1Total < (0.00000000000001))) {
  2988. output += 4.0 * (a1Total / b1Total)
  2989. }
  2990. if !(((-(0.00000000000001)) < b2Total) && (b2Total < (0.00000000000001))) {
  2991. output += 2.0 * (a2Total / b2Total)
  2992. }
  2993. if !(((-(0.00000000000001)) < b3Total) && (b3Total < (0.00000000000001))) {
  2994. output += a3Total / b3Total
  2995. }
  2996. tempLT = inLow[trailingIdx1]
  2997. tempHT = inHigh[trailingIdx1]
  2998. tempCY = inClose[trailingIdx1-1]
  2999. trueLow = 0.0
  3000. if tempLT < tempCY {
  3001. trueLow = tempLT
  3002. } else {
  3003. trueLow = tempCY
  3004. }
  3005. closeMinusTrueLow = inClose[trailingIdx1] - trueLow
  3006. trueRange = tempHT - tempLT
  3007. tempDouble = math.Abs(tempCY - tempHT)
  3008. if tempDouble > trueRange {
  3009. trueRange = tempDouble
  3010. }
  3011. tempDouble = math.Abs(tempCY - tempLT)
  3012. if tempDouble > trueRange {
  3013. trueRange = tempDouble
  3014. }
  3015. a1Total -= closeMinusTrueLow
  3016. b1Total -= trueRange
  3017. tempLT = inLow[trailingIdx2]
  3018. tempHT = inHigh[trailingIdx2]
  3019. tempCY = inClose[trailingIdx2-1]
  3020. trueLow = 0.0
  3021. if tempLT < tempCY {
  3022. trueLow = tempLT
  3023. } else {
  3024. trueLow = tempCY
  3025. }
  3026. closeMinusTrueLow = inClose[trailingIdx2] - trueLow
  3027. trueRange = tempHT - tempLT
  3028. tempDouble = math.Abs(tempCY - tempHT)
  3029. if tempDouble > trueRange {
  3030. trueRange = tempDouble
  3031. }
  3032. tempDouble = math.Abs(tempCY - tempLT)
  3033. if tempDouble > trueRange {
  3034. trueRange = tempDouble
  3035. }
  3036. a2Total -= closeMinusTrueLow
  3037. b2Total -= trueRange
  3038. tempLT = inLow[trailingIdx3]
  3039. tempHT = inHigh[trailingIdx3]
  3040. tempCY = inClose[trailingIdx3-1]
  3041. trueLow = 0.0
  3042. if tempLT < tempCY {
  3043. trueLow = tempLT
  3044. } else {
  3045. trueLow = tempCY
  3046. }
  3047. closeMinusTrueLow = inClose[trailingIdx3] - trueLow
  3048. trueRange = tempHT - tempLT
  3049. tempDouble = math.Abs(tempCY - tempHT)
  3050. if tempDouble > trueRange {
  3051. trueRange = tempDouble
  3052. }
  3053. tempDouble = math.Abs(tempCY - tempLT)
  3054. if tempDouble > trueRange {
  3055. trueRange = tempDouble
  3056. }
  3057. a3Total -= closeMinusTrueLow
  3058. b3Total -= trueRange
  3059. outReal[outIdx] = 100.0 * (output / 7.0)
  3060. outIdx++
  3061. today++
  3062. trailingIdx1++
  3063. trailingIdx2++
  3064. trailingIdx3++
  3065. }
  3066. return outReal
  3067. }
  3068. // WillR - Williams' %R
  3069. func WillR(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  3070. outReal := make([]float64, len(inClose))
  3071. nbInitialElementNeeded := (inTimePeriod - 1)
  3072. diff := 0.0
  3073. outIdx := inTimePeriod - 1
  3074. startIdx := inTimePeriod - 1
  3075. today := startIdx
  3076. trailingIdx := startIdx - nbInitialElementNeeded
  3077. highestIdx := -1
  3078. lowestIdx := -1
  3079. highest := 0.0
  3080. lowest := 0.0
  3081. i := 0
  3082. for today < len(inClose) {
  3083. tmp := inLow[today]
  3084. if lowestIdx < trailingIdx {
  3085. lowestIdx = trailingIdx
  3086. lowest = inLow[lowestIdx]
  3087. i = lowestIdx
  3088. i++
  3089. for i <= today {
  3090. tmp = inLow[i]
  3091. if tmp < lowest {
  3092. lowestIdx = i
  3093. lowest = tmp
  3094. }
  3095. i++
  3096. }
  3097. diff = (highest - lowest) / (-100.0)
  3098. } else if tmp <= lowest {
  3099. lowestIdx = today
  3100. lowest = tmp
  3101. diff = (highest - lowest) / (-100.0)
  3102. }
  3103. tmp = inHigh[today]
  3104. if highestIdx < trailingIdx {
  3105. highestIdx = trailingIdx
  3106. highest = inHigh[highestIdx]
  3107. i = highestIdx
  3108. i++
  3109. for i <= today {
  3110. tmp = inHigh[i]
  3111. if tmp > highest {
  3112. highestIdx = i
  3113. highest = tmp
  3114. }
  3115. i++
  3116. }
  3117. diff = (highest - lowest) / (-100.0)
  3118. } else if tmp >= highest {
  3119. highestIdx = today
  3120. highest = tmp
  3121. diff = (highest - lowest) / (-100.0)
  3122. }
  3123. if diff != 0.0 {
  3124. outReal[outIdx] = (highest - inClose[today]) / diff
  3125. } else {
  3126. outReal[outIdx] = 0.0
  3127. }
  3128. outIdx++
  3129. trailingIdx++
  3130. today++
  3131. }
  3132. return outReal
  3133. }
  3134. /* Volume Indicators */
  3135. // Ad - Chaikin A/D Line
  3136. func Ad(inHigh []float64, inLow []float64, inClose []float64, inVolume []float64) []float64 {
  3137. outReal := make([]float64, len(inClose))
  3138. startIdx := 0
  3139. nbBar := len(inClose) - startIdx
  3140. currentBar := startIdx
  3141. outIdx := 0
  3142. ad := 0.0
  3143. for nbBar != 0 {
  3144. high := inHigh[currentBar]
  3145. low := inLow[currentBar]
  3146. tmp := high - low
  3147. close := inClose[currentBar]
  3148. if tmp > 0.0 {
  3149. ad += (((close - low) - (high - close)) / tmp) * (inVolume[currentBar])
  3150. }
  3151. outReal[outIdx] = ad
  3152. outIdx++
  3153. currentBar++
  3154. nbBar--
  3155. }
  3156. return outReal
  3157. }
  3158. // AdOsc - Chaikin A/D Oscillator
  3159. func AdOsc(inHigh []float64, inLow []float64, inClose []float64, inVolume []float64, inFastPeriod int, inSlowPeriod int) []float64 {
  3160. outReal := make([]float64, len(inClose))
  3161. if (inFastPeriod < 2) || (inSlowPeriod < 2) {
  3162. return outReal
  3163. }
  3164. slowestPeriod := 0
  3165. if inFastPeriod < inSlowPeriod {
  3166. slowestPeriod = inSlowPeriod
  3167. } else {
  3168. slowestPeriod = inFastPeriod
  3169. }
  3170. lookbackTotal := slowestPeriod - 1
  3171. startIdx := lookbackTotal
  3172. today := startIdx - lookbackTotal
  3173. ad := 0.0
  3174. fastk := (2.0 / (float64(inFastPeriod) + 1.0))
  3175. oneMinusfastk := 1.0 - fastk
  3176. slowk := (2.0 / (float64(inSlowPeriod) + 1.0))
  3177. oneMinusslowk := 1.0 - slowk
  3178. high := inHigh[today]
  3179. low := inLow[today]
  3180. tmp := high - low
  3181. close := inClose[today]
  3182. if tmp > 0.0 {
  3183. ad += (((close - low) - (high - close)) / tmp) * (inVolume[today])
  3184. }
  3185. today++
  3186. fastEMA := ad
  3187. slowEMA := ad
  3188. for today < startIdx {
  3189. high = inHigh[today]
  3190. low = inLow[today]
  3191. tmp = high - low
  3192. close = inClose[today]
  3193. if tmp > 0.0 {
  3194. ad += (((close - low) - (high - close)) / tmp) * (inVolume[today])
  3195. }
  3196. today++
  3197. fastEMA = (fastk * ad) + (oneMinusfastk * fastEMA)
  3198. slowEMA = (slowk * ad) + (oneMinusslowk * slowEMA)
  3199. }
  3200. outIdx := lookbackTotal
  3201. for today < len(inClose) {
  3202. high = inHigh[today]
  3203. low = inLow[today]
  3204. tmp = high - low
  3205. close = inClose[today]
  3206. if tmp > 0.0 {
  3207. ad += (((close - low) - (high - close)) / tmp) * (inVolume[today])
  3208. }
  3209. today++
  3210. fastEMA = (fastk * ad) + (oneMinusfastk * fastEMA)
  3211. slowEMA = (slowk * ad) + (oneMinusslowk * slowEMA)
  3212. outReal[outIdx] = fastEMA - slowEMA
  3213. outIdx++
  3214. }
  3215. return outReal
  3216. }
  3217. // Obv - On Balance Volume
  3218. func Obv(inReal []float64, inVolume []float64) []float64 {
  3219. outReal := make([]float64, len(inReal))
  3220. startIdx := 0
  3221. prevOBV := inVolume[startIdx]
  3222. prevReal := inReal[startIdx]
  3223. outIdx := 0
  3224. for i := startIdx; i < len(inReal); i++ {
  3225. tempReal := inReal[i]
  3226. if tempReal > prevReal {
  3227. prevOBV += inVolume[i]
  3228. } else if tempReal < prevReal {
  3229. prevOBV -= inVolume[i]
  3230. }
  3231. outReal[outIdx] = prevOBV
  3232. prevReal = tempReal
  3233. outIdx++
  3234. }
  3235. return outReal
  3236. }
  3237. /* Volatility Indicators */
  3238. // Atr - Average True Range
  3239. func Atr(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  3240. outReal := make([]float64, len(inClose))
  3241. inTimePeriodF := float64(inTimePeriod)
  3242. if inTimePeriod < 1 {
  3243. return outReal
  3244. }
  3245. if inTimePeriod <= 1 {
  3246. return TRange(inHigh, inLow, inClose)
  3247. }
  3248. outIdx := inTimePeriod
  3249. today := inTimePeriod + 1
  3250. tr := TRange(inHigh, inLow, inClose)
  3251. prevATRTemp := Sma(tr, inTimePeriod)
  3252. prevATR := prevATRTemp[inTimePeriod]
  3253. outReal[inTimePeriod] = prevATR
  3254. for outIdx = inTimePeriod + 1; outIdx < len(inClose); outIdx++ {
  3255. prevATR *= inTimePeriodF - 1.0
  3256. prevATR += tr[today]
  3257. prevATR /= inTimePeriodF
  3258. outReal[outIdx] = prevATR
  3259. today++
  3260. }
  3261. return outReal
  3262. }
  3263. // Natr - Normalized Average True Range
  3264. func Natr(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
  3265. outReal := make([]float64, len(inClose))
  3266. if inTimePeriod < 1 {
  3267. return outReal
  3268. }
  3269. if inTimePeriod <= 1 {
  3270. return TRange(inHigh, inLow, inClose)
  3271. }
  3272. inTimePeriodF := float64(inTimePeriod)
  3273. outIdx := inTimePeriod
  3274. today := inTimePeriod
  3275. tr := TRange(inHigh, inLow, inClose)
  3276. prevATRTemp := Sma(tr, inTimePeriod)
  3277. prevATR := prevATRTemp[inTimePeriod]
  3278. tempValue := inClose[today]
  3279. if tempValue != 0.0 {
  3280. outReal[outIdx] = (prevATR / tempValue) * 100.0
  3281. } else {
  3282. outReal[outIdx] = 0.0
  3283. }
  3284. for outIdx = inTimePeriod + 1; outIdx < len(inClose); outIdx++ {
  3285. today++
  3286. prevATR *= inTimePeriodF - 1.0
  3287. prevATR += tr[today]
  3288. prevATR /= inTimePeriodF
  3289. tempValue = inClose[today]
  3290. if tempValue != 0.0 {
  3291. outReal[outIdx] = (prevATR / tempValue) * 100.0
  3292. } else {
  3293. outReal[0] = 0.0
  3294. }
  3295. }
  3296. return outReal
  3297. }
  3298. // TRange - True Range
  3299. func TRange(inHigh []float64, inLow []float64, inClose []float64) []float64 {
  3300. outReal := make([]float64, len(inClose))
  3301. startIdx := 1
  3302. outIdx := startIdx
  3303. today := startIdx
  3304. for today < len(inClose) {
  3305. tempLT := inLow[today]
  3306. tempHT := inHigh[today]
  3307. tempCY := inClose[today-1]
  3308. greatest := tempHT - tempLT
  3309. val2 := math.Abs(tempCY - tempHT)
  3310. if val2 > greatest {
  3311. greatest = val2
  3312. }
  3313. val3 := math.Abs(tempCY - tempLT)
  3314. if val3 > greatest {
  3315. greatest = val3
  3316. }
  3317. outReal[outIdx] = greatest
  3318. outIdx++
  3319. today++
  3320. }
  3321. return outReal
  3322. }
  3323. /* Price Transform */
  3324. // AvgPrice - Average Price (o+h+l+c)/4
  3325. func AvgPrice(inOpen []float64, inHigh []float64, inLow []float64, inClose []float64) []float64 {
  3326. outReal := make([]float64, len(inClose))
  3327. outIdx := 0
  3328. startIdx := 0
  3329. for i := startIdx; i < len(inClose); i++ {
  3330. outReal[outIdx] = (inHigh[i] + inLow[i] + inClose[i] + inOpen[i]) / 4
  3331. outIdx++
  3332. }
  3333. return outReal
  3334. }
  3335. // MedPrice - Median Price (h+l)/2
  3336. func MedPrice(inHigh []float64, inLow []float64) []float64 {
  3337. outReal := make([]float64, len(inHigh))
  3338. outIdx := 0
  3339. startIdx := 0
  3340. for i := startIdx; i < len(inHigh); i++ {
  3341. outReal[outIdx] = (inHigh[i] + inLow[i]) / 2.0
  3342. outIdx++
  3343. }
  3344. return outReal
  3345. }
  3346. // TypPrice - Typical Price (h+l+c)/3
  3347. func TypPrice(inHigh []float64, inLow []float64, inClose []float64) []float64 {
  3348. outReal := make([]float64, len(inClose))
  3349. outIdx := 0
  3350. startIdx := 0
  3351. for i := startIdx; i < len(inClose); i++ {
  3352. outReal[outIdx] = (inHigh[i] + inLow[i] + inClose[i]) / 3.0
  3353. outIdx++
  3354. }
  3355. return outReal
  3356. }
  3357. // WclPrice - Weighted Close Price
  3358. func WclPrice(inHigh []float64, inLow []float64, inClose []float64) []float64 {
  3359. outReal := make([]float64, len(inClose))
  3360. outIdx := 0
  3361. startIdx := 0
  3362. for i := startIdx; i < len(inClose); i++ {
  3363. outReal[outIdx] = (inHigh[i] + inLow[i] + (inClose[i] * 2.0)) / 4.0
  3364. outIdx++
  3365. }
  3366. return outReal
  3367. }
  3368. /* Cycle Indicators */
  3369. // HtDcPeriod - Hilbert Transform - Dominant Cycle Period (lookback=32)
  3370. func HtDcPeriod(inReal []float64) []float64 {
  3371. outReal := make([]float64, len(inReal))
  3372. a := 0.0962
  3373. b := 0.5769
  3374. detrenderOdd := make([]float64, 3)
  3375. detrenderEven := make([]float64, 3)
  3376. q1Odd := make([]float64, 3)
  3377. q1Even := make([]float64, 3)
  3378. jIOdd := make([]float64, 3)
  3379. jIEven := make([]float64, 3)
  3380. jQOdd := make([]float64, 3)
  3381. jQEven := make([]float64, 3)
  3382. rad2Deg := 180.0 / (4.0 * math.Atan(1))
  3383. lookbackTotal := 32
  3384. startIdx := lookbackTotal
  3385. trailingWMAIdx := startIdx - lookbackTotal
  3386. today := trailingWMAIdx
  3387. tempReal := inReal[today]
  3388. today++
  3389. periodWMASub := tempReal
  3390. periodWMASum := tempReal
  3391. tempReal = inReal[today]
  3392. today++
  3393. periodWMASub += tempReal
  3394. periodWMASum += tempReal * 2.0
  3395. tempReal = inReal[today]
  3396. today++
  3397. periodWMASub += tempReal
  3398. periodWMASum += tempReal * 3.0
  3399. trailingWMAValue := 0.0
  3400. i := 9
  3401. smoothedValue := 0.0
  3402. for ok := true; ok; {
  3403. tempReal = inReal[today]
  3404. today++
  3405. periodWMASub += tempReal
  3406. periodWMASub -= trailingWMAValue
  3407. periodWMASum += tempReal * 4.0
  3408. trailingWMAValue = inReal[trailingWMAIdx]
  3409. trailingWMAIdx++
  3410. smoothedValue = periodWMASum * 0.1
  3411. periodWMASum -= periodWMASub
  3412. i--
  3413. ok = i != 0
  3414. }
  3415. hilbertIdx := 0
  3416. detrender := 0.0
  3417. prevDetrenderOdd := 0.0
  3418. prevDetrenderEven := 0.0
  3419. prevDetrenderInputOdd := 0.0
  3420. prevDetrenderInputEven := 0.0
  3421. q1 := 0.0
  3422. prevq1Odd := 0.0
  3423. prevq1Even := 0.0
  3424. prevq1InputOdd := 0.0
  3425. prevq1InputEven := 0.0
  3426. jI := 0.0
  3427. prevJIOdd := 0.0
  3428. prevJIEven := 0.0
  3429. prevJIInputOdd := 0.0
  3430. prevJIInputEven := 0.0
  3431. jQ := 0.0
  3432. prevJQOdd := 0.0
  3433. prevJQEven := 0.0
  3434. prevJQInputOdd := 0.0
  3435. prevJQInputEven := 0.0
  3436. period := 0.0
  3437. outIdx := 32
  3438. previ2 := 0.0
  3439. prevq2 := 0.0
  3440. Re := 0.0
  3441. Im := 0.0
  3442. i2 := 0.0
  3443. q2 := 0.0
  3444. i1ForOddPrev3 := 0.0
  3445. i1ForEvenPrev3 := 0.0
  3446. i1ForOddPrev2 := 0.0
  3447. i1ForEvenPrev2 := 0.0
  3448. smoothPeriod := 0.0
  3449. for today < len(inReal) {
  3450. adjustedPrevPeriod := (0.075 * period) + 0.54
  3451. todayValue := inReal[today]
  3452. periodWMASub += todayValue
  3453. periodWMASub -= trailingWMAValue
  3454. periodWMASum += todayValue * 4.0
  3455. trailingWMAValue = inReal[trailingWMAIdx]
  3456. trailingWMAIdx++
  3457. smoothedValue = periodWMASum * 0.1
  3458. periodWMASum -= periodWMASub
  3459. hilbertTempReal := 0.0
  3460. if (today % 2) == 0 {
  3461. hilbertTempReal = a * smoothedValue
  3462. detrender = -detrenderEven[hilbertIdx]
  3463. detrenderEven[hilbertIdx] = hilbertTempReal
  3464. detrender += hilbertTempReal
  3465. detrender -= prevDetrenderEven
  3466. prevDetrenderEven = b * prevDetrenderInputEven
  3467. detrender += prevDetrenderEven
  3468. prevDetrenderInputEven = smoothedValue
  3469. detrender *= adjustedPrevPeriod
  3470. hilbertTempReal = a * detrender
  3471. q1 = -q1Even[hilbertIdx]
  3472. q1Even[hilbertIdx] = hilbertTempReal
  3473. q1 += hilbertTempReal
  3474. q1 -= prevq1Even
  3475. prevq1Even = b * prevq1InputEven
  3476. q1 += prevq1Even
  3477. prevq1InputEven = detrender
  3478. q1 *= adjustedPrevPeriod
  3479. hilbertTempReal = a * i1ForEvenPrev3
  3480. jI = -jIEven[hilbertIdx]
  3481. jIEven[hilbertIdx] = hilbertTempReal
  3482. jI += hilbertTempReal
  3483. jI -= prevJIEven
  3484. prevJIEven = b * prevJIInputEven
  3485. jI += prevJIEven
  3486. prevJIInputEven = i1ForEvenPrev3
  3487. jI *= adjustedPrevPeriod
  3488. hilbertTempReal = a * q1
  3489. jQ = -jQEven[hilbertIdx]
  3490. jQEven[hilbertIdx] = hilbertTempReal
  3491. jQ += hilbertTempReal
  3492. jQ -= prevJQEven
  3493. prevJQEven = b * prevJQInputEven
  3494. jQ += prevJQEven
  3495. prevJQInputEven = q1
  3496. jQ *= adjustedPrevPeriod
  3497. hilbertIdx++
  3498. if hilbertIdx == 3 {
  3499. hilbertIdx = 0
  3500. }
  3501. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  3502. i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
  3503. i1ForOddPrev3 = i1ForOddPrev2
  3504. i1ForOddPrev2 = detrender
  3505. } else {
  3506. hilbertTempReal = a * smoothedValue
  3507. detrender = -detrenderOdd[hilbertIdx]
  3508. detrenderOdd[hilbertIdx] = hilbertTempReal
  3509. detrender += hilbertTempReal
  3510. detrender -= prevDetrenderOdd
  3511. prevDetrenderOdd = b * prevDetrenderInputOdd
  3512. detrender += prevDetrenderOdd
  3513. prevDetrenderInputOdd = smoothedValue
  3514. detrender *= adjustedPrevPeriod
  3515. hilbertTempReal = a * detrender
  3516. q1 = -q1Odd[hilbertIdx]
  3517. q1Odd[hilbertIdx] = hilbertTempReal
  3518. q1 += hilbertTempReal
  3519. q1 -= prevq1Odd
  3520. prevq1Odd = b * prevq1InputOdd
  3521. q1 += prevq1Odd
  3522. prevq1InputOdd = detrender
  3523. q1 *= adjustedPrevPeriod
  3524. hilbertTempReal = a * i1ForOddPrev3
  3525. jI = -jIOdd[hilbertIdx]
  3526. jIOdd[hilbertIdx] = hilbertTempReal
  3527. jI += hilbertTempReal
  3528. jI -= prevJIOdd
  3529. prevJIOdd = b * prevJIInputOdd
  3530. jI += prevJIOdd
  3531. prevJIInputOdd = i1ForOddPrev3
  3532. jI *= adjustedPrevPeriod
  3533. hilbertTempReal = a * q1
  3534. jQ = -jQOdd[hilbertIdx]
  3535. jQOdd[hilbertIdx] = hilbertTempReal
  3536. jQ += hilbertTempReal
  3537. jQ -= prevJQOdd
  3538. prevJQOdd = b * prevJQInputOdd
  3539. jQ += prevJQOdd
  3540. prevJQInputOdd = q1
  3541. jQ *= adjustedPrevPeriod
  3542. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  3543. i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
  3544. i1ForEvenPrev3 = i1ForEvenPrev2
  3545. i1ForEvenPrev2 = detrender
  3546. }
  3547. Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
  3548. Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
  3549. prevq2 = q2
  3550. previ2 = i2
  3551. tempReal = period
  3552. if (Im != 0.0) && (Re != 0.0) {
  3553. period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
  3554. }
  3555. tempReal2 := 1.5 * tempReal
  3556. if period > tempReal2 {
  3557. period = tempReal2
  3558. }
  3559. tempReal2 = 0.67 * tempReal
  3560. if period < tempReal2 {
  3561. period = tempReal2
  3562. }
  3563. if period < 6 {
  3564. period = 6
  3565. } else if period > 50 {
  3566. period = 50
  3567. }
  3568. period = (0.2 * period) + (0.8 * tempReal)
  3569. smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
  3570. if today >= startIdx {
  3571. outReal[outIdx] = smoothPeriod
  3572. outIdx++
  3573. }
  3574. today++
  3575. }
  3576. return outReal
  3577. }
  3578. // HtDcPhase - Hilbert Transform - Dominant Cycle Phase (lookback=63)
  3579. func HtDcPhase(inReal []float64) []float64 {
  3580. outReal := make([]float64, len(inReal))
  3581. a := 0.0962
  3582. b := 0.5769
  3583. detrenderOdd := make([]float64, 3)
  3584. detrenderEven := make([]float64, 3)
  3585. q1Odd := make([]float64, 3)
  3586. q1Even := make([]float64, 3)
  3587. jIOdd := make([]float64, 3)
  3588. jIEven := make([]float64, 3)
  3589. jQOdd := make([]float64, 3)
  3590. jQEven := make([]float64, 3)
  3591. smoothPriceIdx := 0
  3592. maxIdxSmoothPrice := (50 - 1)
  3593. smoothPrice := make([]float64, maxIdxSmoothPrice+1)
  3594. tempReal := math.Atan(1)
  3595. rad2Deg := 45.0 / tempReal
  3596. constDeg2RadBy360 := tempReal * 8.0
  3597. lookbackTotal := 63
  3598. startIdx := lookbackTotal
  3599. trailingWMAIdx := startIdx - lookbackTotal
  3600. today := trailingWMAIdx
  3601. tempReal = inReal[today]
  3602. today++
  3603. periodWMASub := tempReal
  3604. periodWMASum := tempReal
  3605. tempReal = inReal[today]
  3606. today++
  3607. periodWMASub += tempReal
  3608. periodWMASum += tempReal * 2.0
  3609. tempReal = inReal[today]
  3610. today++
  3611. periodWMASub += tempReal
  3612. periodWMASum += tempReal * 3.0
  3613. trailingWMAValue := 0.0
  3614. i := 34
  3615. smoothedValue := 0.0
  3616. for ok := true; ok; {
  3617. tempReal = inReal[today]
  3618. today++
  3619. periodWMASub += tempReal
  3620. periodWMASub -= trailingWMAValue
  3621. periodWMASum += tempReal * 4.0
  3622. trailingWMAValue = inReal[trailingWMAIdx]
  3623. trailingWMAIdx++
  3624. smoothedValue = periodWMASum * 0.1
  3625. periodWMASum -= periodWMASub
  3626. i--
  3627. ok = i != 0
  3628. }
  3629. hilbertIdx := 0
  3630. detrender := 0.0
  3631. prevDetrenderOdd := 0.0
  3632. prevDetrenderEven := 0.0
  3633. prevDetrenderInputOdd := 0.0
  3634. prevDetrenderInputEven := 0.0
  3635. q1 := 0.0
  3636. prevq1Odd := 0.0
  3637. prevq1Even := 0.0
  3638. prevq1InputOdd := 0.0
  3639. prevq1InputEven := 0.0
  3640. jI := 0.0
  3641. prevJIOdd := 0.0
  3642. prevJIEven := 0.0
  3643. prevJIInputOdd := 0.0
  3644. prevJIInputEven := 0.0
  3645. jQ := 0.0
  3646. prevJQOdd := 0.0
  3647. prevJQEven := 0.0
  3648. prevJQInputOdd := 0.0
  3649. prevJQInputEven := 0.0
  3650. period := 0.0
  3651. outIdx := 0
  3652. previ2 := 0.0
  3653. prevq2 := 0.0
  3654. Re := 0.0
  3655. Im := 0.0
  3656. i1ForOddPrev3 := 0.0
  3657. i1ForEvenPrev3 := 0.0
  3658. i1ForOddPrev2 := 0.0
  3659. i1ForEvenPrev2 := 0.0
  3660. smoothPeriod := 0.0
  3661. dcPhase := 0.0
  3662. q2 := 0.0
  3663. i2 := 0.0
  3664. for today < len(inReal) {
  3665. adjustedPrevPeriod := (0.075 * period) + 0.54
  3666. todayValue := inReal[today]
  3667. periodWMASub += todayValue
  3668. periodWMASub -= trailingWMAValue
  3669. periodWMASum += todayValue * 4.0
  3670. trailingWMAValue = inReal[trailingWMAIdx]
  3671. trailingWMAIdx++
  3672. smoothedValue = periodWMASum * 0.1
  3673. periodWMASum -= periodWMASub
  3674. hilbertTempReal := 0.0
  3675. smoothPrice[smoothPriceIdx] = smoothedValue
  3676. if (today % 2) == 0 {
  3677. hilbertTempReal = a * smoothedValue
  3678. detrender = -detrenderEven[hilbertIdx]
  3679. detrenderEven[hilbertIdx] = hilbertTempReal
  3680. detrender += hilbertTempReal
  3681. detrender -= prevDetrenderEven
  3682. prevDetrenderEven = b * prevDetrenderInputEven
  3683. detrender += prevDetrenderEven
  3684. prevDetrenderInputEven = smoothedValue
  3685. detrender *= adjustedPrevPeriod
  3686. hilbertTempReal = a * detrender
  3687. q1 = -q1Even[hilbertIdx]
  3688. q1Even[hilbertIdx] = hilbertTempReal
  3689. q1 += hilbertTempReal
  3690. q1 -= prevq1Even
  3691. prevq1Even = b * prevq1InputEven
  3692. q1 += prevq1Even
  3693. prevq1InputEven = detrender
  3694. q1 *= adjustedPrevPeriod
  3695. hilbertTempReal = a * i1ForEvenPrev3
  3696. jI = -jIEven[hilbertIdx]
  3697. jIEven[hilbertIdx] = hilbertTempReal
  3698. jI += hilbertTempReal
  3699. jI -= prevJIEven
  3700. prevJIEven = b * prevJIInputEven
  3701. jI += prevJIEven
  3702. prevJIInputEven = i1ForEvenPrev3
  3703. jI *= adjustedPrevPeriod
  3704. hilbertTempReal = a * q1
  3705. jQ = -jQEven[hilbertIdx]
  3706. jQEven[hilbertIdx] = hilbertTempReal
  3707. jQ += hilbertTempReal
  3708. jQ -= prevJQEven
  3709. prevJQEven = b * prevJQInputEven
  3710. jQ += prevJQEven
  3711. prevJQInputEven = q1
  3712. jQ *= adjustedPrevPeriod
  3713. hilbertIdx++
  3714. if hilbertIdx == 3 {
  3715. hilbertIdx = 0
  3716. }
  3717. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  3718. i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
  3719. i1ForOddPrev3 = i1ForOddPrev2
  3720. i1ForOddPrev2 = detrender
  3721. } else {
  3722. hilbertTempReal = a * smoothedValue
  3723. detrender = -detrenderOdd[hilbertIdx]
  3724. detrenderOdd[hilbertIdx] = hilbertTempReal
  3725. detrender += hilbertTempReal
  3726. detrender -= prevDetrenderOdd
  3727. prevDetrenderOdd = b * prevDetrenderInputOdd
  3728. detrender += prevDetrenderOdd
  3729. prevDetrenderInputOdd = smoothedValue
  3730. detrender *= adjustedPrevPeriod
  3731. hilbertTempReal = a * detrender
  3732. q1 = -q1Odd[hilbertIdx]
  3733. q1Odd[hilbertIdx] = hilbertTempReal
  3734. q1 += hilbertTempReal
  3735. q1 -= prevq1Odd
  3736. prevq1Odd = b * prevq1InputOdd
  3737. q1 += prevq1Odd
  3738. prevq1InputOdd = detrender
  3739. q1 *= adjustedPrevPeriod
  3740. hilbertTempReal = a * i1ForOddPrev3
  3741. jI = -jIOdd[hilbertIdx]
  3742. jIOdd[hilbertIdx] = hilbertTempReal
  3743. jI += hilbertTempReal
  3744. jI -= prevJIOdd
  3745. prevJIOdd = b * prevJIInputOdd
  3746. jI += prevJIOdd
  3747. prevJIInputOdd = i1ForOddPrev3
  3748. jI *= adjustedPrevPeriod
  3749. hilbertTempReal = a * q1
  3750. jQ = -jQOdd[hilbertIdx]
  3751. jQOdd[hilbertIdx] = hilbertTempReal
  3752. jQ += hilbertTempReal
  3753. jQ -= prevJQOdd
  3754. prevJQOdd = b * prevJQInputOdd
  3755. jQ += prevJQOdd
  3756. prevJQInputOdd = q1
  3757. jQ *= adjustedPrevPeriod
  3758. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  3759. i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
  3760. i1ForEvenPrev3 = i1ForEvenPrev2
  3761. i1ForEvenPrev2 = detrender
  3762. }
  3763. Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
  3764. Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
  3765. prevq2 = q2
  3766. previ2 = i2
  3767. tempReal = period
  3768. if (Im != 0.0) && (Re != 0.0) {
  3769. period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
  3770. }
  3771. tempReal2 := 1.5 * tempReal
  3772. if period > tempReal2 {
  3773. period = tempReal2
  3774. }
  3775. tempReal2 = 0.67 * tempReal
  3776. if period < tempReal2 {
  3777. period = tempReal2
  3778. }
  3779. if period < 6 {
  3780. period = 6
  3781. } else if period > 50 {
  3782. period = 50
  3783. }
  3784. period = (0.2 * period) + (0.8 * tempReal)
  3785. smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
  3786. DCPeriod := smoothPeriod + 0.5
  3787. DCPeriodInt := math.Floor(DCPeriod)
  3788. realPart := 0.0
  3789. imagPart := 0.0
  3790. idx := smoothPriceIdx
  3791. for i := 0; i < int(DCPeriodInt); i++ {
  3792. tempReal = (float64(i) * constDeg2RadBy360) / (DCPeriodInt * 1.0)
  3793. tempReal2 = smoothPrice[idx]
  3794. realPart += math.Sin(tempReal) * tempReal2
  3795. imagPart += math.Cos(tempReal) * tempReal2
  3796. if idx == 0 {
  3797. idx = 50 - 1
  3798. } else {
  3799. idx--
  3800. }
  3801. }
  3802. tempReal = math.Abs(imagPart)
  3803. if tempReal > 0.0 {
  3804. dcPhase = math.Atan(realPart/imagPart) * rad2Deg
  3805. } else if tempReal <= 0.01 {
  3806. if realPart < 0.0 {
  3807. dcPhase -= 90.0
  3808. } else if realPart > 0.0 {
  3809. dcPhase += 90.0
  3810. }
  3811. }
  3812. dcPhase += 90.0
  3813. dcPhase += 360.0 / smoothPeriod
  3814. if imagPart < 0.0 {
  3815. dcPhase += 180.0
  3816. }
  3817. if dcPhase > 315.0 {
  3818. dcPhase -= 360.0
  3819. }
  3820. if today >= startIdx {
  3821. outReal[outIdx] = dcPhase
  3822. outIdx++
  3823. }
  3824. smoothPriceIdx++
  3825. if smoothPriceIdx > maxIdxSmoothPrice {
  3826. smoothPriceIdx = 0
  3827. }
  3828. today++
  3829. }
  3830. return outReal
  3831. }
  3832. // HtPhasor - Hibert Transform - Phasor Components (lookback=32)
  3833. func HtPhasor(inReal []float64) ([]float64, []float64) {
  3834. outInPhase := make([]float64, len(inReal))
  3835. outQuadrature := make([]float64, len(inReal))
  3836. a := 0.0962
  3837. b := 0.5769
  3838. detrenderOdd := make([]float64, 3)
  3839. detrenderEven := make([]float64, 3)
  3840. q1Odd := make([]float64, 3)
  3841. q1Even := make([]float64, 3)
  3842. jIOdd := make([]float64, 3)
  3843. jIEven := make([]float64, 3)
  3844. jQOdd := make([]float64, 3)
  3845. jQEven := make([]float64, 3)
  3846. rad2Deg := 180.0 / (4.0 * math.Atan(1))
  3847. lookbackTotal := 32
  3848. startIdx := lookbackTotal
  3849. trailingWMAIdx := startIdx - lookbackTotal
  3850. today := trailingWMAIdx
  3851. tempReal := inReal[today]
  3852. today++
  3853. periodWMASub := tempReal
  3854. periodWMASum := tempReal
  3855. tempReal = inReal[today]
  3856. today++
  3857. periodWMASub += tempReal
  3858. periodWMASum += tempReal * 2.0
  3859. tempReal = inReal[today]
  3860. today++
  3861. periodWMASub += tempReal
  3862. periodWMASum += tempReal * 3.0
  3863. trailingWMAValue := 0.0
  3864. i := 9
  3865. smoothedValue := 0.0
  3866. for ok := true; ok; {
  3867. tempReal = inReal[today]
  3868. today++
  3869. periodWMASub += tempReal
  3870. periodWMASub -= trailingWMAValue
  3871. periodWMASum += tempReal * 4.0
  3872. trailingWMAValue = inReal[trailingWMAIdx]
  3873. trailingWMAIdx++
  3874. smoothedValue = periodWMASum * 0.1
  3875. periodWMASum -= periodWMASub
  3876. i--
  3877. ok = i != 0
  3878. }
  3879. hilbertIdx := 0
  3880. detrender := 0.0
  3881. prevDetrenderOdd := 0.0
  3882. prevDetrenderEven := 0.0
  3883. prevDetrenderInputOdd := 0.0
  3884. prevDetrenderInputEven := 0.0
  3885. q1 := 0.0
  3886. prevq1Odd := 0.0
  3887. prevq1Even := 0.0
  3888. prevq1InputOdd := 0.0
  3889. prevq1InputEven := 0.0
  3890. jI := 0.0
  3891. prevJIOdd := 0.0
  3892. prevJIEven := 0.0
  3893. prevJIInputOdd := 0.0
  3894. prevJIInputEven := 0.0
  3895. jQ := 0.0
  3896. prevJQOdd := 0.0
  3897. prevJQEven := 0.0
  3898. prevJQInputOdd := 0.0
  3899. prevJQInputEven := 0.0
  3900. period := 0.0
  3901. outIdx := 32
  3902. previ2 := 0.0
  3903. prevq2 := 0.0
  3904. Re := 0.0
  3905. Im := 0.0
  3906. i1ForOddPrev3 := 0.0
  3907. i1ForEvenPrev3 := 0.0
  3908. i1ForOddPrev2 := 0.0
  3909. i1ForEvenPrev2 := 0.0
  3910. i2 := 0.0
  3911. q2 := 0.0
  3912. for today < len(inReal) {
  3913. adjustedPrevPeriod := (0.075 * period) + 0.54
  3914. todayValue := inReal[today]
  3915. periodWMASub += todayValue
  3916. periodWMASub -= trailingWMAValue
  3917. periodWMASum += todayValue * 4.0
  3918. trailingWMAValue = inReal[trailingWMAIdx]
  3919. trailingWMAIdx++
  3920. smoothedValue = periodWMASum * 0.1
  3921. periodWMASum -= periodWMASub
  3922. hilbertTempReal := 0.0
  3923. if (today % 2) == 0 {
  3924. hilbertTempReal = a * smoothedValue
  3925. detrender = -detrenderEven[hilbertIdx]
  3926. detrenderEven[hilbertIdx] = hilbertTempReal
  3927. detrender += hilbertTempReal
  3928. detrender -= prevDetrenderEven
  3929. prevDetrenderEven = b * prevDetrenderInputEven
  3930. detrender += prevDetrenderEven
  3931. prevDetrenderInputEven = smoothedValue
  3932. detrender *= adjustedPrevPeriod
  3933. hilbertTempReal = a * detrender
  3934. q1 = -q1Even[hilbertIdx]
  3935. q1Even[hilbertIdx] = hilbertTempReal
  3936. q1 += hilbertTempReal
  3937. q1 -= prevq1Even
  3938. prevq1Even = b * prevq1InputEven
  3939. q1 += prevq1Even
  3940. prevq1InputEven = detrender
  3941. q1 *= adjustedPrevPeriod
  3942. if today >= startIdx {
  3943. outQuadrature[outIdx] = q1
  3944. outInPhase[outIdx] = i1ForEvenPrev3
  3945. outIdx++
  3946. }
  3947. hilbertTempReal = a * i1ForEvenPrev3
  3948. jI = -jIEven[hilbertIdx]
  3949. jIEven[hilbertIdx] = hilbertTempReal
  3950. jI += hilbertTempReal
  3951. jI -= prevJIEven
  3952. prevJIEven = b * prevJIInputEven
  3953. jI += prevJIEven
  3954. prevJIInputEven = i1ForEvenPrev3
  3955. jI *= adjustedPrevPeriod
  3956. hilbertTempReal = a * q1
  3957. jQ = -jQEven[hilbertIdx]
  3958. jQEven[hilbertIdx] = hilbertTempReal
  3959. jQ += hilbertTempReal
  3960. jQ -= prevJQEven
  3961. prevJQEven = b * prevJQInputEven
  3962. jQ += prevJQEven
  3963. prevJQInputEven = q1
  3964. jQ *= adjustedPrevPeriod
  3965. hilbertIdx++
  3966. if hilbertIdx == 3 {
  3967. hilbertIdx = 0
  3968. }
  3969. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  3970. i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
  3971. i1ForOddPrev3 = i1ForOddPrev2
  3972. i1ForOddPrev2 = detrender
  3973. } else {
  3974. hilbertTempReal = a * smoothedValue
  3975. detrender = -detrenderOdd[hilbertIdx]
  3976. detrenderOdd[hilbertIdx] = hilbertTempReal
  3977. detrender += hilbertTempReal
  3978. detrender -= prevDetrenderOdd
  3979. prevDetrenderOdd = b * prevDetrenderInputOdd
  3980. detrender += prevDetrenderOdd
  3981. prevDetrenderInputOdd = smoothedValue
  3982. detrender *= adjustedPrevPeriod
  3983. hilbertTempReal = a * detrender
  3984. q1 = -q1Odd[hilbertIdx]
  3985. q1Odd[hilbertIdx] = hilbertTempReal
  3986. q1 += hilbertTempReal
  3987. q1 -= prevq1Odd
  3988. prevq1Odd = b * prevq1InputOdd
  3989. q1 += prevq1Odd
  3990. prevq1InputOdd = detrender
  3991. q1 *= adjustedPrevPeriod
  3992. if today >= startIdx {
  3993. outQuadrature[outIdx] = q1
  3994. outInPhase[outIdx] = i1ForOddPrev3
  3995. outIdx++
  3996. }
  3997. hilbertTempReal = a * i1ForOddPrev3
  3998. jI = -jIOdd[hilbertIdx]
  3999. jIOdd[hilbertIdx] = hilbertTempReal
  4000. jI += hilbertTempReal
  4001. jI -= prevJIOdd
  4002. prevJIOdd = b * prevJIInputOdd
  4003. jI += prevJIOdd
  4004. prevJIInputOdd = i1ForOddPrev3
  4005. jI *= adjustedPrevPeriod
  4006. hilbertTempReal = a * q1
  4007. jQ = -jQOdd[hilbertIdx]
  4008. jQOdd[hilbertIdx] = hilbertTempReal
  4009. jQ += hilbertTempReal
  4010. jQ -= prevJQOdd
  4011. prevJQOdd = b * prevJQInputOdd
  4012. jQ += prevJQOdd
  4013. prevJQInputOdd = q1
  4014. jQ *= adjustedPrevPeriod
  4015. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  4016. i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
  4017. i1ForEvenPrev3 = i1ForEvenPrev2
  4018. i1ForEvenPrev2 = detrender
  4019. }
  4020. Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
  4021. Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
  4022. prevq2 = q2
  4023. previ2 = i2
  4024. tempReal = period
  4025. if (Im != 0.0) && (Re != 0.0) {
  4026. period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
  4027. }
  4028. tempReal2 := 1.5 * tempReal
  4029. if period > tempReal2 {
  4030. period = tempReal2
  4031. }
  4032. tempReal2 = 0.67 * tempReal
  4033. if period < tempReal2 {
  4034. period = tempReal2
  4035. }
  4036. if period < 6 {
  4037. period = 6
  4038. } else if period > 50 {
  4039. period = 50
  4040. }
  4041. period = (0.2 * period) + (0.8 * tempReal)
  4042. today++
  4043. }
  4044. return outInPhase, outQuadrature
  4045. }
  4046. // HtSine - Hilbert Transform - SineWave (lookback=63)
  4047. func HtSine(inReal []float64) ([]float64, []float64) {
  4048. outSine := make([]float64, len(inReal))
  4049. outLeadSine := make([]float64, len(inReal))
  4050. a := 0.0962
  4051. b := 0.5769
  4052. detrenderOdd := make([]float64, 3)
  4053. detrenderEven := make([]float64, 3)
  4054. q1Odd := make([]float64, 3)
  4055. q1Even := make([]float64, 3)
  4056. jIOdd := make([]float64, 3)
  4057. jIEven := make([]float64, 3)
  4058. jQOdd := make([]float64, 3)
  4059. jQEven := make([]float64, 3)
  4060. smoothPriceIdx := 0
  4061. maxIdxSmoothPrice := (50 - 1)
  4062. smoothPrice := make([]float64, maxIdxSmoothPrice+1)
  4063. tempReal := math.Atan(1)
  4064. rad2Deg := 45.0 / tempReal
  4065. deg2Rad := 1.0 / rad2Deg
  4066. constDeg2RadBy360 := tempReal * 8.0
  4067. lookbackTotal := 63
  4068. startIdx := lookbackTotal
  4069. trailingWMAIdx := startIdx - lookbackTotal
  4070. today := trailingWMAIdx
  4071. tempReal = inReal[today]
  4072. today++
  4073. periodWMASub := tempReal
  4074. periodWMASum := tempReal
  4075. tempReal = inReal[today]
  4076. today++
  4077. periodWMASub += tempReal
  4078. periodWMASum += tempReal * 2.0
  4079. tempReal = inReal[today]
  4080. today++
  4081. periodWMASub += tempReal
  4082. periodWMASum += tempReal * 3.0
  4083. trailingWMAValue := 0.0
  4084. i := 34
  4085. smoothedValue := 0.0
  4086. for ok := true; ok; {
  4087. tempReal = inReal[today]
  4088. today++
  4089. periodWMASub += tempReal
  4090. periodWMASub -= trailingWMAValue
  4091. periodWMASum += tempReal * 4.0
  4092. trailingWMAValue = inReal[trailingWMAIdx]
  4093. trailingWMAIdx++
  4094. smoothedValue = periodWMASum * 0.1
  4095. periodWMASum -= periodWMASub
  4096. i--
  4097. ok = i != 0
  4098. }
  4099. hilbertIdx := 0
  4100. detrender := 0.0
  4101. prevDetrenderOdd := 0.0
  4102. prevDetrenderEven := 0.0
  4103. prevDetrenderInputOdd := 0.0
  4104. prevDetrenderInputEven := 0.0
  4105. q1 := 0.0
  4106. prevq1Odd := 0.0
  4107. prevq1Even := 0.0
  4108. prevq1InputOdd := 0.0
  4109. prevq1InputEven := 0.0
  4110. jI := 0.0
  4111. prevJIOdd := 0.0
  4112. prevJIEven := 0.0
  4113. prevJIInputOdd := 0.0
  4114. prevJIInputEven := 0.0
  4115. jQ := 0.0
  4116. prevJQOdd := 0.0
  4117. prevJQEven := 0.0
  4118. prevJQInputOdd := 0.0
  4119. prevJQInputEven := 0.0
  4120. period := 0.0
  4121. outIdx := 63
  4122. previ2 := 0.0
  4123. prevq2 := 0.0
  4124. Re := 0.0
  4125. Im := 0.0
  4126. i1ForOddPrev3 := 0.0
  4127. i1ForEvenPrev3 := 0.0
  4128. i1ForOddPrev2 := 0.0
  4129. i1ForEvenPrev2 := 0.0
  4130. smoothPeriod := 0.0
  4131. dcPhase := 0.0
  4132. hilbertTempReal := 0.0
  4133. q2 := 0.0
  4134. i2 := 0.0
  4135. for today < len(inReal) {
  4136. adjustedPrevPeriod := (0.075 * period) + 0.54
  4137. todayValue := inReal[today]
  4138. periodWMASub += todayValue
  4139. periodWMASub -= trailingWMAValue
  4140. periodWMASum += todayValue * 4.0
  4141. trailingWMAValue = inReal[trailingWMAIdx]
  4142. trailingWMAIdx++
  4143. smoothedValue = periodWMASum * 0.1
  4144. periodWMASum -= periodWMASub
  4145. smoothPrice[smoothPriceIdx] = smoothedValue
  4146. if (today % 2) == 0 {
  4147. hilbertTempReal = a * smoothedValue
  4148. detrender = -detrenderEven[hilbertIdx]
  4149. detrenderEven[hilbertIdx] = hilbertTempReal
  4150. detrender += hilbertTempReal
  4151. detrender -= prevDetrenderEven
  4152. prevDetrenderEven = b * prevDetrenderInputEven
  4153. detrender += prevDetrenderEven
  4154. prevDetrenderInputEven = smoothedValue
  4155. detrender *= adjustedPrevPeriod
  4156. hilbertTempReal = a * detrender
  4157. q1 = -q1Even[hilbertIdx]
  4158. q1Even[hilbertIdx] = hilbertTempReal
  4159. q1 += hilbertTempReal
  4160. q1 -= prevq1Even
  4161. prevq1Even = b * prevq1InputEven
  4162. q1 += prevq1Even
  4163. prevq1InputEven = detrender
  4164. q1 *= adjustedPrevPeriod
  4165. hilbertTempReal = a * i1ForEvenPrev3
  4166. jI = -jIEven[hilbertIdx]
  4167. jIEven[hilbertIdx] = hilbertTempReal
  4168. jI += hilbertTempReal
  4169. jI -= prevJIEven
  4170. prevJIEven = b * prevJIInputEven
  4171. jI += prevJIEven
  4172. prevJIInputEven = i1ForEvenPrev3
  4173. jI *= adjustedPrevPeriod
  4174. hilbertTempReal = a * q1
  4175. jQ = -jQEven[hilbertIdx]
  4176. jQEven[hilbertIdx] = hilbertTempReal
  4177. jQ += hilbertTempReal
  4178. jQ -= prevJQEven
  4179. prevJQEven = b * prevJQInputEven
  4180. jQ += prevJQEven
  4181. prevJQInputEven = q1
  4182. jQ *= adjustedPrevPeriod
  4183. hilbertIdx++
  4184. if hilbertIdx == 3 {
  4185. hilbertIdx = 0
  4186. }
  4187. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  4188. i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
  4189. i1ForOddPrev3 = i1ForOddPrev2
  4190. i1ForOddPrev2 = detrender
  4191. } else {
  4192. hilbertTempReal = a * smoothedValue
  4193. detrender = -detrenderOdd[hilbertIdx]
  4194. detrenderOdd[hilbertIdx] = hilbertTempReal
  4195. detrender += hilbertTempReal
  4196. detrender -= prevDetrenderOdd
  4197. prevDetrenderOdd = b * prevDetrenderInputOdd
  4198. detrender += prevDetrenderOdd
  4199. prevDetrenderInputOdd = smoothedValue
  4200. detrender *= adjustedPrevPeriod
  4201. hilbertTempReal = a * detrender
  4202. q1 = -q1Odd[hilbertIdx]
  4203. q1Odd[hilbertIdx] = hilbertTempReal
  4204. q1 += hilbertTempReal
  4205. q1 -= prevq1Odd
  4206. prevq1Odd = b * prevq1InputOdd
  4207. q1 += prevq1Odd
  4208. prevq1InputOdd = detrender
  4209. q1 *= adjustedPrevPeriod
  4210. hilbertTempReal = a * i1ForOddPrev3
  4211. jI = -jIOdd[hilbertIdx]
  4212. jIOdd[hilbertIdx] = hilbertTempReal
  4213. jI += hilbertTempReal
  4214. jI -= prevJIOdd
  4215. prevJIOdd = b * prevJIInputOdd
  4216. jI += prevJIOdd
  4217. prevJIInputOdd = i1ForOddPrev3
  4218. jI *= adjustedPrevPeriod
  4219. hilbertTempReal = a * q1
  4220. jQ = -jQOdd[hilbertIdx]
  4221. jQOdd[hilbertIdx] = hilbertTempReal
  4222. jQ += hilbertTempReal
  4223. jQ -= prevJQOdd
  4224. prevJQOdd = b * prevJQInputOdd
  4225. jQ += prevJQOdd
  4226. prevJQInputOdd = q1
  4227. jQ *= adjustedPrevPeriod
  4228. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  4229. i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
  4230. i1ForEvenPrev3 = i1ForEvenPrev2
  4231. i1ForEvenPrev2 = detrender
  4232. }
  4233. Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
  4234. Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
  4235. prevq2 = q2
  4236. previ2 = i2
  4237. tempReal = period
  4238. if (Im != 0.0) && (Re != 0.0) {
  4239. period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
  4240. }
  4241. tempReal2 := 1.5 * tempReal
  4242. if period > tempReal2 {
  4243. period = tempReal2
  4244. }
  4245. tempReal2 = 0.67 * tempReal
  4246. if period < tempReal2 {
  4247. period = tempReal2
  4248. }
  4249. if period < 6 {
  4250. period = 6
  4251. } else if period > 50 {
  4252. period = 50
  4253. }
  4254. period = (0.2 * period) + (0.8 * tempReal)
  4255. smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
  4256. DCPeriod := smoothPeriod + 0.5
  4257. DCPeriodInt := math.Floor(DCPeriod)
  4258. realPart := 0.0
  4259. imagPart := 0.0
  4260. idx := smoothPriceIdx
  4261. for i := 0; i < int(DCPeriodInt); i++ {
  4262. tempReal = (float64(i) * constDeg2RadBy360) / (DCPeriodInt * 1.0)
  4263. tempReal2 = smoothPrice[idx]
  4264. realPart += math.Sin(tempReal) * tempReal2
  4265. imagPart += math.Cos(tempReal) * tempReal2
  4266. if idx == 0 {
  4267. idx = 50 - 1
  4268. } else {
  4269. idx--
  4270. }
  4271. }
  4272. tempReal = math.Abs(imagPart)
  4273. if tempReal > 0.0 {
  4274. dcPhase = math.Atan(realPart/imagPart) * rad2Deg
  4275. } else if tempReal <= 0.01 {
  4276. if realPart < 0.0 {
  4277. dcPhase -= 90.0
  4278. } else if realPart > 0.0 {
  4279. dcPhase += 90.0
  4280. }
  4281. }
  4282. dcPhase += 90.0
  4283. dcPhase += 360.0 / smoothPeriod
  4284. if imagPart < 0.0 {
  4285. dcPhase += 180.0
  4286. }
  4287. if dcPhase > 315.0 {
  4288. dcPhase -= 360.0
  4289. }
  4290. if today >= startIdx {
  4291. outSine[outIdx] = math.Sin(dcPhase * deg2Rad)
  4292. outLeadSine[outIdx] = math.Sin((dcPhase + 45) * deg2Rad)
  4293. outIdx++
  4294. }
  4295. smoothPriceIdx++
  4296. if smoothPriceIdx > maxIdxSmoothPrice {
  4297. smoothPriceIdx = 0
  4298. }
  4299. today++
  4300. }
  4301. return outSine, outLeadSine
  4302. }
  4303. // HtTrendMode - Hilbert Transform - Trend vs Cycle Mode (lookback=63)
  4304. func HtTrendMode(inReal []float64) []float64 {
  4305. outReal := make([]float64, len(inReal))
  4306. a := 0.0962
  4307. b := 0.5769
  4308. detrenderOdd := make([]float64, 3)
  4309. detrenderEven := make([]float64, 3)
  4310. q1Odd := make([]float64, 3)
  4311. q1Even := make([]float64, 3)
  4312. jIOdd := make([]float64, 3)
  4313. jIEven := make([]float64, 3)
  4314. jQOdd := make([]float64, 3)
  4315. jQEven := make([]float64, 3)
  4316. smoothPriceIdx := 0
  4317. maxIdxSmoothPrice := (50 - 1)
  4318. smoothPrice := make([]float64, maxIdxSmoothPrice+1)
  4319. iTrend1 := 0.0
  4320. iTrend2 := 0.0
  4321. iTrend3 := 0.0
  4322. daysInTrend := 0
  4323. prevdcPhase := 0.0
  4324. dcPhase := 0.0
  4325. prevSine := 0.0
  4326. sine := 0.0
  4327. prevLeadSine := 0.0
  4328. leadSine := 0.0
  4329. tempReal := math.Atan(1)
  4330. rad2Deg := 45.0 / tempReal
  4331. deg2Rad := 1.0 / rad2Deg
  4332. constDeg2RadBy360 := tempReal * 8.0
  4333. lookbackTotal := 63
  4334. startIdx := lookbackTotal
  4335. trailingWMAIdx := startIdx - lookbackTotal
  4336. today := trailingWMAIdx
  4337. tempReal = inReal[today]
  4338. today++
  4339. periodWMASub := tempReal
  4340. periodWMASum := tempReal
  4341. tempReal = inReal[today]
  4342. today++
  4343. periodWMASub += tempReal
  4344. periodWMASum += tempReal * 2.0
  4345. tempReal = inReal[today]
  4346. today++
  4347. periodWMASub += tempReal
  4348. periodWMASum += tempReal * 3.0
  4349. trailingWMAValue := 0.0
  4350. i := 34
  4351. for ok := true; ok; {
  4352. tempReal = inReal[today]
  4353. today++
  4354. periodWMASub += tempReal
  4355. periodWMASub -= trailingWMAValue
  4356. periodWMASum += tempReal * 4.0
  4357. trailingWMAValue = inReal[trailingWMAIdx]
  4358. trailingWMAIdx++
  4359. //smoothedValue := periodWMASum * 0.1
  4360. periodWMASum -= periodWMASub
  4361. i--
  4362. ok = i != 0
  4363. }
  4364. hilbertIdx := 0
  4365. detrender := 0.0
  4366. prevDetrenderOdd := 0.0
  4367. prevDetrenderEven := 0.0
  4368. prevDetrenderInputOdd := 0.0
  4369. prevDetrenderInputEven := 0.0
  4370. q1 := 0.0
  4371. prevq1Odd := 0.0
  4372. prevq1Even := 0.0
  4373. prevq1InputOdd := 0.0
  4374. prevq1InputEven := 0.0
  4375. jI := 0.0
  4376. prevJIOdd := 0.0
  4377. prevJIEven := 0.0
  4378. prevJIInputOdd := 0.0
  4379. prevJIInputEven := 0.0
  4380. jQ := 0.0
  4381. prevJQOdd := 0.0
  4382. prevJQEven := 0.0
  4383. prevJQInputOdd := 0.0
  4384. prevJQInputEven := 0.0
  4385. period := 0.0
  4386. outIdx := 63
  4387. previ2 := 0.0
  4388. prevq2 := 0.0
  4389. Re := 0.0
  4390. Im := 0.0
  4391. i1ForOddPrev3 := 0.0
  4392. i1ForEvenPrev3 := 0.0
  4393. i1ForOddPrev2 := 0.0
  4394. i1ForEvenPrev2 := 0.0
  4395. smoothPeriod := 0.0
  4396. dcPhase = 0.0
  4397. smoothedValue := 0.0
  4398. hilbertTempReal := 0.0
  4399. q2 := 0.0
  4400. i2 := 0.0
  4401. for today < len(inReal) {
  4402. adjustedPrevPeriod := (0.075 * period) + 0.54
  4403. todayValue := inReal[today]
  4404. periodWMASub += todayValue
  4405. periodWMASub -= trailingWMAValue
  4406. periodWMASum += todayValue * 4.0
  4407. trailingWMAValue = inReal[trailingWMAIdx]
  4408. trailingWMAIdx++
  4409. smoothedValue = periodWMASum * 0.1
  4410. periodWMASum -= periodWMASub
  4411. smoothPrice[smoothPriceIdx] = smoothedValue
  4412. if (today % 2) == 0 {
  4413. hilbertTempReal = a * smoothedValue
  4414. detrender = -detrenderEven[hilbertIdx]
  4415. detrenderEven[hilbertIdx] = hilbertTempReal
  4416. detrender += hilbertTempReal
  4417. detrender -= prevDetrenderEven
  4418. prevDetrenderEven = b * prevDetrenderInputEven
  4419. detrender += prevDetrenderEven
  4420. prevDetrenderInputEven = smoothedValue
  4421. detrender *= adjustedPrevPeriod
  4422. hilbertTempReal = a * detrender
  4423. q1 = -q1Even[hilbertIdx]
  4424. q1Even[hilbertIdx] = hilbertTempReal
  4425. q1 += hilbertTempReal
  4426. q1 -= prevq1Even
  4427. prevq1Even = b * prevq1InputEven
  4428. q1 += prevq1Even
  4429. prevq1InputEven = detrender
  4430. q1 *= adjustedPrevPeriod
  4431. hilbertTempReal = a * i1ForEvenPrev3
  4432. jI = -jIEven[hilbertIdx]
  4433. jIEven[hilbertIdx] = hilbertTempReal
  4434. jI += hilbertTempReal
  4435. jI -= prevJIEven
  4436. prevJIEven = b * prevJIInputEven
  4437. jI += prevJIEven
  4438. prevJIInputEven = i1ForEvenPrev3
  4439. jI *= adjustedPrevPeriod
  4440. hilbertTempReal = a * q1
  4441. jQ = -jQEven[hilbertIdx]
  4442. jQEven[hilbertIdx] = hilbertTempReal
  4443. jQ += hilbertTempReal
  4444. jQ -= prevJQEven
  4445. prevJQEven = b * prevJQInputEven
  4446. jQ += prevJQEven
  4447. prevJQInputEven = q1
  4448. jQ *= adjustedPrevPeriod
  4449. hilbertIdx++
  4450. if hilbertIdx == 3 {
  4451. hilbertIdx = 0
  4452. }
  4453. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  4454. i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
  4455. i1ForOddPrev3 = i1ForOddPrev2
  4456. i1ForOddPrev2 = detrender
  4457. } else {
  4458. hilbertTempReal = a * smoothedValue
  4459. detrender = -detrenderOdd[hilbertIdx]
  4460. detrenderOdd[hilbertIdx] = hilbertTempReal
  4461. detrender += hilbertTempReal
  4462. detrender -= prevDetrenderOdd
  4463. prevDetrenderOdd = b * prevDetrenderInputOdd
  4464. detrender += prevDetrenderOdd
  4465. prevDetrenderInputOdd = smoothedValue
  4466. detrender *= adjustedPrevPeriod
  4467. hilbertTempReal = a * detrender
  4468. q1 = -q1Odd[hilbertIdx]
  4469. q1Odd[hilbertIdx] = hilbertTempReal
  4470. q1 += hilbertTempReal
  4471. q1 -= prevq1Odd
  4472. prevq1Odd = b * prevq1InputOdd
  4473. q1 += prevq1Odd
  4474. prevq1InputOdd = detrender
  4475. q1 *= adjustedPrevPeriod
  4476. hilbertTempReal = a * i1ForOddPrev3
  4477. jI = -jIOdd[hilbertIdx]
  4478. jIOdd[hilbertIdx] = hilbertTempReal
  4479. jI += hilbertTempReal
  4480. jI -= prevJIOdd
  4481. prevJIOdd = b * prevJIInputOdd
  4482. jI += prevJIOdd
  4483. prevJIInputOdd = i1ForOddPrev3
  4484. jI *= adjustedPrevPeriod
  4485. hilbertTempReal = a * q1
  4486. jQ = -jQOdd[hilbertIdx]
  4487. jQOdd[hilbertIdx] = hilbertTempReal
  4488. jQ += hilbertTempReal
  4489. jQ -= prevJQOdd
  4490. prevJQOdd = b * prevJQInputOdd
  4491. jQ += prevJQOdd
  4492. prevJQInputOdd = q1
  4493. jQ *= adjustedPrevPeriod
  4494. q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
  4495. i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
  4496. i1ForEvenPrev3 = i1ForEvenPrev2
  4497. i1ForEvenPrev2 = detrender
  4498. }
  4499. Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
  4500. Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
  4501. prevq2 = q2
  4502. previ2 = i2
  4503. tempReal = period
  4504. if (Im != 0.0) && (Re != 0.0) {
  4505. period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
  4506. }
  4507. tempReal2 := 1.5 * tempReal
  4508. if period > tempReal2 {
  4509. period = tempReal2
  4510. }
  4511. tempReal2 = 0.67 * tempReal
  4512. if period < tempReal2 {
  4513. period = tempReal2
  4514. }
  4515. if period < 6 {
  4516. period = 6
  4517. } else if period > 50 {
  4518. period = 50
  4519. }
  4520. period = (0.2 * period) + (0.8 * tempReal)
  4521. smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
  4522. prevdcPhase = dcPhase
  4523. DCPeriod := smoothPeriod + 0.5
  4524. DCPeriodInt := math.Floor(DCPeriod)
  4525. realPart := 0.0
  4526. imagPart := 0.0
  4527. idx := smoothPriceIdx
  4528. for i := 0; i < int(DCPeriodInt); i++ {
  4529. tempReal = (float64(i) * constDeg2RadBy360) / (DCPeriodInt * 1.0)
  4530. tempReal2 = smoothPrice[idx]
  4531. realPart += math.Sin(tempReal) * tempReal2
  4532. imagPart += math.Cos(tempReal) * tempReal2
  4533. if idx == 0 {
  4534. idx = 50 - 1
  4535. } else {
  4536. idx--
  4537. }
  4538. }
  4539. tempReal = math.Abs(imagPart)
  4540. if tempReal > 0.0 {
  4541. dcPhase = math.Atan(realPart/imagPart) * rad2Deg
  4542. } else if tempReal <= 0.01 {
  4543. if realPart < 0.0 {
  4544. dcPhase -= 90.0
  4545. } else if realPart > 0.0 {
  4546. dcPhase += 90.0
  4547. }
  4548. }
  4549. dcPhase += 90.0
  4550. dcPhase += 360.0 / smoothPeriod
  4551. if imagPart < 0.0 {
  4552. dcPhase += 180.0
  4553. }
  4554. if dcPhase > 315.0 {
  4555. dcPhase -= 360.0
  4556. }
  4557. prevSine = sine
  4558. prevLeadSine = leadSine
  4559. sine = math.Sin(dcPhase * deg2Rad)
  4560. leadSine = math.Sin((dcPhase + 45) * deg2Rad)
  4561. DCPeriod = smoothPeriod + 0.5
  4562. DCPeriodInt = math.Floor(DCPeriod)
  4563. idx = today
  4564. tempReal = 0.0
  4565. for i := 0; i < int(DCPeriodInt); i++ {
  4566. tempReal += inReal[idx]
  4567. idx--
  4568. }
  4569. if DCPeriodInt > 0 {
  4570. tempReal = tempReal / (DCPeriodInt * 1.0)
  4571. }
  4572. trendline := (4.0*tempReal + 3.0*iTrend1 + 2.0*iTrend2 + iTrend3) / 10.0
  4573. iTrend3 = iTrend2
  4574. iTrend2 = iTrend1
  4575. iTrend1 = tempReal
  4576. trend := 1
  4577. if ((sine > leadSine) && (prevSine <= prevLeadSine)) || ((sine < leadSine) && (prevSine >= prevLeadSine)) {
  4578. daysInTrend = 0
  4579. trend = 0
  4580. }
  4581. daysInTrend++
  4582. if float64(daysInTrend) < (0.5 * smoothPeriod) {
  4583. trend = 0
  4584. }
  4585. tempReal = dcPhase - prevdcPhase
  4586. if (smoothPeriod != 0.0) && ((tempReal > (0.67 * 360.0 / smoothPeriod)) && (tempReal < (1.5 * 360.0 / smoothPeriod))) {
  4587. trend = 0
  4588. }
  4589. tempReal = smoothPrice[smoothPriceIdx]
  4590. if (trendline != 0.0) && (math.Abs((tempReal-trendline)/trendline) >= 0.015) {
  4591. trend = 1
  4592. }
  4593. if today >= startIdx {
  4594. outReal[outIdx] = float64(trend)
  4595. outIdx++
  4596. }
  4597. smoothPriceIdx++
  4598. if smoothPriceIdx > maxIdxSmoothPrice {
  4599. smoothPriceIdx = 0
  4600. }
  4601. today++
  4602. }
  4603. return outReal
  4604. }
  4605. /* Statistic Functions */
  4606. // Beta - Beta
  4607. func Beta(inReal0 []float64, inReal1 []float64, inTimePeriod int) []float64 {
  4608. outReal := make([]float64, len(inReal0))
  4609. x := 0.0
  4610. y := 0.0
  4611. sSS := 0.0
  4612. sXY := 0.0
  4613. sX := 0.0
  4614. sY := 0.0
  4615. tmpReal := 0.0
  4616. n := 0.0
  4617. nbInitialElementNeeded := inTimePeriod
  4618. startIdx := nbInitialElementNeeded
  4619. trailingIdx := startIdx - nbInitialElementNeeded
  4620. trailingLastPriceX := inReal0[trailingIdx]
  4621. lastPriceX := trailingLastPriceX
  4622. trailingLastPriceY := inReal1[trailingIdx]
  4623. lastPriceY := trailingLastPriceY
  4624. trailingIdx++
  4625. i := trailingIdx
  4626. for i < startIdx {
  4627. tmpReal := inReal0[i]
  4628. x := 0.0
  4629. if !((-0.00000000000001 < lastPriceX) && (lastPriceX < 0.00000000000001)) {
  4630. x = (tmpReal - lastPriceX) / lastPriceX
  4631. }
  4632. lastPriceX = tmpReal
  4633. tmpReal = inReal1[i]
  4634. i++
  4635. y := 0.0
  4636. if !((-0.00000000000001 < lastPriceY) && (lastPriceY < 0.00000000000001)) {
  4637. y = (tmpReal - lastPriceY) / lastPriceY
  4638. }
  4639. lastPriceY = tmpReal
  4640. sSS += x * x
  4641. sXY += x * y
  4642. sX += x
  4643. sY += y
  4644. }
  4645. outIdx := inTimePeriod
  4646. n = float64(inTimePeriod)
  4647. for ok := true; ok; {
  4648. tmpReal = inReal0[i]
  4649. if !((-0.00000000000001 < lastPriceX) && (lastPriceX < 0.00000000000001)) {
  4650. x = (tmpReal - lastPriceX) / lastPriceX
  4651. } else {
  4652. x = 0.0
  4653. }
  4654. lastPriceX = tmpReal
  4655. tmpReal = inReal1[i]
  4656. i++
  4657. if !((-0.00000000000001 < lastPriceY) && (lastPriceY < 0.00000000000001)) {
  4658. y = (tmpReal - lastPriceY) / lastPriceY
  4659. } else {
  4660. y = 0.0
  4661. }
  4662. lastPriceY = tmpReal
  4663. sSS += x * x
  4664. sXY += x * y
  4665. sX += x
  4666. sY += y
  4667. tmpReal = inReal0[trailingIdx]
  4668. if !(((-(0.00000000000001)) < trailingLastPriceX) && (trailingLastPriceX < (0.00000000000001))) {
  4669. x = (tmpReal - trailingLastPriceX) / trailingLastPriceX
  4670. } else {
  4671. x = 0.0
  4672. }
  4673. trailingLastPriceX = tmpReal
  4674. tmpReal = inReal1[trailingIdx]
  4675. trailingIdx++
  4676. if !(((-(0.00000000000001)) < trailingLastPriceY) && (trailingLastPriceY < (0.00000000000001))) {
  4677. y = (tmpReal - trailingLastPriceY) / trailingLastPriceY
  4678. } else {
  4679. y = 0.0
  4680. }
  4681. trailingLastPriceY = tmpReal
  4682. tmpReal = (n * sSS) - (sX * sX)
  4683. if !(((-(0.00000000000001)) < tmpReal) && (tmpReal < (0.00000000000001))) {
  4684. outReal[outIdx] = ((n * sXY) - (sX * sY)) / tmpReal
  4685. } else {
  4686. outReal[outIdx] = 0.0
  4687. }
  4688. outIdx++
  4689. sSS -= x * x
  4690. sXY -= x * y
  4691. sX -= x
  4692. sY -= y
  4693. ok = i < len(inReal0)
  4694. }
  4695. return outReal
  4696. }
  4697. // Correl - Pearson's Correlation Coefficient (r)
  4698. func Correl(inReal0 []float64, inReal1 []float64, inTimePeriod int) []float64 {
  4699. outReal := make([]float64, len(inReal0))
  4700. inTimePeriodF := float64(inTimePeriod)
  4701. lookbackTotal := inTimePeriod - 1
  4702. startIdx := lookbackTotal
  4703. trailingIdx := startIdx - lookbackTotal
  4704. sumXY, sumX, sumY, sumX2, sumY2 := 0.0, 0.0, 0.0, 0.0, 0.0
  4705. today := trailingIdx
  4706. for today = trailingIdx; today <= startIdx; today++ {
  4707. x := inReal0[today]
  4708. sumX += x
  4709. sumX2 += x * x
  4710. y := inReal1[today]
  4711. sumXY += x * y
  4712. sumY += y
  4713. sumY2 += y * y
  4714. }
  4715. trailingX := inReal0[trailingIdx]
  4716. trailingY := inReal1[trailingIdx]
  4717. trailingIdx++
  4718. tempReal := (sumX2 - ((sumX * sumX) / inTimePeriodF)) * (sumY2 - ((sumY * sumY) / inTimePeriodF))
  4719. if !(tempReal < 0.00000000000001) {
  4720. outReal[inTimePeriod-1] = (sumXY - ((sumX * sumY) / inTimePeriodF)) / math.Sqrt(tempReal)
  4721. } else {
  4722. outReal[inTimePeriod-1] = 0.0
  4723. }
  4724. outIdx := inTimePeriod
  4725. for today < len(inReal0) {
  4726. sumX -= trailingX
  4727. sumX2 -= trailingX * trailingX
  4728. sumXY -= trailingX * trailingY
  4729. sumY -= trailingY
  4730. sumY2 -= trailingY * trailingY
  4731. x := inReal0[today]
  4732. sumX += x
  4733. sumX2 += x * x
  4734. y := inReal1[today]
  4735. today++
  4736. sumXY += x * y
  4737. sumY += y
  4738. sumY2 += y * y
  4739. trailingX = inReal0[trailingIdx]
  4740. trailingY = inReal1[trailingIdx]
  4741. trailingIdx++
  4742. tempReal = (sumX2 - ((sumX * sumX) / inTimePeriodF)) * (sumY2 - ((sumY * sumY) / inTimePeriodF))
  4743. if !(tempReal < (0.00000000000001)) {
  4744. outReal[outIdx] = (sumXY - ((sumX * sumY) / inTimePeriodF)) / math.Sqrt(tempReal)
  4745. } else {
  4746. outReal[outIdx] = 0.0
  4747. }
  4748. outIdx++
  4749. }
  4750. return outReal
  4751. }
  4752. // LinearReg - Linear Regression
  4753. func LinearReg(inReal []float64, inTimePeriod int) []float64 {
  4754. outReal := make([]float64, len(inReal))
  4755. inTimePeriodF := float64(inTimePeriod)
  4756. lookbackTotal := inTimePeriod
  4757. startIdx := lookbackTotal
  4758. outIdx := startIdx - 1
  4759. today := startIdx - 1
  4760. sumX := inTimePeriodF * (inTimePeriodF - 1) * 0.5
  4761. sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
  4762. divisor := sumX*sumX - inTimePeriodF*sumXSqr
  4763. //initialize values of sumY and sumXY over first (inTimePeriod) input values
  4764. sumXY := 0.0
  4765. sumY := 0.0
  4766. i := inTimePeriod
  4767. for i != 0 {
  4768. i--
  4769. tempValue1 := inReal[today-i]
  4770. sumY += tempValue1
  4771. sumXY += float64(i) * tempValue1
  4772. }
  4773. for today < len(inReal) {
  4774. //sumX and sumXY are already available for first output value
  4775. if today > startIdx-1 {
  4776. tempValue2 := inReal[today-inTimePeriod]
  4777. sumXY += sumY - inTimePeriodF*tempValue2
  4778. sumY += inReal[today] - tempValue2
  4779. }
  4780. m := (inTimePeriodF*sumXY - sumX*sumY) / divisor
  4781. b := (sumY - m*sumX) / inTimePeriodF
  4782. outReal[outIdx] = b + m*(inTimePeriodF-1)
  4783. outIdx++
  4784. today++
  4785. }
  4786. return outReal
  4787. }
  4788. // LinearRegAngle - Linear Regression Angle
  4789. func LinearRegAngle(inReal []float64, inTimePeriod int) []float64 {
  4790. outReal := make([]float64, len(inReal))
  4791. inTimePeriodF := float64(inTimePeriod)
  4792. lookbackTotal := inTimePeriod
  4793. startIdx := lookbackTotal
  4794. outIdx := startIdx - 1
  4795. today := startIdx - 1
  4796. sumX := inTimePeriodF * (inTimePeriodF - 1) * 0.5
  4797. sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
  4798. divisor := sumX*sumX - inTimePeriodF*sumXSqr
  4799. //initialize values of sumY and sumXY over first (inTimePeriod) input values
  4800. sumXY := 0.0
  4801. sumY := 0.0
  4802. i := inTimePeriod
  4803. for i != 0 {
  4804. i--
  4805. tempValue1 := inReal[today-i]
  4806. sumY += tempValue1
  4807. sumXY += float64(i) * tempValue1
  4808. }
  4809. for today < len(inReal) {
  4810. //sumX and sumXY are already available for first output value
  4811. if today > startIdx-1 {
  4812. tempValue2 := inReal[today-inTimePeriod]
  4813. sumXY += sumY - inTimePeriodF*tempValue2
  4814. sumY += inReal[today] - tempValue2
  4815. }
  4816. m := (inTimePeriodF*sumXY - sumX*sumY) / divisor
  4817. outReal[outIdx] = math.Atan(m) * (180.0 / math.Pi)
  4818. outIdx++
  4819. today++
  4820. }
  4821. return outReal
  4822. }
  4823. // LinearRegIntercept - Linear Regression Intercept
  4824. func LinearRegIntercept(inReal []float64, inTimePeriod int) []float64 {
  4825. outReal := make([]float64, len(inReal))
  4826. inTimePeriodF := float64(inTimePeriod)
  4827. lookbackTotal := inTimePeriod
  4828. startIdx := lookbackTotal
  4829. outIdx := startIdx - 1
  4830. today := startIdx - 1
  4831. sumX := inTimePeriodF * (inTimePeriodF - 1) * 0.5
  4832. sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
  4833. divisor := sumX*sumX - inTimePeriodF*sumXSqr
  4834. //initialize values of sumY and sumXY over first (inTimePeriod) input values
  4835. sumXY := 0.0
  4836. sumY := 0.0
  4837. i := inTimePeriod
  4838. for i != 0 {
  4839. i--
  4840. tempValue1 := inReal[today-i]
  4841. sumY += tempValue1
  4842. sumXY += float64(i) * tempValue1
  4843. }
  4844. for today < len(inReal) {
  4845. //sumX and sumXY are already available for first output value
  4846. if today > startIdx-1 {
  4847. tempValue2 := inReal[today-inTimePeriod]
  4848. sumXY += sumY - inTimePeriodF*tempValue2
  4849. sumY += inReal[today] - tempValue2
  4850. }
  4851. m := (inTimePeriodF*sumXY - sumX*sumY) / divisor
  4852. outReal[outIdx] = (sumY - m*sumX) / inTimePeriodF
  4853. outIdx++
  4854. today++
  4855. }
  4856. return outReal
  4857. }
  4858. // LinearRegSlope - Linear Regression Slope
  4859. func LinearRegSlope(inReal []float64, inTimePeriod int) []float64 {
  4860. outReal := make([]float64, len(inReal))
  4861. inTimePeriodF := float64(inTimePeriod)
  4862. lookbackTotal := inTimePeriod
  4863. startIdx := lookbackTotal
  4864. outIdx := startIdx - 1
  4865. today := startIdx - 1
  4866. sumX := inTimePeriodF * (inTimePeriodF - 1) * 0.5
  4867. sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
  4868. divisor := sumX*sumX - inTimePeriodF*sumXSqr
  4869. //initialize values of sumY and sumXY over first (inTimePeriod) input values
  4870. sumXY := 0.0
  4871. sumY := 0.0
  4872. i := inTimePeriod
  4873. for i != 0 {
  4874. i--
  4875. tempValue1 := inReal[today-i]
  4876. sumY += tempValue1
  4877. sumXY += float64(i) * tempValue1
  4878. }
  4879. for today < len(inReal) {
  4880. //sumX and sumXY are already available for first output value
  4881. if today > startIdx-1 {
  4882. tempValue2 := inReal[today-inTimePeriod]
  4883. sumXY += sumY - inTimePeriodF*tempValue2
  4884. sumY += inReal[today] - tempValue2
  4885. }
  4886. outReal[outIdx] = (inTimePeriodF*sumXY - sumX*sumY) / divisor
  4887. outIdx++
  4888. today++
  4889. }
  4890. return outReal
  4891. }
  4892. // StdDev - Standard Deviation
  4893. func StdDev(inReal []float64, inTimePeriod int, inNbDev float64) []float64 {
  4894. outReal := Var(inReal, inTimePeriod)
  4895. if inNbDev != 1.0 {
  4896. for i := 0; i < len(inReal); i++ {
  4897. tempReal := outReal[i]
  4898. if !(tempReal < 0.00000000000001) {
  4899. outReal[i] = math.Sqrt(tempReal) * inNbDev
  4900. } else {
  4901. outReal[i] = 0.0
  4902. }
  4903. }
  4904. } else {
  4905. for i := 0; i < len(inReal); i++ {
  4906. tempReal := outReal[i]
  4907. if !(tempReal < 0.00000000000001) {
  4908. outReal[i] = math.Sqrt(tempReal)
  4909. } else {
  4910. outReal[i] = 0.0
  4911. }
  4912. }
  4913. }
  4914. return outReal
  4915. }
  4916. // Tsf - Time Series Forecast
  4917. func Tsf(inReal []float64, inTimePeriod int) []float64 {
  4918. outReal := make([]float64, len(inReal))
  4919. inTimePeriodF := float64(inTimePeriod)
  4920. lookbackTotal := inTimePeriod
  4921. startIdx := lookbackTotal
  4922. outIdx := startIdx - 1
  4923. today := startIdx - 1
  4924. sumX := inTimePeriodF * (inTimePeriodF - 1.0) * 0.5
  4925. sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
  4926. divisor := sumX*sumX - inTimePeriodF*sumXSqr
  4927. //initialize values of sumY and sumXY over first (inTimePeriod) input values
  4928. sumXY := 0.0
  4929. sumY := 0.0
  4930. i := inTimePeriod
  4931. for i != 0 {
  4932. i--
  4933. tempValue1 := inReal[today-i]
  4934. sumY += tempValue1
  4935. sumXY += float64(i) * tempValue1
  4936. }
  4937. for today < len(inReal) {
  4938. //sumX and sumXY are already available for first output value
  4939. if today > startIdx-1 {
  4940. tempValue2 := inReal[today-inTimePeriod]
  4941. sumXY += sumY - inTimePeriodF*tempValue2
  4942. sumY += inReal[today] - tempValue2
  4943. }
  4944. m := (inTimePeriodF*sumXY - sumX*sumY) / divisor
  4945. b := (sumY - m*sumX) / inTimePeriodF
  4946. outReal[outIdx] = b + m*inTimePeriodF
  4947. today++
  4948. outIdx++
  4949. }
  4950. return outReal
  4951. }
  4952. // Var - Variance
  4953. func Var(inReal []float64, inTimePeriod int) []float64 {
  4954. outReal := make([]float64, len(inReal))
  4955. nbInitialElementNeeded := inTimePeriod - 1
  4956. startIdx := nbInitialElementNeeded
  4957. periodTotal1 := 0.0
  4958. periodTotal2 := 0.0
  4959. trailingIdx := startIdx - nbInitialElementNeeded
  4960. i := trailingIdx
  4961. if inTimePeriod > 1 {
  4962. for i < startIdx {
  4963. tempReal := inReal[i]
  4964. periodTotal1 += tempReal
  4965. tempReal *= tempReal
  4966. periodTotal2 += tempReal
  4967. i++
  4968. }
  4969. }
  4970. outIdx := startIdx
  4971. for ok := true; ok; {
  4972. tempReal := inReal[i]
  4973. periodTotal1 += tempReal
  4974. tempReal *= tempReal
  4975. periodTotal2 += tempReal
  4976. meanValue1 := periodTotal1 / float64(inTimePeriod)
  4977. meanValue2 := periodTotal2 / float64(inTimePeriod)
  4978. tempReal = inReal[trailingIdx]
  4979. periodTotal1 -= tempReal
  4980. tempReal *= tempReal
  4981. periodTotal2 -= tempReal
  4982. outReal[outIdx] = meanValue2 - meanValue1*meanValue1
  4983. i++
  4984. trailingIdx++
  4985. outIdx++
  4986. ok = i < len(inReal)
  4987. }
  4988. return outReal
  4989. }
  4990. /* Math Transform Functions */
  4991. // Acos - Vector Trigonometric ACOS
  4992. func Acos(inReal []float64) []float64 {
  4993. outReal := make([]float64, len(inReal))
  4994. for i := 0; i < len(inReal); i++ {
  4995. outReal[i] = math.Acos(inReal[i])
  4996. }
  4997. return outReal
  4998. }
  4999. // Asin - Vector Trigonometric ASIN
  5000. func Asin(inReal []float64) []float64 {
  5001. outReal := make([]float64, len(inReal))
  5002. for i := 0; i < len(inReal); i++ {
  5003. outReal[i] = math.Asin(inReal[i])
  5004. }
  5005. return outReal
  5006. }
  5007. // Atan - Vector Trigonometric ATAN
  5008. func Atan(inReal []float64) []float64 {
  5009. outReal := make([]float64, len(inReal))
  5010. for i := 0; i < len(inReal); i++ {
  5011. outReal[i] = math.Atan(inReal[i])
  5012. }
  5013. return outReal
  5014. }
  5015. // Ceil - Vector CEIL
  5016. func Ceil(inReal []float64) []float64 {
  5017. outReal := make([]float64, len(inReal))
  5018. for i := 0; i < len(inReal); i++ {
  5019. outReal[i] = math.Ceil(inReal[i])
  5020. }
  5021. return outReal
  5022. }
  5023. // Cos - Vector Trigonometric COS
  5024. func Cos(inReal []float64) []float64 {
  5025. outReal := make([]float64, len(inReal))
  5026. for i := 0; i < len(inReal); i++ {
  5027. outReal[i] = math.Cos(inReal[i])
  5028. }
  5029. return outReal
  5030. }
  5031. // Cosh - Vector Trigonometric COSH
  5032. func Cosh(inReal []float64) []float64 {
  5033. outReal := make([]float64, len(inReal))
  5034. for i := 0; i < len(inReal); i++ {
  5035. outReal[i] = math.Cosh(inReal[i])
  5036. }
  5037. return outReal
  5038. }
  5039. // Exp - Vector atrithmetic EXP
  5040. func Exp(inReal []float64) []float64 {
  5041. outReal := make([]float64, len(inReal))
  5042. for i := 0; i < len(inReal); i++ {
  5043. outReal[i] = math.Exp(inReal[i])
  5044. }
  5045. return outReal
  5046. }
  5047. // Floor - Vector FLOOR
  5048. func Floor(inReal []float64) []float64 {
  5049. outReal := make([]float64, len(inReal))
  5050. for i := 0; i < len(inReal); i++ {
  5051. outReal[i] = math.Floor(inReal[i])
  5052. }
  5053. return outReal
  5054. }
  5055. // Ln - Vector natural log LN
  5056. func Ln(inReal []float64) []float64 {
  5057. outReal := make([]float64, len(inReal))
  5058. for i := 0; i < len(inReal); i++ {
  5059. outReal[i] = math.Log(inReal[i])
  5060. }
  5061. return outReal
  5062. }
  5063. // Log10 - Vector LOG10
  5064. func Log10(inReal []float64) []float64 {
  5065. outReal := make([]float64, len(inReal))
  5066. for i := 0; i < len(inReal); i++ {
  5067. outReal[i] = math.Log10(inReal[i])
  5068. }
  5069. return outReal
  5070. }
  5071. // Sin - Vector Trigonometric SIN
  5072. func Sin(inReal []float64) []float64 {
  5073. outReal := make([]float64, len(inReal))
  5074. for i := 0; i < len(inReal); i++ {
  5075. outReal[i] = math.Sin(inReal[i])
  5076. }
  5077. return outReal
  5078. }
  5079. // Sinh - Vector Trigonometric SINH
  5080. func Sinh(inReal []float64) []float64 {
  5081. outReal := make([]float64, len(inReal))
  5082. for i := 0; i < len(inReal); i++ {
  5083. outReal[i] = math.Sinh(inReal[i])
  5084. }
  5085. return outReal
  5086. }
  5087. // Sqrt - Vector SQRT
  5088. func Sqrt(inReal []float64) []float64 {
  5089. outReal := make([]float64, len(inReal))
  5090. for i := 0; i < len(inReal); i++ {
  5091. outReal[i] = math.Sqrt(inReal[i])
  5092. }
  5093. return outReal
  5094. }
  5095. // Tan - Vector Trigonometric TAN
  5096. func Tan(inReal []float64) []float64 {
  5097. outReal := make([]float64, len(inReal))
  5098. for i := 0; i < len(inReal); i++ {
  5099. outReal[i] = math.Tan(inReal[i])
  5100. }
  5101. return outReal
  5102. }
  5103. // Tanh - Vector Trigonometric TANH
  5104. func Tanh(inReal []float64) []float64 {
  5105. outReal := make([]float64, len(inReal))
  5106. for i := 0; i < len(inReal); i++ {
  5107. outReal[i] = math.Tanh(inReal[i])
  5108. }
  5109. return outReal
  5110. }
  5111. /* Math Operator Functions */
  5112. // Add - Vector arithmetic addition
  5113. func Add(inReal0 []float64, inReal1 []float64) []float64 {
  5114. outReal := make([]float64, len(inReal0))
  5115. for i := 0; i < len(inReal0); i++ {
  5116. outReal[i] = inReal0[i] + inReal1[i]
  5117. }
  5118. return outReal
  5119. }
  5120. // Div - Vector arithmetic division
  5121. func Div(inReal0 []float64, inReal1 []float64) []float64 {
  5122. outReal := make([]float64, len(inReal0))
  5123. for i := 0; i < len(inReal0); i++ {
  5124. outReal[i] = inReal0[i] / inReal1[i]
  5125. }
  5126. return outReal
  5127. }
  5128. // Max - Highest value over a period
  5129. func Max(inReal []float64, inTimePeriod int) []float64 {
  5130. outReal := make([]float64, len(inReal))
  5131. if inTimePeriod < 2 {
  5132. return outReal
  5133. }
  5134. nbInitialElementNeeded := inTimePeriod - 1
  5135. startIdx := nbInitialElementNeeded
  5136. outIdx := startIdx
  5137. today := startIdx
  5138. trailingIdx := startIdx - nbInitialElementNeeded
  5139. highestIdx := -1
  5140. highest := 0.0
  5141. for today < len(outReal) {
  5142. tmp := inReal[today]
  5143. if highestIdx < trailingIdx {
  5144. highestIdx = trailingIdx
  5145. highest = inReal[highestIdx]
  5146. i := highestIdx + 1
  5147. for i <= today {
  5148. tmp = inReal[i]
  5149. if tmp > highest {
  5150. highestIdx = i
  5151. highest = tmp
  5152. }
  5153. i++
  5154. }
  5155. } else if tmp >= highest {
  5156. highestIdx = today
  5157. highest = tmp
  5158. }
  5159. outReal[outIdx] = highest
  5160. outIdx++
  5161. trailingIdx++
  5162. today++
  5163. }
  5164. return outReal
  5165. }
  5166. // MaxIndex - Index of highest value over a specified period
  5167. func MaxIndex(inReal []float64, inTimePeriod int) []float64 {
  5168. outReal := make([]float64, len(inReal))
  5169. if inTimePeriod < 2 {
  5170. return outReal
  5171. }
  5172. nbInitialElementNeeded := inTimePeriod - 1
  5173. startIdx := nbInitialElementNeeded
  5174. outIdx := startIdx
  5175. today := startIdx
  5176. trailingIdx := startIdx - nbInitialElementNeeded
  5177. highestIdx := -1
  5178. highest := 0.0
  5179. for today < len(inReal) {
  5180. tmp := inReal[today]
  5181. if highestIdx < trailingIdx {
  5182. highestIdx = trailingIdx
  5183. highest = inReal[highestIdx]
  5184. i := highestIdx + 1
  5185. for i <= today {
  5186. tmp := inReal[i]
  5187. if tmp > highest {
  5188. highestIdx = i
  5189. highest = tmp
  5190. }
  5191. i++
  5192. }
  5193. } else if tmp >= highest {
  5194. highestIdx = today
  5195. highest = tmp
  5196. }
  5197. outReal[outIdx] = float64(highestIdx)
  5198. outIdx++
  5199. trailingIdx++
  5200. today++
  5201. }
  5202. return outReal
  5203. }
  5204. // Min - Lowest value over a period
  5205. func Min(inReal []float64, inTimePeriod int) []float64 {
  5206. outReal := make([]float64, len(inReal))
  5207. if inTimePeriod < 2 {
  5208. return outReal
  5209. }
  5210. nbInitialElementNeeded := inTimePeriod - 1
  5211. startIdx := nbInitialElementNeeded
  5212. outIdx := startIdx
  5213. today := startIdx
  5214. trailingIdx := startIdx - nbInitialElementNeeded
  5215. lowestIdx := -1
  5216. lowest := 0.0
  5217. for today < len(outReal) {
  5218. tmp := inReal[today]
  5219. if lowestIdx < trailingIdx {
  5220. lowestIdx = trailingIdx
  5221. lowest = inReal[lowestIdx]
  5222. i := lowestIdx + 1
  5223. for i <= today {
  5224. tmp = inReal[i]
  5225. if tmp < lowest {
  5226. lowestIdx = i
  5227. lowest = tmp
  5228. }
  5229. i++
  5230. }
  5231. } else if tmp <= lowest {
  5232. lowestIdx = today
  5233. lowest = tmp
  5234. }
  5235. outReal[outIdx] = lowest
  5236. outIdx++
  5237. trailingIdx++
  5238. today++
  5239. }
  5240. return outReal
  5241. }
  5242. // MinIndex - Index of lowest value over a specified period
  5243. func MinIndex(inReal []float64, inTimePeriod int) []float64 {
  5244. outReal := make([]float64, len(inReal))
  5245. if inTimePeriod < 2 {
  5246. return outReal
  5247. }
  5248. nbInitialElementNeeded := inTimePeriod - 1
  5249. startIdx := nbInitialElementNeeded
  5250. outIdx := startIdx
  5251. today := startIdx
  5252. trailingIdx := startIdx - nbInitialElementNeeded
  5253. lowestIdx := -1
  5254. lowest := 0.0
  5255. for today < len(inReal) {
  5256. tmp := inReal[today]
  5257. if lowestIdx < trailingIdx {
  5258. lowestIdx = trailingIdx
  5259. lowest = inReal[lowestIdx]
  5260. i := lowestIdx + 1
  5261. for i <= today {
  5262. tmp = inReal[i]
  5263. if tmp < lowest {
  5264. lowestIdx = i
  5265. lowest = tmp
  5266. }
  5267. i++
  5268. }
  5269. } else if tmp <= lowest {
  5270. lowestIdx = today
  5271. lowest = tmp
  5272. }
  5273. outReal[outIdx] = float64(lowestIdx)
  5274. outIdx++
  5275. trailingIdx++
  5276. today++
  5277. }
  5278. return outReal
  5279. }
  5280. // MinMax - Lowest and highest values over a specified period
  5281. func MinMax(inReal []float64, inTimePeriod int) ([]float64, []float64) {
  5282. outMin := make([]float64, len(inReal))
  5283. outMax := make([]float64, len(inReal))
  5284. nbInitialElementNeeded := (inTimePeriod - 1)
  5285. startIdx := nbInitialElementNeeded
  5286. outIdx := startIdx
  5287. today := startIdx
  5288. trailingIdx := startIdx - nbInitialElementNeeded
  5289. highestIdx := -1
  5290. highest := 0.0
  5291. lowestIdx := -1
  5292. lowest := 0.0
  5293. for today < len(inReal) {
  5294. tmpLow, tmpHigh := inReal[today], inReal[today]
  5295. if highestIdx < trailingIdx {
  5296. highestIdx = trailingIdx
  5297. highest = inReal[highestIdx]
  5298. i := highestIdx
  5299. i++
  5300. for i <= today {
  5301. tmpHigh = inReal[i]
  5302. if tmpHigh > highest {
  5303. highestIdx = i
  5304. highest = tmpHigh
  5305. }
  5306. i++
  5307. }
  5308. } else if tmpHigh >= highest {
  5309. highestIdx = today
  5310. highest = tmpHigh
  5311. }
  5312. if lowestIdx < trailingIdx {
  5313. lowestIdx = trailingIdx
  5314. lowest = inReal[lowestIdx]
  5315. i := lowestIdx
  5316. i++
  5317. for i <= today {
  5318. tmpLow = inReal[i]
  5319. if tmpLow < lowest {
  5320. lowestIdx = i
  5321. lowest = tmpLow
  5322. }
  5323. i++
  5324. }
  5325. } else if tmpLow <= lowest {
  5326. lowestIdx = today
  5327. lowest = tmpLow
  5328. }
  5329. outMax[outIdx] = highest
  5330. outMin[outIdx] = lowest
  5331. outIdx++
  5332. trailingIdx++
  5333. today++
  5334. }
  5335. return outMin, outMax
  5336. }
  5337. // MinMaxIndex - Indexes of lowest and highest values over a specified period
  5338. func MinMaxIndex(inReal []float64, inTimePeriod int) ([]float64, []float64) {
  5339. outMinIdx := make([]float64, len(inReal))
  5340. outMaxIdx := make([]float64, len(inReal))
  5341. nbInitialElementNeeded := (inTimePeriod - 1)
  5342. startIdx := nbInitialElementNeeded
  5343. outIdx := startIdx
  5344. today := startIdx
  5345. trailingIdx := startIdx - nbInitialElementNeeded
  5346. highestIdx := -1
  5347. highest := 0.0
  5348. lowestIdx := -1
  5349. lowest := 0.0
  5350. for today < len(inReal) {
  5351. tmpLow, tmpHigh := inReal[today], inReal[today]
  5352. if highestIdx < trailingIdx {
  5353. highestIdx = trailingIdx
  5354. highest = inReal[highestIdx]
  5355. i := highestIdx
  5356. i++
  5357. for i <= today {
  5358. tmpHigh = inReal[i]
  5359. if tmpHigh > highest {
  5360. highestIdx = i
  5361. highest = tmpHigh
  5362. }
  5363. i++
  5364. }
  5365. } else if tmpHigh >= highest {
  5366. highestIdx = today
  5367. highest = tmpHigh
  5368. }
  5369. if lowestIdx < trailingIdx {
  5370. lowestIdx = trailingIdx
  5371. lowest = inReal[lowestIdx]
  5372. i := lowestIdx
  5373. i++
  5374. for i <= today {
  5375. tmpLow = inReal[i]
  5376. if tmpLow < lowest {
  5377. lowestIdx = i
  5378. lowest = tmpLow
  5379. }
  5380. i++
  5381. }
  5382. } else if tmpLow <= lowest {
  5383. lowestIdx = today
  5384. lowest = tmpLow
  5385. }
  5386. outMaxIdx[outIdx] = float64(highestIdx)
  5387. outMinIdx[outIdx] = float64(lowestIdx)
  5388. outIdx++
  5389. trailingIdx++
  5390. today++
  5391. }
  5392. return outMinIdx, outMaxIdx
  5393. }
  5394. // Mult - Vector arithmetic multiply
  5395. func Mult(inReal0 []float64, inReal1 []float64) []float64 {
  5396. outReal := make([]float64, len(inReal0))
  5397. for i := 0; i < len(inReal0); i++ {
  5398. outReal[i] = inReal0[i] * inReal1[i]
  5399. }
  5400. return outReal
  5401. }
  5402. // Sub - Vector arithmetic subtraction
  5403. func Sub(inReal0 []float64, inReal1 []float64) []float64 {
  5404. outReal := make([]float64, len(inReal0))
  5405. for i := 0; i < len(inReal0); i++ {
  5406. outReal[i] = inReal0[i] - inReal1[i]
  5407. }
  5408. return outReal
  5409. }
  5410. // Sum - Vector summation
  5411. func Sum(inReal []float64, inTimePeriod int) []float64 {
  5412. outReal := make([]float64, len(inReal))
  5413. lookbackTotal := inTimePeriod - 1
  5414. startIdx := lookbackTotal
  5415. periodTotal := 0.0
  5416. trailingIdx := startIdx - lookbackTotal
  5417. i := trailingIdx
  5418. if inTimePeriod > 1 {
  5419. for i < startIdx {
  5420. periodTotal += inReal[i]
  5421. i++
  5422. }
  5423. }
  5424. outIdx := startIdx
  5425. for i < len(inReal) {
  5426. periodTotal += inReal[i]
  5427. tempReal := periodTotal
  5428. periodTotal -= inReal[trailingIdx]
  5429. outReal[outIdx] = tempReal
  5430. i++
  5431. trailingIdx++
  5432. outIdx++
  5433. }
  5434. return outReal
  5435. }
  5436. // HeikinashiCandles - from candle values extracts heikinashi candle values.
  5437. //
  5438. // Returns highs, opens, closes and lows of the heikinashi candles (in this order).
  5439. //
  5440. // NOTE: The number of Heikin-Ashi candles will always be one less than the number of provided candles, due to the fact
  5441. // that a previous candle is necessary to calculate the Heikin-Ashi candle, therefore the first provided candle is not considered
  5442. // as "current candle" in the algorithm, but only as "previous candle".
  5443. func HeikinashiCandles(highs []float64, opens []float64, closes []float64, lows []float64) ([]float64, []float64, []float64, []float64) {
  5444. N := len(highs)
  5445. heikinHighs := make([]float64, N)
  5446. heikinOpens := make([]float64, N)
  5447. heikinCloses := make([]float64, N)
  5448. heikinLows := make([]float64, N)
  5449. for currentCandle := 1; currentCandle < N; currentCandle++ {
  5450. previousCandle := currentCandle - 1
  5451. heikinHighs[currentCandle] = math.Max(highs[currentCandle], math.Max(opens[currentCandle], closes[currentCandle]))
  5452. heikinOpens[currentCandle] = (opens[previousCandle] + closes[previousCandle]) / 2
  5453. heikinCloses[currentCandle] = (highs[currentCandle] + opens[currentCandle] + closes[currentCandle] + lows[currentCandle]) / 4
  5454. heikinLows[currentCandle] = math.Min(highs[currentCandle], math.Min(opens[currentCandle], closes[currentCandle]))
  5455. }
  5456. return heikinHighs, heikinOpens, heikinCloses, heikinLows
  5457. }
  5458. // Hlc3 returns the Hlc3 values
  5459. //
  5460. // NOTE: Every Hlc item is defined as follows : (high + low + close) / 3
  5461. // It is used as AvgPrice candle.
  5462. func Hlc3(highs []float64, lows []float64, closes []float64) []float64 {
  5463. N := len(highs)
  5464. result := make([]float64, N)
  5465. for i := range highs {
  5466. result[i] = (highs[i] + lows[i] + closes[i]) / 3
  5467. }
  5468. return result
  5469. }
  5470. // Crossover returns true if series1 is crossing over series2.
  5471. //
  5472. // NOTE: Usually this is used with Media Average Series to check if it crosses for buy signals.
  5473. // It assumes first values are the most recent.
  5474. // The crossover function does not use most recent value, since usually it's not a complete candle.
  5475. // The second recent values and the previous are used, instead.
  5476. func Crossover(series1 []float64, series2 []float64) bool {
  5477. if len(series1) < 3 || len(series2) < 3 {
  5478. return false
  5479. }
  5480. N := len(series1)
  5481. return series1[N-2] <= series2[N-2] && series1[N-1] > series2[N-1]
  5482. }
  5483. // Crossunder returns true if series1 is crossing under series2.
  5484. //
  5485. // NOTE: Usually this is used with Media Average Series to check if it crosses for sell signals.
  5486. func Crossunder(series1 []float64, series2 []float64) bool {
  5487. if len(series1) < 3 || len(series2) < 3 {
  5488. return false
  5489. }
  5490. N := len(series1)
  5491. return series1[N-1] <= series2[N-1] && series1[N-2] > series2[N-2]
  5492. }
  5493. // GroupCandles groups a set of candles in another set of candles, basing on a grouping factor.
  5494. //
  5495. // This is pretty useful if you want to transform, for example, 15min candles into 1h candles using same data.
  5496. //
  5497. // This avoid calling multiple times the exchange for multiple contexts.
  5498. //
  5499. // Example:
  5500. //
  5501. // To transform 15 minute candles in 30 minutes candles you have a grouping factor = 2
  5502. //
  5503. // To transform 15 minute candles in 1 hour candles you have a grouping factor = 4
  5504. //
  5505. // To transform 30 minute candles in 1 hour candles you have a grouping factor = 2
  5506. func GroupCandles(highs []float64, opens []float64, closes []float64, lows []float64, groupingFactor int) ([]float64, []float64, []float64, []float64, error) {
  5507. N := len(highs)
  5508. if groupingFactor == 0 {
  5509. return nil, nil, nil, nil, errors.New("Grouping factor must be > 0")
  5510. } else if groupingFactor == 1 {
  5511. return highs, opens, closes, lows, nil // no need to group in this case, return the parameters.
  5512. }
  5513. if N%groupingFactor > 0 {
  5514. return nil, nil, nil, nil, errors.New("Cannot group properly, need a groupingFactor which is a factor of the number of candles")
  5515. }
  5516. groupedN := N / groupingFactor
  5517. groupedHighs := make([]float64, groupedN)
  5518. groupedOpens := make([]float64, groupedN)
  5519. groupedCloses := make([]float64, groupedN)
  5520. groupedLows := make([]float64, groupedN)
  5521. lastOfCurrentGroup := groupingFactor - 1
  5522. k := 0
  5523. for i := 0; i < N; i += groupingFactor { // scan all param candles
  5524. groupedOpens[k] = opens[i]
  5525. groupedCloses[k] = closes[i+lastOfCurrentGroup]
  5526. groupedHighs[k] = highs[i]
  5527. groupedLows[k] = lows[i]
  5528. endOfCurrentGroup := i + lastOfCurrentGroup
  5529. for j := i + 1; j <= endOfCurrentGroup; j++ { // group high lows candles here
  5530. if lows[j] < groupedLows[k] {
  5531. groupedLows[k] = lows[j]
  5532. }
  5533. if highs[j] > groupedHighs[k] {
  5534. groupedHighs[k] = highs[j]
  5535. }
  5536. }
  5537. k++
  5538. }
  5539. return groupedHighs, groupedOpens, groupedCloses, groupedLows, nil
  5540. }