| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561 |
- //
- // ChartView.m
- // ChartView
- //
- // Created by Simon Zhou on 14-6-11.
- // Copyright (c) 2014年 muchinfo. All rights reserved.
- //
- #import "ChartView.h"
- #import "ChartData.h"
- #import "ChartCalculateUtils.h"
- #define TAG_BUTTON_MACD 1000
- #define TAG_BUTTON_KDJ 1001
- #define TAG_BUTTON_RSI 1002
- @implementation ChartView {
- /// X轴相关
- /// X轴宽度,通过视图宽度-价格标签宽度-边框Padding计算得出
- CGFloat _xAxisWidth;
- /// X轴左边距,即价格标签宽度
- CGFloat _xAxisPaddingLeft;
- /// X轴右边距,默认为5.0f(因为要显示最后一个时间标签)
- CGFloat _xAxisPaddingRight;
- CGFloat _excessXAxisWidth;
-
- /// Y轴相关
- /// Y轴高度,通过视图高度-边框Padding计算得出
- CGFloat _yAxisHeight;
- /// 当前可视Y轴最大值
- CGFloat _yAxisMaxValue;
- /// 当前可视Y轴最小值
- CGFloat _yAxisMinValue;
-
- /// K起点
- /// 坐标原点
- CGPoint _kLineOrigin;
-
- /// K线相关
- /// K线形状最小宽度
- CGFloat _kLineMinWidth;
- /// K线形状最大宽度
- CGFloat _kLineMaxWidth;
- /// K线形状之间的间隔,默认为1.0f
- CGFloat _kLinePadding;
- /// K线形状宽度,默认为5.0f
- CGFloat _kLineWidth;
- /// 可显示K线数量,由_xAxisWidth/_kLineWidth 计算得出
- NSInteger _kLineCount;
- /// 当前可视K线数据起始下标
- NSInteger _kLineStartIndex;
- /// 当前可视K线数据
- NSInteger _kLineEndIndex;
-
- /// 十字线相关
- /// 是否显示十字线
- BOOL _isShowTipLine;
- /// 十字线当前K线下标
- NSInteger _tipLineIndex;
- /// 十字线Y轴坐标
- CGFloat _tipLineYAxis;
-
- /// MACD相关
- /// 指标框下边距
- CGFloat _indicatorPaddingBottom;
- /// 指标原点
- CGPoint _indicatorOrigin;
- /// MACD可视指标最大值
- CGFloat _indicatorMaxValue;
- /// MACD可视指标最小值
- CGFloat _indicatorMinValue;
-
- /// VOL相关
- /// VOL可视指标最大值
- CGFloat _indicatorVOLMaxValue;
- /// VOL可视指标最小值
- CGFloat _indicatorVOLMiniValue;
-
- /// KDJ相关
- /// KDJ可视指标最大值
- CGFloat _indicatorKDJMaxValue;
- /// KDJ可视指标最小值
- CGFloat _indicatorKDJMiniValue;
-
- /// RSI相关
- /// RSI可视指标最大值
- CGFloat _indicatorRSIMaxValue;
- /// RSI可视指标最小值
- CGFloat _indicatorRSIMiniValue;
-
- /// CCI相关
- /// CCI可视指标最大值
- CGFloat _indicatorCCIMaxValue;
- /// CCI可视指标最小值
- CGFloat _indicatorCCIMiniValue;
-
- /// DMA相关
- /// DMA可视指标最大值
- CGFloat _indicatorDMAMaxValue;
- /// DMA可视指标最小值
- CGFloat _indicatorDMAMiniValue;
-
- /// BIAS相关
- /// BIAS可视指标最大值
- CGFloat _indicatorBIASMaxValue;
- /// BIAS可视指标最小值
- CGFloat _indicatorBIASMiniValue;
-
- /// PSY相关
- /// PSY可视指标最大值
- CGFloat _indicatorPSYMaxValue;
- /// PSY可视指标最小值
- CGFloat _indicatorPSYMiniValue;
-
- /// CR相关
- /// CR可视指标最大值
- CGFloat _indicatorCRMaxValue;
- /// CR可视指标最小值
- CGFloat _indicatorCRMiniValue;
-
- /// 交互相关
- CGPoint _startTouchPosition;
- CGFloat _startScale;
-
- /// 分时图相关
- /// 分时图最早数据开始X轴(因有时开盘时间与第一口价格有时间差)
- CGFloat _tsStartXPonit;
-
- /// 现价相关
- /// 行情现价
- NSDecimalNumber *_price;
- /// 现价报价时间
- NSDate *_priceTime;
-
- /// FIXME: 临时变量
- BOOL _added;
- }
- #pragma mark - 重载方法
- - (void)layoutSubviews {
- // NSLog(@"%s",__func__);
- }
- - (void)drawRect:(CGRect)rect {
- if (!_chartDataArray) {
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetRGBFillColor(context, _bgRed, _bgGreen, _bgBlue, 1.0f);
- CGContextFillRect(context, self.bounds);
-
- return;
- }
- /// 更新数据的方法
- [self updateData];
- /// 画框图表架
- [self drawBorder];
- /// 画图表X轴
- [self drawXAxis];
- /// 画图表Y轴
- [self drawYAxis];
-
- if (_chartViewType == ChartViewTypeKL) {
- if (_isBBGoods) {
- /// K线
- [self drawBBTSPlanLine];
- /// 画平均线
- [self drawBBAverageLine];
- } else {
- /// K线
- [self drawKLine];
- /// 画平均线
- [self drawAverageLine];
- if (_isShowIndicator) { /// 需要显示指标
- switch (_chartTargetType) {
- case MACD: { /// 指标为MACD
- /// 初始化MACD可视化数据
- [self initMACDData];
- /// 画MACD指标的方法
- [self drawMACD];
- break;
- }
- case VOL:{ /// 指标为VOL
- /// 初始化VOL可视化数据
- [self initVOLData];
- /// 画VOL指标的方法
- [self drawVOL];
- break;
- }
- case KDJ: { /// 指标为KDJ
- /// 初始化KDJ可视化数据
- [self initKDJData];
- /// 画KDJ指标的方法
- [self drawKDJ];
- break;
- }
- case CCI: { /// 指标为CCI
- /// 初始化CCI可视化数据
- [self initCCIData];
- /// 画CCI指标的方法
- [self drawCCI];
- break;
- }
- case PSY: { /// 指标为PSY
- /// 初始化PSY可视化数据
- [self initPSYData];
- /// 画PSY指标的方法
- [self drawPSY];
- break;
- }
- case BIAS: { /// 指标为BIAS
- /// 初始化BIAS可视化数据
- [self initBIASData];
- /// 画BIAS指标的方法
- [self drawBIAS];
- break;
- }
- case KD: { /// 指标为KD
- /// 初始化KD可视化数据
- [self initKDJData];
- /// 画KD指标的方法
- [self drawKD];
- break;
- }
- case DMA: { /// 指标为DMA
- /// 初始化DMA可视化数据
- [self initDMAData];
- /// 画DMA指标的方法
- [self drawDMA];
- break;
- }
- default:
- break;
- }
- }
- }
- } else if (_chartViewType == ChartViewTypeImmediately) { // 即时图
- /// 即时线
- [self drawImmediatelyLine];
- } else if (_chartViewType == ChartViewTypeTSPlan) { // 分时图
- /// 分时图
- [self drawTSPlanLine];
- /// 分时图平均线
- [self drawTSAverageLine];
- }
-
- // 画现价的方法
- [self drawPrice];
- }
- #pragma mark - 初始化
- /**
- * @brief 初始化图表 (图表初始化时调用)
- */
- - (void)initChartView {
- // 视图整体相关
- if (!_lineColor) _lineColor = [UIColor colorWithRed:50.0f/225.0f green:50.0f/225.0f blue:50.0f/225.0f alpha:1.0f];
- if (!_titleColor) _titleColor = [UIColor whiteColor];
- if (!_titleFont) _titleFont = [UIFont systemFontOfSize:8.0f];
-
- // K线阴块颜色
- _decKRed = 1.0f;
- _decKGreen = 0.0f;
- _decKBlue = 0.0f;
- _decKAlpha = 1.0f;
-
- // K线阳块颜色
- _aesKRed = 0.0f;
- _aesKGreen = 1.0f;
- _aesKBlue = 0.0f;
- _aesKAlpha = 1.0f;
-
- // K线平块颜色
- _samKRed = 1.0f;
- _samKGreen = 1.0f;
- _samKBlue = 1.0f;
- _samKAlpha = 1.0f;
-
- // 十字线颜色
- _tipRed = 1.0f;
- _tipGreen = 1.0f;
- _tipBlue = 1.0f;
- _tipAlpha = 1.0f;
- if (!_tipTitleColor) _tipTitleColor = [UIColor whiteColor];
-
- // K线MA5颜色
- _kMA5Red = 1.0f;
- _kMA5Green = 0.0f;
- _kMA5Blue = 1.0f;
- _kMA5Alpha = 0.5f;
-
- // K线MA10颜色 1.0f, 0.3f, 0, 0.5f
- _kMA10Red = 1.0f;
- _kMA10Green = 0.3f;
- _kMA10Blue = 0.0f;
- _kMA10Alpha = 0.5f;
-
- // K线MA15颜色 0, 1.0f, 0, 0.5f
- _kMA15Red = 0.0f;
- _kMA15Green = 1.0f;
- _kMA15Blue = 0.0f;
- _kMA15Alpha = 0.5f;
-
- // 分时线颜色 168.0f/255.0f, 217.0f/255.0f, 243.0f/255.0f, 1.0f
- _tsRed = 168.0f/255.0f;
- _tsGreen = 217.0f/255.0f;
- _tsBlue = 243.0f/255.0f;
- _tsAlpha = 1.0f;
-
- // 分时MA线 1.0f, 1.0f, 0, 1.0f
- _tsMARed = 1.0f;
- _tsMAGreen = 1.0f;
- _tsMABlue = 0.0f;
- _tsMAAlpha = 1.0f;
-
- // MACD DIF线颜色 1.0f, 0, 0, 0.5f
- _macdDIFRed = 1.0f;
- _macdDIFGreen = 0.0f;
- _macdDIFBlue = 0.0f;
- _macdDIFAlpha = 0.5f;
-
- // MACD DEA线颜色 0, 1.0f, 0, 0.5f
- _macdDEARed = 0.0f;
- _macdDEAGreen = 1.0f;
- _macdDEABlue = 0.0f;
- _macdDEAAlpha = 0.5f;
-
- //X轴相关
- _xAxisPaddingLeft = 5.0f; //X轴左边距
- // _ts_remove_count = 0;
-
- //Y轴相关
- _yAxisPaddingTop = 35.0f; //Y轴上边距,默认为10.0f(因为要显示最高标签与平均线说明标签)
- _yAxisPaddingBottom = 35.0f; //Y轴上边距,主要由视图高度-指标框高度(可能为0)计算得出
-
- //K线相关
- _kLineMinWidth = 1.0f; //K线形状最小宽度
- _kLineMaxWidth = 20.0f; //K线形状最大宽度
- _kLinePadding = 2.0f; //K线形状之间的间隔
- _kLineWidth = 5.0f; //K线形状宽度,默认为5.0f
-
- // _minUnit = [[NSDecimalNumber decimalNumberWithString:@"0.01"] retain];
-
- //交互相关
- _panGestureIncrement = 1;
-
- //现价
- _isShowPrice = YES;
-
- //指标相关
- if (_chartViewType == ChartViewTypeKL) {
- _isShowIndicator = YES;
- if (_indicatorHight == 0.0f) _indicatorHight = 70.0f;
- _indicatorPaddingBottom = 5.0f;
- } else {
- //分时图不显示指标
- _isShowIndicator = NO;
- _indicatorHight = 0;
- _indicatorPaddingBottom = 0;
- }
- }
- /**
- * @brief 初始化整个视图,主要包括计算相关数据 (设置数据时调用)
- */
- - (void)initData {
- /// 如果没有任何图表数据 不做任何处理
- if (_chartDataArray.count == 0) return;
-
- /// ************** X轴相关 ***************
- /// 计算X轴左边距
- NSDecimalNumberHandler *behavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:0 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
- ChartData *chartData = [_chartDataArray objectAtIndex:0];
- NSDecimalNumber *widthDecimalNumber = [[chartData.closed decimalNumberByRoundingAccordingToBehavior:behavior] decimalNumberByAdding:_minUnit];
- _xAxisPaddingRight = [[widthDecimalNumber description] sizeWithAttributes:@{NSFontAttributeName:_titleFont}].width + 10.0f;
-
- ///n计算X轴宽度
- _xAxisWidth = self.bounds.size.width - _xAxisPaddingLeft - _xAxisPaddingRight;
-
- if (_chartViewType == ChartViewTypeKL || _chartViewType == ChartViewTypeImmediately) {
- /// ************** K线相关 ***************
- /// 计算可显示K线数量
- _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding));
- if (_kLineCount < 0) _kLineCount = 0;
- /// 把多余的右边空间加到左边
- _excessXAxisWidth = _xAxisWidth - (_kLineWidth + _kLinePadding)*_kLineCount-1.0f;
- _xAxisPaddingRight += _excessXAxisWidth;
- _xAxisWidth -= _excessXAxisWidth;
-
- /// 当前可视K线数据起始下标 (默认最新的数据在第一条)
- _kLineStartIndex = _chartDataArray.count > _kLineCount ? _kLineCount - 1 : _chartDataArray.count - 1;
- /// 当前可视K线数据结束下标
- _kLineEndIndex = 0;
- } else {
- /// ************** 分时相关 ***************
- _excessXAxisWidth = 0;
- /// 遍历计算计划内的有效时间
- _kLineCount = 0;
- for (NSDictionary<NSString *, NSDate *> *item in _reckonDetails) {
- _kLineCount += [self diffMinuteWithFromDate:item[@"openTime"] toDate:item[@"reckonTime"]];
- }
-
- if (_kLineCount < 0) _kLineCount = 0;
- _kLineStartIndex = _chartDataArray.count-1;
- _kLineEndIndex = 0;
- }
-
- //************** Y轴相关 ***************
- /// 计算Y轴高度
- _yAxisHeight = self.bounds.size.height - _yAxisPaddingTop - _yAxisPaddingBottom - _indicatorHight - _indicatorPaddingBottom;
-
- /// ************** 坐标原点 ***************
- _kLineOrigin = CGPointMake(_xAxisPaddingLeft,_yAxisHeight + _yAxisPaddingTop);
-
- /// ************** 指标原点 ***************
- _indicatorOrigin = CGPointMake(_kLineOrigin.x, _kLineOrigin.y + _yAxisPaddingBottom + _indicatorHight);
-
- if (_chartViewType != ChartViewTypeImmediately) {
- /// 初始化平均线数据以及MACD指标数据
- [self initAverageLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化平均线数据以及VOL指标数据
- [self initVOLLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化KDJ指标数据
- [self initKDJLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化CCI指标数据
- [self initCCILineDataWithIndex:_chartDataArray.count-1];
- /// 初始化BIAS指标数据
- [self initBIASLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化PSY指标数据
- [self initPSYLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化DMA指标数据
- [self initDMALineDataWithIndex:_chartDataArray.count-1];
-
- /// 回调方法通知上层当前有数据的指标列表
- BOOL hasMACD = NO;
- BOOL hasVOL = NO;
- BOOL hasKDJ = NO;
- BOOL hasRSI = NO;
- BOOL hasCCI = NO;
- BOOL hasDMA = NO;
- BOOL hasBIAS = NO;
- BOOL hasPSY = NO;
- for (ChartData *chartData in self.chartDataArray) {
- if (chartData.macd && ![chartData.macd isEqualToNumber:[NSDecimalNumber zero]] && !hasMACD)
- hasMACD = YES;
- if (chartData.vol5 && ![chartData.vol5 isEqualToNumber:[NSDecimalNumber zero]] && !hasVOL)
- hasVOL = YES;
- if (chartData.kt && ![chartData.kt isEqualToNumber:[NSDecimalNumber zero]] && !hasKDJ)
- hasKDJ = YES;
- if (chartData.rsi1 && ![chartData.rsi1 isEqualToNumber:[NSDecimalNumber zero]] && !hasRSI)
- hasRSI = YES;
- if (chartData.cci && ![chartData.cci isEqualToNumber:[NSDecimalNumber zero]] && !hasCCI)
- hasCCI = YES;
- if (chartData.dma && ![chartData.dma isEqualToNumber:[NSDecimalNumber zero]] && !hasDMA)
- hasDMA = YES;
- if (chartData.bias1 && ![chartData.bias1 isEqualToNumber:[NSDecimalNumber zero]] && !hasBIAS)
- hasBIAS = YES;
- if (chartData.psy && ![chartData.psy isEqualToNumber:[NSDecimalNumber zero]] && !hasPSY)
- hasPSY = YES;
- }
- NSMutableArray<NSString *> *targets = [NSMutableArray arrayWithCapacity:0];
- if (hasMACD)
- [targets addObject:@"MACD"];
- if (hasVOL)
- [targets addObject:@"VOL"];
- if (hasKDJ)
- [targets addObject:@"KDJ"];
- if (hasRSI)
- [targets addObject:@"RSI"];
- if (hasCCI)
- [targets addObject:@"CCI"];
- if (hasDMA)
- [targets addObject:@"DMA"];
- if (hasBIAS)
- [targets addObject:@"BIAS"];
- if (hasPSY)
- [targets addObject:@"PSY"];
- if (self.delegate)
- [self.delegate onFinishInitDataWithTargets:targets];
- }
- }
- #pragma mark - 公开方法
- /**
- * @brief 初始化方法,一般在buildView时调用
- *
- * @param chartViewType 图表类型
- * @param frame frame
- *
- * @return self
- */
- - (nullable instancetype)initWithType:(ChartViewType)chartViewType frame:(CGRect)frame {
- /// 设置视图最小宽度与最小高度
- if (frame.size.width < 160.0f) frame.size.width = 160.0f;
- if (frame.size.height < 200.0f) frame.size.height = 200.0f;
-
- /// 类型
- _chartViewType = chartViewType;
-
- self = [super initWithFrame:frame];
- if (self) {
- /// 初始化图表
- [self initChartView];
- /// 初始化图表交互的相关手势
- [self initGestureRecognizer];
- }
-
- return self;
- }
- /**
- * @brief 切换图表类型的方法,一般在用户点击分时图或K线周期时调用
- *
- * @param chartViewType 目标切换图表类型
- * @param chartDataArray 图表数据
- */
- - (void)changeChartType:(ChartViewType)chartViewType chartDataArray:(nullable NSMutableArray *)chartDataArray {
- _chartViewType = chartViewType;
- /// 显示K线图以及指标
- if (_chartViewType == ChartViewTypeKL && _isShowIndicator) {
- if (_indicatorHight == 0.0f) _indicatorHight = 70.0f;
- _indicatorPaddingBottom = 5.0f;
- } else {
- /// 分时图不显示指标
- _indicatorHight = 0;
- _indicatorPaddingBottom = 0;
- }
- _yAxisHeight = self.bounds.size.height - _yAxisPaddingTop - _yAxisPaddingBottom - _indicatorHight - _indicatorPaddingBottom;
-
- self.chartDataArray = chartDataArray;
-
- if (_price) {
- _price = nil;
- }
- if (_priceTime) {
- _priceTime = nil;
- }
- [self setNeedsDisplay];
- }
- /**
- * @brief 切换图表指标类型的方法
- */
- - (void)changeChartTargetType:(ChartTargetType)chartTargetType {
- /// 调用上层方法重新描绘图表
- [self setNeedsDisplay];
- }
- /**
- * @brief 追加图表数据的方法,一般在图表刷新(包括自动刷新)时调用
- *
- * @param appendChartDataArray 追加的图表数据
- */
- - (void)appendChartDataArray:(nullable NSMutableArray *)appendChartDataArray {
- if (appendChartDataArray.count == 0) return;
-
- //判断追加完数据后要不要刷新图表
- BOOL isNeedRefresh = YES;
- if (_kLineEndIndex != 0) isNeedRefresh = NO;
-
- //判断追加的最后一条数据是否原第一条数据
- NSInteger appendChartDataEndIndex = _chartDataArray.count-1+appendChartDataArray.count-1;
- ChartData *appendLastChartData = [appendChartDataArray objectAtIndex:appendChartDataArray.count-1];
- ChartData *sourceFirstChartData = [_chartDataArray objectAtIndex:0];
- if ([appendLastChartData.startTime compare:sourceFirstChartData.startTime] == NSOrderedSame) {
- [_chartDataArray removeObject:sourceFirstChartData];
- appendChartDataEndIndex --;
- }
-
- /// 追加数据
- [appendChartDataArray addObjectsFromArray:_chartDataArray];
- _chartDataArray = appendChartDataArray;
-
- /// 计算平均线等数据
- if (_chartViewType == ChartViewTypeKL || _chartViewType == ChartViewTypeImmediately) {
- /// 初始化平均线数据以及MACD指标数据
- [self initAverageLineDataWithIndex:appendChartDataEndIndex];
- /// 初始化平均线数据以及VOL指标数据
- [self initVOLLineDataWithIndex:appendChartDataEndIndex];
- /// 初始化KDJ指标数据
- [self initKDJLineDataWithIndex:appendChartDataEndIndex];
- /// 初始化CCI指标数据
- [self initCCILineDataWithIndex:appendChartDataEndIndex];
- /// 初始化BIAS指标数据
- [self initBIASLineDataWithIndex:appendChartDataEndIndex];
- /// 初始化PSY指标数据
- [self initPSYLineDataWithIndex:appendChartDataEndIndex];
- /// 初始化DMA指标数据
- [self initDMALineDataWithIndex:appendChartDataEndIndex];
- }
-
- if (isNeedRefresh) [self setNeedsDisplay];
- }
- /**
- * @brief 对外公开设置图表数据的方法,内部会调用initData方法
- *
- * @param chartDataArray 图表数据
- */
- - (void)setChartDataArray:(nullable NSMutableArray *)chartDataArray {
- if (_chartDataArray) {
- if (_chartDataArray != chartDataArray) {
- _chartDataArray = chartDataArray;
- }
- } else {
- _chartDataArray = chartDataArray;
- }
- /// 初始化数据
- [self initData];
- }
- /**
- * @brief 让图表恢复正常状态的方法。可在十字线显示时离开ViewController等情况下调用。
- */
- - (void)restoreNormalState {
- _isShowTipLine = NO;
- [self setNeedsDisplay];
- }
- /**
- 清空图表的方法
- */
- - (void)clear {
- if (_chartDataArray) {
- _chartDataArray = nil;
- }
-
- [self setNeedsDisplay];
- }
- /**
- * @brief 追加行情现价的方法。
- *
- * @param price 行情现价
- * @param priceTime 行情时间
- * @param lastVolume 成交量
- *
- */
- - (ChartErrorType)appendQuotaPrice:(nullable NSDecimalNumber *)price priceTime:(nullable NSDate *)priceTime lastVolume:(nullable NSDecimalNumber *)lastVolume {
- if (_cycleInterval == 0.0f) {
- /// 没有设置周期间隔秒数则
- return ChartErrorTypeNotSetCycleInterval;
- }
-
- ChartData *chartDataLast = [_chartDataArray objectAtIndex:0];
-
- /// 如果行情时间比图表最近时间还要早则不做任务处理
- if ([priceTime compare:chartDataLast.startTime] == NSOrderedAscending) {
- return ChartErrorTypeQuotaTimeOldest;
- }
-
- /// 获取下一个周期开始时间和下两个周期开始时间
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
- NSInteger cycle = 0;
- switch ((NSInteger)_cycleInterval) {
- case 60:
- cycle = 1;
- break;
- case 5 * 60:
- cycle = 4;
- break;
- case 15 * 60:
- cycle = 14;
- break;
- case 30 * 60:
- cycle = 29;
- break;
- case 60 * 60:
- cycle = 59;
- break;
- case 60 * 60 * 2:
- cycle = (60 * 2) - 1;
- break;
- case 60 * 60 * 4:
- cycle = (60 * 4) - 1;
- break;
- case 60 * 60 * 24:
- cycle = (60 * 24) - 1;
- break;
- default:
- break;
- }
- NSInteger seconds = cycle * 60 - [[[dateFormatter stringFromDate:chartDataLast.startTime] substringWithRange:NSMakeRange(16, 2)] integerValue];
- NSDate *nextOneDate = [[NSDate alloc] initWithTimeInterval:seconds sinceDate:chartDataLast.startTime];
- NSDate *nextTwoDate = [[NSDate alloc] initWithTimeInterval:_cycleInterval*2 sinceDate:chartDataLast.startTime];
-
- if ([priceTime compare:nextTwoDate] != NSOrderedAscending) {
- /// 行情时间已经超时一个数据块时间周期
- if (self.delegate) {
- [self.delegate requestRefreshChartDataWithErrorCode:ChartErrorTypeQuotaTimeout];
- }
- } else {
- /// 行情时间在可接收范围之内,则再判断行情数据是图表最近时间块内,还是下一个时间周期块
- if ([priceTime compare:nextOneDate] != NSOrderedAscending) {
- /// Warning:目前遇到下一个周期不是整数的问题,暂时直接处理
- priceTime = [chartDataLast.startTime dateByAddingTimeInterval:_cycleInterval];
- ChartData *chartData = [[ChartData alloc] init];
- chartData.opened = price;
- chartData.closed = price;
- chartData.highest = price;
- chartData.lowest = price;
-
- chartData.startTime = priceTime;
- chartData.totleVolume = lastVolume;
- [_chartDataArray insertObject:chartData atIndex:0];
-
- /// 触发图表数据最新时间变更回调
- if (self.delegate) [self.delegate onChangeDataLasttime:priceTime];
- } else {
- /// 行情时间属于图表最近时间周期块
- chartDataLast.closed = price;
- if ([price compare:chartDataLast.highest] == NSOrderedDescending) {
- chartDataLast.highest = price;
- }
- if ([price compare:chartDataLast.lowest] == NSOrderedAscending) {
- chartDataLast.lowest = price;
- }
- if (chartDataLast.totleVolume && lastVolume) {
- chartDataLast.totleVolume = [chartDataLast.totleVolume decimalNumberByAdding:lastVolume];
- }
- }
-
- /// 记录现价和时间
- if (_price) {
- if (_price != price) {
- _price = price;
- }
- } else {
- _price = price;
- }
-
- if (_priceTime) {
- if (_priceTime != priceTime) {
- _priceTime = priceTime;
- }
- } else {
- _priceTime = priceTime;
- }
-
- /// 计算平均线等数据
- if (_chartViewType == ChartViewTypeKL || _chartViewType == ChartViewTypeImmediately) {
- /// 初始化平均线数据以及MACD指标数据
- /// 刷新最近一条数据就可以(错)
- [self initAverageLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化平均线数据以及VOL指标数据
- [self initVOLLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化KDJ指标数据
- [self initKDJLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化CCI指标数据
- [self initCCILineDataWithIndex:_chartDataArray.count-1];
- /// 初始化BIAS指标数据
- [self initBIASLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化PSY指标数据
- [self initPSYLineDataWithIndex:_chartDataArray.count-1];
- /// 初始化DMA指标数据
- [self initDMALineDataWithIndex:_chartDataArray.count-1];
- } else {
- /// 初始化平均线数据以及MACD指标数据
- /// 刷新最近一条数据就可以(错)
- [self initAverageLineDataWithIndex:_chartDataArray.count-1];
- }
- /// 调用父类方法 重新去描绘图表
- [self setNeedsDisplay];
- }
-
- return ChartErrorTypeNone;
- }
- #pragma mark - 颜色设置
- /**
- * @brief 设置K线阴块颜色的方法
- *
- * @param decKRed K线阴块红色值
- * @param decKGreen K线阴块绿色值
- * @param decKBlue K线阴块蓝色值
- * @param decKAlpha K线阴块alpha值
- */
- - (void)setDecKRed:(CGFloat)decKRed decKGreen:(CGFloat)decKGreen decKBlue:(CGFloat)decKBlue decKAlpha:(CGFloat)decKAlpha {
- _decKRed = decKRed;
- _decKGreen = decKGreen;
- _decKBlue = decKBlue;
- _decKAlpha = decKAlpha;
- }
- /**
- * @brief 设置K线阳块颜色的方法
- *
- * @param aesKRed K线阳块红色值
- * @param aesKGreen K线阳块绿色值
- * @param aesKBlue K线阳块蓝色值
- * @param aesKAlpha K线阳块alpha值
- */
- - (void)setAesKRed:(CGFloat)aesKRed aesKGreen:(CGFloat)aesKGreen aesKBlue:(CGFloat)aesKBlue aesKAlpha:(CGFloat)aesKAlpha {
- _aesKRed = aesKRed;
- _aesKGreen = aesKGreen;
- _aesKBlue = aesKBlue;
- _aesKAlpha = aesKAlpha;
- }
- /**
- * @brief 设置开高低收报价字体颜色为绿色时的颜色
- */
- - (void)setPriceGreenColor:(nullable UIColor *)priceGreenColor {
- if (!_priceGreenColor) {
- _priceGreenColor = priceGreenColor;
- } else {
- _priceGreenColor = nil;
- _priceGreenColor = priceGreenColor;
- }
- }
- /**
- * @brief 设置K线平块颜色的方法
- *
- * @param samKRed K线平块红色值
- * @param samKGreen K线平块绿色值
- * @param samKBlue K线平块蓝色值
- * @param samKAlpha K线平块alpha值
- */
- - (void)setSamKRed:(CGFloat)samKRed samKGreen:(CGFloat)samKGreen samKBlue:(CGFloat)samKBlue samKAlpha:(CGFloat)samKAlpha {
- _samKRed = samKRed;
- _samKGreen = samKGreen;
- _samKBlue = samKBlue;
- _samKAlpha = samKAlpha;
- }
- /**
- * @brief 设置十字线颜色的方法
- *
- * @param tipRed 十字线红色值
- * @param tipGreen 十字线绿色值
- * @param tipBlue 十字线蓝色值
- * @param tipAlpha 十字线alpha值
- * @param tipTitleColor 十字线标题颜色对象
- */
- - (void)setTipRed:(CGFloat)tipRed tipGreen:(CGFloat)tipGreen tipBlue:(CGFloat)tipBlue tipAlpha:(CGFloat)tipAlpha tipTitleColor:(nullable UIColor *)tipTitleColor {
- _tipRed = tipRed;
- _tipGreen = tipGreen;
- _tipBlue = tipBlue;
- _tipAlpha = tipAlpha;
- if (_tipTitleColor) {
- if (_tipTitleColor != tipTitleColor) {
- _tipTitleColor = tipTitleColor;
- }
- } else {
- _tipTitleColor = tipTitleColor;
- }
- }
- /**
- * @brief 设置分时图昨收线颜色的方法
- *
- * @param preCloseLineRed 昨收线红色值
- * @param preCloseLineGreen 昨收线绿色值
- * @param preCloseLineBlue 昨收线蓝色值
- * @param preCloseLineAlpha 昨收线alpha值
- */
- - (void)setPreCloseLineRed:(CGFloat)preCloseLineRed preCloseLineGreen:(CGFloat)preCloseLineGreen preCloseLineBlue:(CGFloat)preCloseLineBlue preCloseLineAlpha:(CGFloat)preCloseLineAlpha {
- _preCloseLineRed = preCloseLineRed;
- _preCloseLineGreen = preCloseLineGreen;
- _preCloseLineBlue = preCloseLineBlue;
- _preCloseLineAlpha = preCloseLineAlpha;
- }
- /**
- * @brief 设置K线MA5平均线颜色的方法
- *
- * @param kMA5Red K线MA5平均线红色值
- * @param kMA5Green K线MA5平均线绿色值
- * @param kMA5Blue K线MA5平均线蓝色值
- * @param kMA5Alpha K线MA5平均线alpha值
- */
- - (void)setkMA5Red:(CGFloat)kMA5Red kMA5Green:(CGFloat)kMA5Green kMA5Blue:(CGFloat)kMA5Blue kMA5Alpha:(CGFloat)kMA5Alpha {
- _kMA5Red = kMA5Red;
- _kMA5Green = kMA5Green;
- _kMA5Blue = kMA5Blue;
- _kMA5Alpha = kMA5Alpha;
- }
- /**
- * @brief 设置K线MA10平均线颜色的方法
- *
- * @param kMA10Red K线MA10平均线红色值
- * @param kMA10Green K线MA10平均线绿色值
- * @param kMA10Blue K线MA10平均线蓝色值
- * @param kMA10Alpha K线MA10平均线alpha值
- */
- - (void)setkMA10Red:(CGFloat)kMA10Red kMA10Green:(CGFloat)kMA10Green kMA10Blue:(CGFloat)kMA10Blue kMA10Alpha:(CGFloat)kMA10Alpha {
- _kMA10Red = kMA10Red;
- _kMA10Green = kMA10Green;
- _kMA10Blue = kMA10Blue;
- _kMA10Alpha = kMA10Alpha;
- }
- /**
- * @brief 设置K线MA15平均线颜色的方法
- *
- * @param kMA15Red K线MA15平均线红色值
- * @param kMA15Green K线MA15平均线绿色值
- * @param kMA15Blue K线MA15平均线蓝色值
- * @param kMA15Alpha K线MA15平均线alpha值
- */
- - (void)setkMA15Red:(CGFloat)kMA15Red kMA15Green:(CGFloat)kMA15Green kMA15Blue:(CGFloat)kMA15Blue kMA15Alpha:(CGFloat)kMA15Alpha {
- _kMA15Red = kMA15Red;
- _kMA15Green = kMA15Green;
- _kMA15Blue = kMA15Blue;
- _kMA15Alpha = kMA15Alpha;
- }
- /**
- * @brief 设置分时线颜色的方法
- *
- * @param tsRed 分时线红色值
- * @param tsGreen 分时线绿色值
- * @param tsBlue 分时线蓝色值
- * @param tsAlpha 分时线alpha值
- */
- - (void)setTsRed:(CGFloat)tsRed tsGreen:(CGFloat)tsGreen tsBlue:(CGFloat)tsBlue tsAlpha:(CGFloat)tsAlpha {
- _tsRed = tsRed;
- _tsGreen = tsGreen;
- _tsBlue = tsBlue;
- }
- /**
- * @brief 设置分时MA线颜色的方法
- *
- * @param tsMARed 分时MA线红色值
- * @param tsMAGreen 分时MA线绿色值
- * @param tsMABlue 分时MA线蓝色值
- * @param tsMAAlpha 分时MA线alpha值
- */
- - (void)setTsMARed:(CGFloat)tsMARed tsMAGreen:(CGFloat)tsMAGreen tsMABlue:(CGFloat)tsMABlue tsMAAlpha:(CGFloat)tsMAAlpha {
- _tsMARed = tsMARed;
- _tsMAGreen = tsMAGreen;
- _tsMABlue = tsMABlue;
- _tsMAAlpha = tsMAAlpha;
- }
- /**
- * @brief 设置MACD DIF线颜色的方法
- *
- * @param macdDIFRed MACD DIF线红色值
- * @param macdDIFGreen MACD DIF线绿色值
- * @param macdDIFBlue MACD DIF线蓝色值
- * @param macdDIFAlpha MACD DIF线alpha值
- */
- - (void)setMacdDIFRed:(CGFloat)macdDIFRed macdDIFGreen:(CGFloat)macdDIFGreen macdDIFBlue:(CGFloat)macdDIFBlue macdDIFAlpha:(CGFloat)macdDIFAlpha {
- _macdDIFRed = macdDIFRed;
- _macdDIFGreen = macdDIFGreen;
- _macdDIFBlue = macdDIFBlue;
- _macdDIFAlpha = macdDIFAlpha;
- }
- /**
- * @brief 设置MACD DEA线颜色的方法
- *
- * @param macdDEARed MACD DEA线红色值
- * @param macdDEAGreen MACD DEA线绿色值
- * @param macdDEABlue MACD DEA线蓝色值
- * @param macdDEAAlpha MACD DEA线alpha值
- */
- - (void)setMacdDEARed:(CGFloat)macdDEARed macdDEAGreen:(CGFloat)macdDEAGreen macdDEABlue:(CGFloat)macdDEABlue macdDEAAlpha:(CGFloat)macdDEAAlpha {
- _macdDEARed = macdDEARed;
- _macdDEAGreen = macdDEAGreen;
- _macdDEABlue = macdDEABlue;
- _macdDEAAlpha = macdDEAAlpha;
- }
- /**
- * @brief 设置RSI RSI1线颜色的方法
- *
- * @param rsi1Red RSI RSI1线红色值
- * @param rsi1Green RSI RSI1线绿色值
- * @param rsi1Blue RSI RSI1线蓝色值
- * @param rsi1Alpha RSI RSI1线alpha值
- */
- - (void)setRSI1Red:(CGFloat)rsi1Red rsi1Green:(CGFloat)rsi1Green rsi1Blue:(CGFloat)rsi1Blue rsi1Alpha:(CGFloat)rsi1Alpha {
- _rsi1Red = rsi1Red;
- _rsi1Green = rsi1Green;
- _rsi1Blue = rsi1Blue;
- _rsi1Alpha = rsi1Alpha;
- }
- /**
- * @brief 设置RSI RSI2线颜色的方法
- *
- * @param rsi2Red RSI RSI2线红色值
- * @param rsi2Green RSI RSI2线绿色值
- * @param rsi2Blue RSI RSI2线蓝色值
- * @param rsi2Alpha RSI RSI2线alpha值
- */
- - (void)setRSI2Red:(CGFloat)rsi2Red rsi2Green:(CGFloat)rsi2Green rsi2Blue:(CGFloat)rsi2Blue rsi2Alpha:(CGFloat)rsi2Alpha {
- _rsi2Red = rsi2Red;
- _rsi2Green = rsi2Green;
- _rsi2Blue = rsi2Blue;
- _rsi2Alpha = rsi2Alpha;
- }
- /**
- * @brief 设置RSI RSI3线颜色的方法
- *
- * @param rsi3Red RSI RSI3线红色值
- * @param rsi3Green RSI RSI3线绿色值
- * @param rsi3Blue RSI RSI3线蓝色值
- * @param rsi3Alpha RSI RSI3线alpha值
- */
- - (void)setRSI3Red:(CGFloat)rsi3Red rsi3Green:(CGFloat)rsi3Green rsi3Blue:(CGFloat)rsi3Blue rsi3Alpha:(CGFloat)rsi3Alpha {
- _rsi3Red = rsi3Red;
- _rsi3Green = rsi3Green;
- _rsi3Blue = rsi3Blue;
- _rsi3Alpha = rsi3Alpha;
- }
- /**
- * @brief 设置KT KT线颜色的方法
- *
- * @param ktRed KT KT线红色值
- * @param ktGreen KT KT线绿色值
- * @param ktBlue KT KT线蓝色值
- * @param ktAlpha KT KT线alpha值
- */
- - (void)setKTRed:(CGFloat)ktRed ktGreen:(CGFloat)ktGreen ktBlue:(CGFloat)ktBlue ktAlpha:(CGFloat)ktAlpha {
- _ktRed = ktRed;
- _ktGreen = ktGreen;
- _ktBlue = ktBlue;
- _ktAlpha = ktAlpha;
- }
- /**
- * @brief 设置DT DT线颜色的方法
- *
- * @param dtRed DT DT线红色值
- * @param dtGreen DT DT线绿色值
- * @param dtBlue DT DT线蓝色值
- * @param dtAlpha DT DT线alpha值
- */
- - (void)setDTRed:(CGFloat)dtRed dtGreen:(CGFloat)dtGreen dtBlue:(CGFloat)dtBlue dtAlpha:(CGFloat)dtAlpha {
- _dtRed = dtRed;
- _dtGreen = dtGreen;
- _dtBlue = dtBlue;
- _dtAlpha = dtAlpha;
- }
- /**
- * @brief 设置JT JT线颜色的方法
- *
- * @param jtRed JT JT线红色值
- * @param jtGreen JT JT线绿色值
- * @param jtBlue JT JT线蓝色值
- * @param jtAlpha JT JT线alpha值
- */
- - (void)setJTRed:(CGFloat)jtRed jtGreen:(CGFloat)jtGreen jtBlue:(CGFloat)jtBlue jtAlpha:(CGFloat)jtAlpha {
- _jtRed = jtRed;
- _jtBlue = jtBlue;
- _jtGreen = jtGreen;
- _jtAlpha = jtAlpha;
- }
- /**
- * @brief 设置CCI CCI线颜色的方法
- *
- * @param cciRed CCI CCI线红色值
- * @param cciGreen CCI CCI线绿色值
- * @param cciBlue CCI CCI线蓝色值
- * @param cciAlpha CCI CCI线alpha值
- */
- - (void)setCCIRed:(CGFloat)cciRed cciGreen:(CGFloat)cciGreen cciBlue:(CGFloat)cciBlue cciAlpha:(CGFloat)cciAlpha {
- _cciRed = cciRed;
- _cciGreen = cciGreen;
- _cciBlue = cciBlue;
- _cciAlpha = cciAlpha;
- }
- /**
- * @brief 设置DMA线颜色的方法
- *
- * @param dmaRed DMA线红色值
- * @param dmaGreen DMA线绿色值
- * @param dmaBlue DMA线蓝色值
- * @param dmaAlpha DMA线alpha值
- */
- - (void)setDMARed:(CGFloat)dmaRed dmaGreen:(CGFloat)dmaGreen cciBlue:(CGFloat)dmaBlue cciAlpha:(CGFloat)dmaAlpha {
- _dmaRed = dmaRed;
- _dmaGreen = dmaGreen;
- _dmaBlue = dmaBlue;
- _dmaAlpha = dmaAlpha;
- }
- /**
- * @brief 设置AMA线颜色的方法
- *
- * @param amaRed AMA线红色值
- * @param amaGreen AMA线绿色值
- * @param amaBlue AMA线蓝色值
- * @param amaAlpha AMA线alpha值
- */
- - (void)setAMARed:(CGFloat)amaRed amaGreen:(CGFloat)amaGreen cciBlue:(CGFloat)amaBlue cciAlpha:(CGFloat)amaAlpha {
- _amaRed = amaRed;
- _amaGreen = amaGreen;
- _amaBlue = amaBlue;
- _amaAlpha = amaAlpha;
- }
- /**
- * @brief 设置BIAS BIAS1线颜色的方法
- *
- * @param bias1Red BIAS BIAS1线红色值
- * @param bias1Green BIAS BIAS1线绿色值
- * @param bias1Blue BIAS BIAS1线蓝色值
- * @param bias1Alpha BIAS BIAS1线alpha值
- */
- - (void)setBIAS1Red:(CGFloat)bias1Red bias1Green:(CGFloat)bias1Green bias1Blue:(CGFloat)bias1Blue bias1Alpha:(CGFloat)bias1Alpha {
- _bias1Red = bias1Red;
- _bias1Green = bias1Green;
- _bias1Blue = bias1Blue;
- _bias1Alpha = bias1Alpha;
- }
- /**
- * @brief 设置BIAS BIAS2线颜色的方法
- *
- * @param bias2Red BIAS BIAS2线红色值
- * @param bias2Green BIAS BIAS2线绿色值
- * @param bias2Blue BIAS BIAS2线蓝色值
- * @param bias2Alpha BIAS BIAS2线alpha值
- */
- - (void)setBIAS2Red:(CGFloat)bias2Red bias2Green:(CGFloat)bias2Green bias2Blue:(CGFloat)bias2Blue bias2Alpha:(CGFloat)bias2Alpha {
- _bias2Red = bias2Red;
- _bias2Green = bias2Green;
- _bias2Blue = bias2Blue;
- _bias2Alpha = bias2Alpha;
- }
- /**
- * @brief 设置BIAS BIAS3线颜色的方法
- *
- * @param bias3Red BIAS BIAS3线红色值
- * @param bias3Green BIAS BIAS3线绿色值
- * @param bias3Blue BIAS BIAS3线蓝色值
- * @param bias3Alpha BIAS BIAS3线alpha值
- */
- - (void)setBIAS3Red:(CGFloat)bias3Red bias3Green:(CGFloat)bias3Green bias3Blue:(CGFloat)bias3Blue bias3Alpha:(CGFloat)bias3Alpha {
- _bias3Red = bias3Red;
- _bias3Green = bias3Green;
- _bias3Blue = bias3Blue;
- _bias3Alpha = bias3Alpha;
- }
- /**
- * @brief 设置PSY PSY线颜色的方法
- *
- * @param psyRed PSY PSY线红色值
- * @param psyGreen PSY PSY线绿色值
- * @param psyBlue PSY PSY线蓝色值
- * @param psyAlpha PSY PSY线alpha值
- */
- - (void)setPSYRed:(CGFloat)psyRed psyGreen:(CGFloat)psyGreen psyBlue:(CGFloat)psyBlue psyAlpha:(CGFloat)psyAlpha {
- _psyRed = psyRed;
- _psyGreen = psyGreen;
- _psyBlue = psyBlue;
- _psyAlpha = psyAlpha;
- }
- /**
- * @brief 设置PSYMA PSYMA线颜色的方法
- *
- * @param psymaRed PSYMA PSYMA线红色值
- * @param psymaGreen PSYMA PSYMA线绿色值
- * @param psymaBlue PSYMA PSYMA线蓝色值
- * @param psymaAlpha PSYMA PSYMA线alpha值
- */
- - (void)setPSYMARed:(CGFloat)psymaRed psymaGreen:(CGFloat)psymaGreen psymaBlue:(CGFloat)psymaBlue psymaAlpha:(CGFloat)psymaAlpha {
- _psymaRed = psymaRed;
- _psymaGreen = psymaGreen;
- _psymaBlue = psymaBlue;
- _psymaAlpha = psymaAlpha;
- }
- #pragma mark - 画坐标轴相关
- /**
- * @brief 更新数据的方法,主要用于更新图表
- */
- - (void)updateData {
- //当前可视坐标最高价=当前可视最高价+几个点(这几个点应该从当前可视最高与最低价点差计算得出)
- NSDecimalNumber *maxValue = [self maxPriceAtVisible];
- NSDecimalNumber *minValue = [self minPriceAtVisible];
-
- // 这里有可能最大值和最小值相等
- if ([maxValue compare:minValue] == NSOrderedSame) {
- ChartData *chartData = _chartDataArray[0];
-
- maxValue = [chartData.closed decimalNumberByAdding:[_minUnit decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInt:20]]];
- }
-
- //如果当前是分时图,要重新计算最高最低价,以便让昨收线在中间
- if (_chartViewType == ChartViewTypeTSPlan) {
- NSDecimalNumber *diffMax = [ChartCalculateUtils abs:[_preClose decimalNumberBySubtracting:maxValue]];
- NSDecimalNumber *diffMin = [ChartCalculateUtils abs:[_preClose decimalNumberBySubtracting:minValue]];
-
- if ([diffMax compare:diffMin] == NSOrderedDescending) {
- //最高与昨收的差比最低的大
- maxValue = [_preClose decimalNumberByAdding:diffMax];
- minValue = [_preClose decimalNumberBySubtracting:diffMax];
- } else {
- //反之
- maxValue = [_preClose decimalNumberByAdding:diffMin];
- minValue = [_preClose decimalNumberBySubtracting:diffMin];
- }
- }
-
- //最多10个点的高低值
- NSDecimalNumberHandler *behavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:0 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
- NSInteger stepValue = [[[[[maxValue decimalNumberBySubtracting:minValue] decimalNumberByDividingBy:_minUnit] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"10"]] decimalNumberByRoundingAccordingToBehavior:behavior] integerValue];
- if (stepValue > 10)
- stepValue = 10;
- NSString *stepString = [NSString stringWithFormat:@"%d",(int)stepValue];
-
- _yAxisMaxValue = [[maxValue decimalNumberByAdding:[_minUnit decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:stepString]]] floatValue];
- _yAxisMinValue = [[minValue decimalNumberBySubtracting:[_minUnit decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:stepString]]] floatValue];
- }
- /**
- * @brief 画框架
- */
- - (void)drawBorder {
- CGContextRef context = UIGraphicsGetCurrentContext();
-
- //整体相关
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- CGContextSetRGBFillColor(context, _bgRed, _bgGreen, _bgBlue, 1.0f);
- CGContextFillRect(context, self.bounds);
-
- //边框相关
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha];
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextAddRect(context, CGRectMake(_kLineOrigin.x, _yAxisPaddingTop, _xAxisWidth, _yAxisHeight));
- #ifdef DEBUG
- // NSLog(@"%s _yAxisHeight:%f", __func__, _yAxisHeight);
- #endif
-
- NSString *targetTitle = [[NSString alloc] init];
- //指标相关
- if (_isShowIndicator) {
- if (_chartViewType == ChartViewTypeKL) {
- CGContextAddRect(context, CGRectMake(_indicatorOrigin.x, _indicatorOrigin.y-_indicatorHight, _xAxisWidth, _indicatorHight));
- CGContextStrokePath(context);
-
- if (_chartTargetType == MACD) {
- //MACD标题
- targetTitle = @"MACD(12,26,9)";
- } else if (_chartTargetType == VOL) {
- //VOL标题
- targetTitle = @"VOL(5,10)";
- } else if (_chartTargetType == KDJ) {
- //KDJ标题
- targetTitle = @"KDJ(9,3,3)";
- } else if (_chartTargetType == RSI) {
- //RSI标题
- targetTitle = @"RSI(6,12,24)";
- } else if (_chartTargetType == CCI) {
- //CCI标题
- targetTitle = @"CCI(14)";
- } else if (_chartTargetType == DMA) {
- //DMA标题
- targetTitle = @"DMA(10,50,10)";
- } else if (_chartTargetType == KD) {
- //KD标题
- targetTitle = @"KD(9,3)";
- } else if (_chartTargetType == BIAS) {
- //BIAS标题
- targetTitle = @"BIAS(6,12,24)";
- } else if (_chartTargetType == PSY) {
- //PSY标题
- targetTitle = @"PSY(12,6)";
- }
- }
-
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; // 价格左边距
- // 写数据
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:targetTitle attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:_titleColor}];
- [tipString drawAtPoint:CGPointMake(priceXOffset - 60.0f, _indicatorOrigin.y - _indicatorHight - 15.0f)];
- }
- }
- /**
- * @brief 画X轴
- */
- - (void)drawXAxis {
- //时间格式化
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- /// 分时图
- dateFormatter.dateFormat = _chartViewType == ChartViewTypeTSPlan ? @"HH:mm" : @"MM-dd HH:mm";
-
- if (_chartViewType == ChartViewTypeTSPlan) {//分时图
- //开盘时间
- [_lineColor setFill];
- [_titleColor set];
- [[dateFormatter stringFromDate:_tsStartTime] drawAtPoint:_kLineOrigin withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //收盘时间
- [_titleColor set];
- CGFloat dateStringWidth = [[dateFormatter stringFromDate:_tsCloseTime] sizeWithAttributes:@{NSFontAttributeName:_titleFont}].width;
- [_titleColor set];
- [[dateFormatter stringFromDate:_tsCloseTime] drawAtPoint:CGPointMake(_kLineOrigin.x + _xAxisWidth - dateStringWidth, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- } else {//K线或即时线
- //起始时间
- ChartData *startChartData = [_chartDataArray objectAtIndex:_kLineStartIndex];
- [_lineColor setFill];
- [_titleColor set];
- [[dateFormatter stringFromDate:startChartData.startTime] drawAtPoint:_kLineOrigin withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //结束时间,如果K线数量不足整屏则不显示结束时间
- if (_chartDataArray.count >= _kLineCount) {
- ChartData *endChartData = [_chartDataArray objectAtIndex:_kLineEndIndex];
- CGFloat dateStringWidth = [[dateFormatter stringFromDate:endChartData.startTime] sizeWithAttributes:@{NSFontAttributeName:_titleFont}].width;
- [_titleColor set];
- [[dateFormatter stringFromDate:endChartData.startTime] drawAtPoint:CGPointMake(_kLineOrigin.x + _xAxisWidth - dateStringWidth, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- }
- }
- }
- /**
- * @brief 画Y轴
- */
- - (void)drawYAxis {
- //当前可视坐标最高价=当前可视最高价+几个点(这几个点应该从当前可视最高与最低价点差计算得出)
- NSDecimalNumber *maxValue = [self maxPriceAtVisible];
- NSDecimalNumber *minValue = [self minPriceAtVisible];
-
- // 这里有可能最大值和最小值相等
- if ([maxValue compare:minValue] == NSOrderedSame) {
- ChartData *chartData = _chartDataArray[0];
- maxValue = [chartData.closed decimalNumberByAdding:[_minUnit decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInt:20]]];
- }
-
- //如果当前是分时图,要重新计算最高最低价,以便让昨收线在中间
- if (_chartViewType == ChartViewTypeTSPlan) {
- NSDecimalNumber *diffMax = [ChartCalculateUtils abs:[_preClose decimalNumberBySubtracting:maxValue]];
- NSDecimalNumber *diffMin = [ChartCalculateUtils abs:[_preClose decimalNumberBySubtracting:minValue]];
-
- if ([diffMax compare:diffMin] == NSOrderedDescending) {
- //最高与昨收的差比最低的大
- maxValue = [_preClose decimalNumberByAdding:diffMax];
- minValue = [_preClose decimalNumberBySubtracting:diffMax];
- } else {
- //反之
- maxValue = [_preClose decimalNumberByAdding:diffMin];
- minValue = [_preClose decimalNumberBySubtracting:diffMin];
- }
- }
-
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha];
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
-
- //画线
- CGContextSetLineWidth(context, 1.0f);
- //当前可视最高价线
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:maxValue]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:maxValue]);
- //当前可视最低价线
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:minValue]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:minValue]);
- //二等分价线
- NSDecimalNumber *averagePrice = [[[maxValue decimalNumberBySubtracting:minValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]] decimalNumberByAdding:minValue];
- if (_chartViewType != ChartViewTypeTSPlan) {
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:averagePrice]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:averagePrice]);
- }
- //四等分价线(高)
- NSDecimalNumber *quarterHighPrice = [averagePrice decimalNumberByAdding:[[averagePrice decimalNumberBySubtracting:minValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]]];
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:quarterHighPrice]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:quarterHighPrice]);
- //四等分价线(低)
- NSDecimalNumber *quarterLowPrice = [averagePrice decimalNumberBySubtracting:[[averagePrice decimalNumberBySubtracting:minValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]]];
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:quarterLowPrice]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:quarterLowPrice]);
- CGContextStrokePath(context);
-
- //写价格
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
- //K线最高价
- [_titleColor set];
- NSString *maxPriceString = [ChartCalculateUtils notRounding:maxValue afterPoint:digitCount];
- [maxPriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:maxValue] - [maxPriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- //K线最低价
- NSString *minPriceString = [ChartCalculateUtils notRounding:minValue afterPoint:digitCount];
- [minPriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:minValue] - [maxPriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- //二等分价
- if (_chartViewType != ChartViewTypeTSPlan) {
- NSString *averagePriceString = [ChartCalculateUtils notRounding:averagePrice afterPoint:digitCount];
- [averagePriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:averagePrice] - [averagePriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- }
- //四等分价(高)
- NSString *quarterHighPriceString = [ChartCalculateUtils notRounding:quarterHighPrice afterPoint:digitCount];
- [quarterHighPriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:quarterHighPrice] - [quarterHighPriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- //四等分价(低)
- NSString *quarterLowPriceString = [ChartCalculateUtils notRounding:quarterLowPrice afterPoint:digitCount];
- [quarterLowPriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:quarterLowPrice] - [quarterLowPriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //分时图画昨收线与昨收价
- if (_chartViewType == ChartViewTypeTSPlan) {
- CGContextSetRGBStrokeColor(context, _preCloseLineRed, _preCloseLineGreen, _preCloseLineBlue, _preCloseLineAlpha);
- CGFloat dashes[] = { 4, 3 };
- CGContextSetLineDash( context, 0.0, dashes, 2 );
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:_preClose]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:_preClose]);
- CGContextStrokePath(context);
- CGContextSetLineDash(context, 0.0, dashes, 0);
-
- [[UIColor colorWithRed:_preCloseLineRed green:_preCloseLineGreen blue:_preCloseLineBlue alpha:_preCloseLineAlpha] set];
- NSString *preCloseString = [ChartCalculateUtils notRounding:_preClose afterPoint:digitCount];
- [preCloseString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:_preClose] - [preCloseString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- }
- }
- #pragma mark - 画K线相关
- /**
- * @brief 画K线的方法
- */
- - (void)drawKLine {
- CGContextRef context = UIGraphicsGetCurrentContext();
-
- CGFloat currentXPonit = _kLineOrigin.x + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if ([chartData.closed compare:chartData.opened] == NSOrderedAscending) {
- //close < open
- CGContextSetRGBFillColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
- CGContextAddRect(context, CGRectMake(currentXPonit, [self yPointWithPrice:chartData.opened], _kLineWidth, [self yPointWithPrice:chartData.closed] - [self yPointWithPrice:chartData.opened]));
- CGContextFillPath(context);
-
- if ([chartData.highest compare:chartData.opened] == NSOrderedDescending) {
- //high > open
- CGContextSetRGBStrokeColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.highest]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.opened]);
- CGContextStrokePath(context);
- }
-
- if ([chartData.lowest compare:chartData.closed] == NSOrderedAscending) {
- //low < close
- CGContextSetRGBStrokeColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.closed]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.lowest]);
- CGContextStrokePath(context);
- }
- } else if ([chartData.closed compare:chartData.opened] == NSOrderedDescending) {
-
- //close > open
- CGContextSetRGBFillColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
- CGContextAddRect(context, CGRectMake(currentXPonit, [self yPointWithPrice:chartData.closed], _kLineWidth, [self yPointWithPrice:chartData.opened] - [self yPointWithPrice:chartData.closed]));
- CGContextFillPath(context);
-
- if ([chartData.highest compare:chartData.closed] == NSOrderedDescending) {
- CGContextSetRGBStrokeColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
- //high > close
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.highest]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.closed]);
- CGContextStrokePath(context);
- }
-
- if ([chartData.lowest compare:chartData.opened] == NSOrderedAscending) {
- //low < close
- CGContextSetRGBStrokeColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
- //low < open
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.opened]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.lowest]);
- CGContextStrokePath(context);
- }
-
- CGContextStrokePath(context);
- } else {
- //close == open
- CGContextSetRGBStrokeColor(context, _samKRed, _samKGreen, _samKBlue, _samKAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth, [self yPointWithPrice:chartData.closed]);
-
- if ([chartData.highest compare:chartData.closed] == NSOrderedDescending) {
- //high > close
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.highest]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.closed]);
- }
-
- if ([chartData.lowest compare:chartData.closed] == NSOrderedAscending) {
- //low < open
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.closed]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.lowest]);
- }
-
- CGContextStrokePath(context);
- }
-
- //是否需要显示十字线
- if (_isShowTipLine) {
- /// 是否需要长显示开高低收
- [self showOHLPPriceWithIsKLine:YES isShow:NO];
- if (_tipLineIndex == i) {
- /// 画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, _yAxisPaddingTop);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, _kLineOrigin.y);
-
- /// 画水平线
- CGContextMoveToPoint(context, _kLineOrigin.x, _tipLineYAxis);
- CGContextAddLineToPoint(context, _kLineOrigin.x + _xAxisWidth , _tipLineYAxis);
- CGContextStrokePath(context);
-
- /// 写数据
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSString *ma5 = [ChartCalculateUtils notRounding:chartData.ma5 afterPoint:digitCount];
-
- UIColor *profileColor = nil;
- if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
- profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
- else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
- profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
- else
- profileColor = _titleColor;
-
- /// 写数据
- NSMutableAttributedString *MAString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@ ", ma5 ? ma5 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA5Red green:_kMA5Green blue:_kMA5Blue alpha:_kMA5Alpha], NSFontAttributeName:_titleFont}];
- NSString *ma10 = [ChartCalculateUtils notRounding:chartData.ma10 afterPoint:digitCount];
- [MAString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@ ",ma10 ? ma10 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA10Red green:_kMA10Green blue:_kMA10Blue alpha:_kMA10Alpha], NSFontAttributeName:_titleFont}]];
- NSString *ma15 = [ChartCalculateUtils notRounding:chartData.ma15 afterPoint:digitCount];
- [MAString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA15:%@ ",ma15 ? ma15 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA15Red green:_kMA15Green blue:_kMA15Blue alpha:_kMA15Alpha], NSFontAttributeName:_titleFont}]];
- NSAttributedString *tipString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n开:%@ 高:%@ 低:%@ 收:%@", [ChartCalculateUtils notRounding:chartData.opened afterPoint:digitCount], [ChartCalculateUtils notRounding:chartData.highest afterPoint:digitCount] ,[ChartCalculateUtils notRounding:chartData.lowest afterPoint:digitCount],[ChartCalculateUtils notRounding:chartData.closed afterPoint:digitCount]] attributes:@{NSForegroundColorAttributeName:profileColor, NSFontAttributeName:_titleFont}];
- // 横屏一排显示就够了
- if (self.frame.size.width < self.frame.size.height) {
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, 12.0f)];
- } else {
- [MAString appendAttributedString:tipString];
- }
- [MAString drawAtPoint:CGPointMake(_kLineOrigin.x, 0)];
-
- //纵轴时间
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- if (self.cycleInterval == 30 * 24 * 60 * 60) {
- dateFormatter.dateFormat = @"MM-dd";
- } else {
- dateFormatter.dateFormat = @"MM-dd HH:mm";
- }
- NSString *dateTime = [dateFormatter stringFromDate:chartData.startTime];
- CGSize dateTimeSize = [dateTime sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGFloat x = currentXPonit+_kLineWidth/2-dateTimeSize.width/2;
- if (x < _xAxisPaddingLeft)
- x = _xAxisPaddingLeft;
- else if (x > _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width)
- x = _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width;
- CGContextAddRect(context, CGRectMake(x, _kLineOrigin.y, dateTimeSize.width, dateTimeSize.height));
- CGContextFillPath(context);
- [_tipTitleColor set];
- [dateTime drawAtPoint:CGPointMake(x, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
- //横轴价格
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSDecimalNumber *yPrice = [self priceWithYPoint:_tipLineYAxis];
- NSString *priceString = [ChartCalculateUtils notRounding:yPrice afterPoint:decimalNumber];
- CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextAddRect(context, CGRectMake(priceXOffset, _tipLineYAxis-priceStringSize.height/2, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
- CGContextFillPath(context);
- [_tipTitleColor set];
- [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, _tipLineYAxis-priceStringSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
- }
- } else {
- /// 是否需要长显示开高低收
- [self showOHLPPriceWithIsKLine:YES isShow:YES];
- }
-
- currentXPonit += _kLineWidth + _kLinePadding;
- }
- }
- #pragma mark - 十字线相关
- /**
- * @brief 通过x坐标获取对应K线数据下标
- *
- * @param xPoint x坐标
- *
- * @return K线数据下标
- */
- - (NSInteger)tipIndexWithXPoint:(CGFloat)xPoint {
- NSInteger tipIndex = NSNotFound;
-
- CGFloat currentXPonit = _kLineOrigin.x + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- //要把K线的间隔也算上
- CGRect kLineRect = CGRectMake(currentXPonit, _yAxisPaddingTop, _kLineWidth+_kLinePadding, _yAxisHeight);
- if (CGRectContainsPoint(kLineRect, CGPointMake(xPoint, _yAxisPaddingTop+10.0f))) {
- tipIndex = i;
- break;
- }
- currentXPonit += _kLineWidth + _kLinePadding;
- }
-
- return tipIndex;
- }
- /**
- * @brief 通过x坐标获取对应分时数据下标
- *
- * @param xPoint x坐标
- *
- * @return 分时数据下标
- */
- - (NSInteger)tipIndexTSPlanWithXPoint:(CGFloat)xPoint {
- NSInteger tipIndex = NSNotFound;
-
- CGFloat currentXPonit = _tsStartXPonit;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- //要把K线的间隔也算上
- CGRect kLineRect = CGRectMake(currentXPonit, _yAxisPaddingTop, _xAxisWidth/_kLineCount, _yAxisHeight);
- if (CGRectContainsPoint(kLineRect, CGPointMake(xPoint, _yAxisPaddingTop+10.0f))) {
- tipIndex = i;
- break;
- }
-
- currentXPonit += _xAxisWidth/_kLineCount;
- }
-
- return tipIndex;
- }
- #pragma mark - 图表数据计算相关
- /**
- * @brief 初始计算各平均线数据的方法
- *
- * @param index 需要刷新数据的0-index的范围
- */
- - (void)initAverageLineDataWithIndex:(NSInteger)index {
- //当前总合,主要用于分时图
- NSDecimalNumber *totalPrice = [NSDecimalNumber zero];
- NSDecimalNumber *totalNumber = [NSDecimalNumber zero];
- for (NSInteger i=index ; i>=0 ; i--) {
- /// m5
- if (index-i>=4) {
- ChartData *chartData = nil;
- NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
- for (NSInteger j=i+4; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
- }
- chartData.ma5 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"5"]];
- }
-
- /// m10
- if (index-i>=9) {
- ChartData *chartData = nil;
- NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
- for (NSInteger j=i+9; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
- }
- chartData.ma10 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"10"]];
- }
-
- /// m15
- if (index-i>=14) {
- ChartData *chartData = nil;
- NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
- for (NSInteger j=i+14; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
- }
- chartData.ma15 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"15"]];
- }
-
- /// m50
- if (index-i>=49) {
- ChartData *chartData = nil;
- NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
- for (NSInteger j=i+49 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
- }
- chartData.ma50 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"50"]];
- }
-
- //****************** MACD ********************
- //EMA12
- if (index-i>=11) {
- if (index-i == 11) {
- //第一个EMA12是前12个收盘价代数平均
- NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
- ChartData *chartData = nil;
- for (NSInteger j=i+11 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
- }
- chartData.ema12 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"]];
- }
- else {
- //今日EMA(12) = 2/(12+1)×今日收盘价 + 11/(12+1)×昨日EMA(12)<-错的 EMA12 = 前一日EMA12 X 11/13 + 今日收盘 X 2/13
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- ChartData *yesterdayChartData = [_chartDataArray objectAtIndex:i+1];
- chartData.ema12 = [[[[ChartCalculateUtils notRoundingWithDecimalNumber:yesterdayChartData.ema12 afterPoint:5] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"11"]] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"13"]] decimalNumberByAdding:([[chartData.closed decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"2"]] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"13"]])];
- }
- }
-
- //EMA26 & DIF
- if (index-i>=25) {
- if (index-i == 25) {
- NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
- ChartData *chartData = nil;
- for (NSInteger j=i+25 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
- }
- chartData.ema26 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"26"]];
- chartData.dif = [chartData.ema12 decimalNumberBySubtracting:chartData.ema26];
- }
- else {
- //今日EMA(26)=2/(26+1)×今日收盘价+25/(26+1)×昨日EMA(26)<-错的 EMA26 = 前一日EMA26 X 25/27 + 今日收盘 X 2/27
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- ChartData *yesterdayChartData = [_chartDataArray objectAtIndex:i+1];
- chartData.ema26 = [[[[ChartCalculateUtils notRoundingWithDecimalNumber:yesterdayChartData.ema26 afterPoint:5] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"25"]] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"27"]] decimalNumberByAdding:([[chartData.closed decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"2"]] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"27"]])];
- chartData.dif = [chartData.ema12 decimalNumberBySubtracting:chartData.ema26];
- }
- }
-
- //DEA & MACD
- if (index-i>=34) {
- if (index-i == 34) {
- ChartData *chartData = nil;
- NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
- for (NSInteger j=i+9 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.dif];
- }
- chartData.dea = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"9"]];
- // macd = (dif-dea)*2
- chartData.macd = [[NSDecimalNumber decimalNumberWithString:@"2"] decimalNumberByMultiplyingBy:([chartData.dif decimalNumberBySubtracting:chartData.dea])];
- }
- else {
- //今日DEA=(前一日DEA X 8/10 + 今日DIF X 2/10)
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- ChartData *yesterdayChartData = [_chartDataArray objectAtIndex:i+1];
- chartData.dea = [[[ChartCalculateUtils notRoundingWithDecimalNumber:yesterdayChartData.dea afterPoint:5] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"0.8"]] decimalNumberByAdding:([chartData.dif decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"0.2"]])];
-
- chartData.macd = [[NSDecimalNumber decimalNumberWithString:@"2"] decimalNumberByMultiplyingBy:([chartData.dif decimalNumberBySubtracting:chartData.dea])];
- }
- }
-
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (i == 0 || !chartData.isSupp) {
- totalPrice = [totalPrice decimalNumberByAdding:chartData.closed];
- totalNumber = [totalNumber decimalNumberByAdding:[NSDecimalNumber decimalNumberWithString:@"1"]];
- chartData.tsma = [totalPrice decimalNumberByDividingBy:totalNumber];
- } else {
- if (i != _chartDataArray.count - 1) {
- // 这里去对补的数据不进行处理
- ChartData *yesterdayChartData = [_chartDataArray objectAtIndex:i+1];
- // 如果是补的数据 当前的平均数据为上一口的数据
- chartData.tsma = yesterdayChartData.tsma;
- }
- }
- }
- }
- /**
- * @brief 初始计算VOL线数据的方法
- *
- * @param index 需要刷新数据的0-index的范围
- */
- - (void)initVOLLineDataWithIndex:(NSInteger)index {
- for (NSInteger i=index ; i>=0 ; i--) {
- //期5为周期算
- if (index - i >= 4) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- NSDecimalNumber *averagevolume= [NSDecimalNumber zero];
- //算出周期里面收盘价的总和
- for (NSInteger j=i+4 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- if (chartData.totleVolume)
- averagevolume = [averagevolume decimalNumberByAdding:chartData.totleVolume];
- }
- //vol5 = sum(totalVolume, N)/N
- chartData.vol5 = [averagevolume decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"5"]];
- }
-
- //期10为周期算
- if (index - i >= 9) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- NSDecimalNumber *averagevolume= [NSDecimalNumber zero];
- //算出周期里面收盘价的总和
- for (NSInteger j=i+9 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- if (chartData.totleVolume)
- averagevolume = [averagevolume decimalNumberByAdding:chartData.totleVolume];
- }
- //BIAS = sum(totalVolume, N)/N
- chartData.vol10 = [averagevolume decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"10"]];
- }
- }
- }
- /**
- * @brief 初始计算KDJ线数据的方法
- *
- * @param index 需要刷新数据的0-index的范围
- */
- - (void)initKDJLineDataWithIndex:(NSInteger)index {
- for (NSInteger i=index ; i>=0 ; i--) {
- /// 取前九根为一周期
- if (index - i >= 8) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- NSDecimalNumber *highDecimalNumber = chartData.highest;
- NSDecimalNumber *lowDecimalNumber = chartData.lowest;
- /// 循环算出周期里面的最高值和最低值
- for (NSInteger j=i; j-i<8; j++) {
- ChartData *yesterdayData = [_chartDataArray objectAtIndex:j+1];
- if ([highDecimalNumber compare:yesterdayData.highest] == NSOrderedAscending) {
- highDecimalNumber = yesterdayData.highest;
- }
- if ([lowDecimalNumber compare:yesterdayData.lowest] == NSOrderedDescending) {
- lowDecimalNumber = yesterdayData.lowest;
- }
- }
-
- /// 如果最高价和最低价相等 则默认rsv值为50
- if ([lowDecimalNumber compare:highDecimalNumber] == NSOrderedSame) {
- chartData.rsv = [NSDecimalNumber decimalNumberWithString:@"50"];
- } else {
- chartData.rsv = [[[chartData.closed decimalNumberBySubtracting:lowDecimalNumber] decimalNumberByDividingBy:[highDecimalNumber decimalNumberBySubtracting:lowDecimalNumber]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
- }
- /// 如果前一日的KT值不存在则默认为50
- if (!((ChartData *)[_chartDataArray objectAtIndex:i+1]).kt) {
- ((ChartData *)[_chartDataArray objectAtIndex:i+1]).kt = [NSDecimalNumber decimalNumberWithString:@"50"];
- }
- /// 如果前一日的DT值不存在则默认为50
- if (!((ChartData *)[_chartDataArray objectAtIndex:i+1]).dt) {
- ((ChartData *)[_chartDataArray objectAtIndex:i+1]).dt = [NSDecimalNumber decimalNumberWithString:@"50"];
- }
-
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
- /// KT = 2/3*前一日的KT+1/3*当日的RSV
- chartData.kt = [NSDecimalNumber decimalNumberWithString:[ChartCalculateUtils notRounding:[[[[NSDecimalNumber decimalNumberWithString:@"2"] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"3"]] decimalNumberByMultiplyingBy:((ChartData *)[_chartDataArray objectAtIndex:i+1]).kt] decimalNumberByAdding:[[[NSDecimalNumber decimalNumberWithString:@"1"] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"3"]] decimalNumberByMultiplyingBy:chartData.rsv]] afterPoint:digitCount]];
-
- /// DT = 2/3*前一日的DT+1/3*当日的KT
- chartData.dt = [NSDecimalNumber decimalNumberWithString:[ChartCalculateUtils notRounding:[[[[NSDecimalNumber decimalNumberWithString:@"2"] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"3"]] decimalNumberByMultiplyingBy:((ChartData *)[_chartDataArray objectAtIndex:i+1]).dt] decimalNumberByAdding:[[[NSDecimalNumber decimalNumberWithString:@"1"] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"3"]] decimalNumberByMultiplyingBy:chartData.kt]] afterPoint:digitCount]];
-
- /// JT = 3*当前的KT-2*当日的DT
- chartData.jt = [[[NSDecimalNumber decimalNumberWithString:@"3"] decimalNumberByMultiplyingBy:chartData.kt] decimalNumberBySubtracting:[[NSDecimalNumber decimalNumberWithString:@"2"] decimalNumberByMultiplyingBy:chartData.dt]];
- }
- }
- }
- /**
- * @brief 初始计算CCI线数据的方法
- *
- * @param index 需要刷新数据的0-index的范围
- */
- - (void)initCCILineDataWithIndex:(NSInteger)index {
- for (NSInteger i=index ; i>=0 ; i--) {
- /// 取14根为一周期
- if (index - i >=13) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- ///TP = (highest + lowest + close)/3
- chartData.tp = [[[chartData.highest decimalNumberByAdding:chartData.lowest] decimalNumberByAdding:chartData.closed] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"3"]];
-
- /// MA = N日的TP的和/N
- NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
- /// 循环算出周期里面收盘价的总和
- for (NSInteger j=i+13; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- if (chartData.tp)
- totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.tp];
- }
- chartData.ma = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"14"]];
-
- /// MD = N日的|((N)TP-MA)|的和/N(平均绝对方差)
- NSDecimalNumber *totalMDSum = [NSDecimalNumber zero];
- NSDecimalNumber *decimal = [NSDecimalNumber zero];
- /// 循环算出周期里面收盘价的总和
- for (NSInteger j=i+13 ; j>=i ; j--) {
- ChartData *nowChartData = [_chartDataArray objectAtIndex:j];
- if (chartData.ma && nowChartData.tp)
- decimal = [nowChartData.tp decimalNumberBySubtracting:chartData.ma];
- /// 如果算出来的值为负数 则去绝对值
- if ([decimal compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
- decimal = [decimal decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"-1"]];
- }
- totalMDSum = [totalMDSum decimalNumberByAdding:decimal];
- }
- chartData.md = [totalMDSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"14"]];
-
- /// CCI = (TP-MA)/MD/0.015
- if (chartData.tp && chartData.ma && chartData.md && [chartData.md compare:[NSDecimalNumber zero]] != NSOrderedSame)
- chartData.cci = [[chartData.tp decimalNumberBySubtracting:chartData.ma] decimalNumberByDividingBy:[chartData.md decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"0.015"]]];
- }
- }
- }
- /**
- * @brief 初始计算DMA线数据的方法
- *
- * @param index 需要刷新数据的0-index的范围
- */
- - (void)initDMALineDataWithIndex:(NSInteger)index {
- for (NSInteger i=index ; i>=0 ; i--) {
- //以10为一周期进行计算
- if (index - i >= 9) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //DMA = MA10 - MA50
- if (chartData.ma10 && chartData.ma50)
- chartData.dma = [chartData.ma10 decimalNumberBySubtracting:chartData.ma50];
-
- NSDecimalNumber *totalAMASum = [NSDecimalNumber zero];
- //算出周期里面dma的和
- for (NSInteger j=i+9 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- if (chartData.dma)
- totalAMASum = [totalAMASum decimalNumberByAdding:chartData.dma];
- }
- chartData.ama = [totalAMASum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"10"]];
- }
- }
- }
- /**
- * @brief 初始计算BIAS线数据的方法
- *
- * @param index 需要刷新数据的0-index的范围
- */
- - (void)initBIASLineDataWithIndex:(NSInteger)index {
- for (NSInteger i=index ; i>=0 ; i--) {
- //期6为周期算
- if (index - i >= 5) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- NSDecimalNumber *totalCloseSum = [NSDecimalNumber zero];
- //算出周期里面收盘价的总和
- for (NSInteger j=i+5 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totalCloseSum = [totalCloseSum decimalNumberByAdding:chartData.closed];
- }
- if ([totalCloseSum compare:[NSDecimalNumber zero]] != NSOrderedSame) {
- //BIAS = (closed - N(closed))/N(closed)*100
- chartData.bias1 = [[[chartData.closed decimalNumberBySubtracting:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"6"]]] decimalNumberByDividingBy:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"6"]]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
- } else {
- chartData.bias1 = [NSDecimalNumber zero];
- }
- }
-
- //期12为周期算
- if (index - i >= 11) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- NSDecimalNumber *totalCloseSum = [NSDecimalNumber zero];
- //算出周期里面收盘价的总和
- for (NSInteger j=i+11 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totalCloseSum = [totalCloseSum decimalNumberByAdding:chartData.closed];
- }
-
- if ([totalCloseSum compare:[NSDecimalNumber zero]] != NSOrderedSame) {
- //BIAS = (closed - N(closed))/N(closed)*100
- chartData.bias2 = [[[chartData.closed decimalNumberBySubtracting:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"]]] decimalNumberByDividingBy:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"]]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
- } else {
- chartData.bias2 = [NSDecimalNumber zero];
- }
- }
-
- //期24为周期算
- if (index - i >= 23) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- NSDecimalNumber *totalCloseSum = [NSDecimalNumber zero];
- //算出周期里面收盘价的总和
- for (NSInteger j=i+23 ; j>=i ; j--) {
- chartData = [_chartDataArray objectAtIndex:j];
- totalCloseSum = [totalCloseSum decimalNumberByAdding:chartData.closed];
- }
- if ([totalCloseSum compare:[NSDecimalNumber zero]] != NSOrderedSame) {
- //BIAS = (closed - N(closed))/N(closed)*100
- chartData.bias3 = [[[chartData.closed decimalNumberBySubtracting:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"24"]]] decimalNumberByDividingBy:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"24"]]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
- } else {
- chartData.bias3 = [NSDecimalNumber zero];
- }
- }
- }
- }
- /**
- * @brief 初始计算PSY线数据的方法
- *
- * @param index 需要刷新数据的0-index的范围
- */
- - (void)initPSYLineDataWithIndex:(NSInteger)index {
- for (NSInteger i=index ; i>=0 ; i--) {
- //取前12根为一周期
- if (index - i >= 12) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- NSDecimalNumber *upFlagDecimalNumber = [NSDecimalNumber zero];
- //循环算出周期里面上涨的天数
- for (NSInteger j=i; j-i<12; j++) {
- ChartData *nowChartData = [_chartDataArray objectAtIndex:j];
- ChartData *yesterdayData = [_chartDataArray objectAtIndex:j+1];
- if ([nowChartData.closed compare:yesterdayData.closed] == NSOrderedDescending) {
- upFlagDecimalNumber = [upFlagDecimalNumber decimalNumberByAdding:[NSDecimalNumber decimalNumberWithString:@"1"]];
- }
- }
- //PSY = 上涨的天数/周期 * 100
- chartData.psy = [[upFlagDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
- }
-
- //取前6根为一周期
- if (index - i >= 6) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- NSDecimalNumber *sumPsyDecimal = [NSDecimalNumber zero];
- //循环算出周期里面上涨的天数
- for (NSInteger j=i; j-i<6; j++) {
- ChartData *nowChartData = [_chartDataArray objectAtIndex:j];
- if (nowChartData.psy) {
- sumPsyDecimal = [sumPsyDecimal decimalNumberByAdding:nowChartData.psy];
- }
- }
-
- //PSYMA = PSY的M日简单移动平均
- chartData.psyma = [sumPsyDecimal decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"6"]];
- }
- }
- }
- #pragma mark - 画平均线相关
- /**
- * @brief 画平均线的方法(MACD相关计算目前也放在这个方法完成)
- */
- - (void)drawAverageLine {
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- /// MA5
- CGContextSetRGBStrokeColor(context, _kMA5Red, _kMA5Green, _kMA5Blue, _kMA5Alpha);
- CGFloat currentXPoint = _kLineOrigin.x + 1.0f+_kLineWidth/2;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.ma5) {
- /// 前4条数据
- }
- else if (chartData.ma5 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
- }
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //MA10
- CGContextSetRGBStrokeColor(context, _kMA10Red, _kMA10Green, _kMA10Blue, _kMA10Alpha);
- currentXPoint = _kLineOrigin.x + 1.0f+_kLineWidth/2;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.ma10) {
- //前9条数据
- }
- else if (chartData.ma10 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
- }
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //MA15
- CGContextSetRGBStrokeColor(context, _kMA15Red, _kMA15Green, _kMA15Blue, _kMA15Alpha);
- currentXPoint = _kLineOrigin.x + 1.0f+_kLineWidth/2;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.ma15) {
- //前14条数据
- }
- else if (chartData.ma15 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
- }
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- if (!_isShowTipLine) {
- // 获取最后一根数据
- ChartData *chartData = [_chartDataArray objectAtIndex:0];
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
- //平均线说明
- CGFloat currentX = _kLineOrigin.x;
- //MA5
- NSString *ma5 = [ChartCalculateUtils notRounding:chartData.ma5 afterPoint:digitCount];
- NSAttributedString *MA5 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@", ma5 ? ma5 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA5Red green:_kMA5Green blue:_kMA5Blue alpha:_kMA5Alpha]}];
- CGSize titleSize = [MA5 size];
- [MA5 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
- currentX += titleSize.width + 4.0f;
-
- //MA10
- NSString *ma10 = [ChartCalculateUtils notRounding:chartData.ma10 afterPoint:digitCount];
- NSAttributedString *MA10 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@", ma10 ? ma10 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA10Red green:_kMA10Green blue:_kMA10Blue alpha:_kMA10Alpha]}];
- titleSize = [MA10 size];
- [MA10 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
- currentX += titleSize.width + 4.0f;
-
- //MA15
- NSString *ma15 = [ChartCalculateUtils notRounding:chartData.ma15 afterPoint:digitCount];
- NSAttributedString *MA15 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA15:%@", ma15 ? ma15 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA15Red green:_kMA15Green blue:_kMA15Blue alpha:_kMA15Alpha]}];
- titleSize = [MA15 size];
- [MA15 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
- }
- }
- /**
- * @brief 画平均线的方法(MACD相关计算目前也放在这个方法完成)
- */
- - (void)drawBBAverageLine {
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //MA5
- CGContextSetRGBStrokeColor(context, _kMA5Red, _kMA5Green, _kMA5Blue, _kMA5Alpha);
- CGFloat currentXPoint = _kLineOrigin.x;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.ma5) {
- //前4条数据
- }
- else if (chartData.ma5 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
- }
- currentXPoint += _xAxisWidth/_kLineCount;
- }
- CGContextStrokePath(context);
-
- //MA10
- CGContextSetRGBStrokeColor(context, _kMA10Red, _kMA10Green, _kMA10Blue, _kMA10Alpha);
- currentXPoint = _kLineOrigin.x;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.ma10) {
- //前9条数据
- }
- else if (chartData.ma10 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
- }
- currentXPoint += _xAxisWidth/_kLineCount;
- }
- CGContextStrokePath(context);
-
- //MA15
- CGContextSetRGBStrokeColor(context, _kMA15Red, _kMA15Green, _kMA15Blue, _kMA15Alpha);
- currentXPoint = _kLineOrigin.x;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.ma15) {
- //前14条数据
- }
- else if (chartData.ma15 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
- }
- currentXPoint += _xAxisWidth/_kLineCount;
- }
- CGContextStrokePath(context);
-
- if (!_isShowTipLine) {
- // 获取最后一根数据
- ChartData *chartData = [_chartDataArray objectAtIndex:0];
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
- //平均线说明
- CGFloat currentX = _kLineOrigin.x;
- //MA5
- NSString *ma5 = [ChartCalculateUtils notRounding:chartData.ma5 afterPoint:digitCount];
- NSAttributedString *MA5 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@", ma5 ? ma5 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA5Red green:_kMA5Green blue:_kMA5Blue alpha:_kMA5Alpha]}];
- CGSize titleSize = [MA5 size];
- [MA5 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
- currentX += titleSize.width + 4.0f;
-
- //MA10
- NSString *ma10 = [ChartCalculateUtils notRounding:chartData.ma10 afterPoint:digitCount];
- NSAttributedString *MA10 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@", ma10 ? ma10 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA10Red green:_kMA10Green blue:_kMA10Blue alpha:_kMA10Alpha]}];
- titleSize = [MA10 size];
- [MA10 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
- currentX += titleSize.width + 4.0f;
-
- //MA15
- NSString *ma15 = [ChartCalculateUtils notRounding:chartData.ma15 afterPoint:digitCount];
- NSAttributedString *MA15 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA15:%@", ma15 ? ma15 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA15Red green:_kMA15Green blue:_kMA15Blue alpha:_kMA15Alpha]}];
- titleSize = [MA15 size];
- [MA15 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
- }
- }
- #pragma mark - 画即时图相关
- /**
- * @brief 画即时图的方法
- */
- - (void)drawImmediatelyLine {
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetRGBStrokeColor(context, 1.0f, 1.0, 1.0f, 1.0f);
-
- BOOL isInit = NO;
- CGFloat currentXPonit = _kLineOrigin.x + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!isInit) {
- CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
- CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
- }
-
- currentXPonit += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- /// 是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- /// 画垂直线
- CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, _yAxisPaddingTop);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, _kLineOrigin.y);
-
- /// 画水平线
- CGContextMoveToPoint(context, _kLineOrigin.x, _tipLineYAxis);
- CGContextAddLineToPoint(context, _kLineOrigin.x + _xAxisWidth , _tipLineYAxis);
- CGContextStrokePath(context);
-
- /// 写数据
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSString *tipString = [NSString stringWithFormat:@"Open:%@ High:%@ Low:%@ Close:%@"
- ,[ChartCalculateUtils notRounding:chartData.opened afterPoint:digitCount]
- ,[ChartCalculateUtils notRounding:chartData.highest afterPoint:digitCount]
- ,[ChartCalculateUtils notRounding:chartData.lowest afterPoint:digitCount]
- ,[ChartCalculateUtils notRounding:chartData.closed afterPoint:digitCount]
- ];
- UIColor *profileColor = nil;
- if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
- profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
- else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
- profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
- else
- profileColor = _titleColor;
- [profileColor set];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, _yAxisPaddingTop - [tipString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- /// 纵轴时间
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- dateFormatter.dateFormat = @"MM-dd HH:mm";
- NSString *dateTime = [dateFormatter stringFromDate:chartData.startTime];
- CGSize dateTimeSize = [dateTime sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 0.9f);
- CGFloat x = currentXPonit+_kLineWidth/2-dateTimeSize.width/2;
- if (x < _xAxisPaddingLeft)
- x = _xAxisPaddingLeft;
- else if (x > _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width)
- x = _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width;
- CGContextAddRect(context, CGRectMake(x, _kLineOrigin.y, dateTimeSize.width, dateTimeSize.height));
- CGContextFillPath(context);
- [[UIColor blackColor] set];
- [dateTime drawAtPoint:CGPointMake(x, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
-
- /// 横轴价格
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSDecimalNumber *yPrice = [self priceWithYPoint:_tipLineYAxis];
- NSString *priceString = [ChartCalculateUtils notRounding:yPrice afterPoint:decimalNumber];
- CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 0.9f);
- CGContextAddRect(context, CGRectMake(priceXOffset, _tipLineYAxis-priceStringSize.height/2, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
- CGContextFillPath(context);
- [[UIColor blackColor] set];
- [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, _tipLineYAxis-priceStringSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
-
- break;
- }
- }
-
- currentXPonit += _kLineWidth + _kLinePadding;
- }
- }
- #pragma mark - 画分时图相关
- /**
- * @brief 画分时图的方法
- */
- - (void)drawTSPlanLine {
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetRGBStrokeColor(context, _tsRed, _tsGreen, _tsBlue, _tsAlpha);
- CGContextSetLineWidth(context, 1.0f);
-
- NSMutableArray<NSValue *> *pointArray = [[NSMutableArray alloc] init];
-
- /// FIXME: 临时性解决有完整数据(交易日已完整休市)后,总数据条数对不上的问题
- if (self.chartDataArray.count > 0) {
- ChartData *lastData = self.chartDataArray[0];
- if ([lastData.startTime compare:self.tsCloseTime] == NSOrderedSame && !_added) {
- _kLineCount = self.chartDataArray.count;
- _added = YES;
- }
- }
-
- /// 判断最早的数据时间是否开盘时间
- BOOL isInit = NO;
- NSInteger diffTime = [self diffMinuteWithFromDate:_tsStartTime toDate:((ChartData *)[_chartDataArray objectAtIndex:_chartDataArray.count-1]).startTime];
- _tsStartXPonit = _kLineOrigin.x;
- if (diffTime != 0) {
- /// 在昨价线上画一条到最早数据的直线
- _tsStartXPonit += diffTime * (_xAxisWidth/_kLineCount);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:_preClose]);
- CGContextAddLineToPoint(context, _tsStartXPonit, [self yPointWithPrice:_preClose]);
- isInit = YES;
-
- /// 记录第一个点
- [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(_kLineOrigin.x, [self yPointWithPrice:_preClose])]];
- /// 记录第二个点
- [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(_tsStartXPonit, [self yPointWithPrice:_preClose])]];
- }
-
- CGFloat currentXPonit = _tsStartXPonit;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- /// 记录位置
- CGPoint point = CGPointMake(currentXPonit, [self yPointWithPrice:chartData.closed]);
- [pointArray addObject:[NSValue valueWithCGPoint:point]];
-
- if (!isInit) {
- CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
- CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
- }
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- CGContextStrokePath(context);
-
- if (pointArray.count > 0) {
- /// 画填充
- CGContextMoveToPoint(context, _kLineOrigin.x, _kLineOrigin.y);
- for (int i=0 ; i<pointArray.count ; i++) {
- CGPoint point = [[pointArray objectAtIndex:i] CGPointValue];
- CGContextAddLineToPoint(context, point.x, point.y);
- }
-
- CGPoint point = [[pointArray objectAtIndex:pointArray.count-1] CGPointValue];
- CGContextAddLineToPoint(context, point.x,_kLineOrigin.y);
- CGContextAddLineToPoint(context, _kLineOrigin.x,_kLineOrigin.y);
- CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0xe3/0xff green:0xef/0xff blue:0xff/0xff alpha:0.1f].CGColor);
- CGContextFillPath(context);
- }
-
- currentXPonit = _tsStartXPonit;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- /// 是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- /// 画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, _yAxisPaddingTop);
- CGContextAddLineToPoint(context, currentXPonit, _kLineOrigin.y);
-
- /// 画水平线
- CGContextMoveToPoint(context, _kLineOrigin.x, _tipLineYAxis);
- CGContextAddLineToPoint(context, _kLineOrigin.x + _xAxisWidth , _tipLineYAxis);
- CGContextStrokePath(context);
-
- UIColor *profileColor = nil;
- if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
- profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
- else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
- profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
- else
- profileColor = _titleColor;
-
- /// 写数据
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSString *tipString = [NSString stringWithFormat:@"开:%@ 高:%@ 低:%@ 收:%@"
- ,[ChartCalculateUtils notRounding:chartData.opened afterPoint:digitCount]
- ,[ChartCalculateUtils notRounding:chartData.highest afterPoint:digitCount]
- ,[ChartCalculateUtils notRounding:chartData.lowest afterPoint:digitCount]
- ,[ChartCalculateUtils notRounding:chartData.closed afterPoint:digitCount]
- ];
- [profileColor set];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, _yAxisPaddingTop - [tipString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: profileColor}];
-
- /// 纵轴时间
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- dateFormatter.dateFormat = _chartViewType == ChartViewTypeTSPlan ? @"HH:mm" : @"MM-dd HH:mm";
- NSString *dateTime = [dateFormatter stringFromDate:chartData.startTime];
- CGSize dateTimeSize = [dateTime sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGFloat x = currentXPonit+_kLineWidth/2-dateTimeSize.width/2;
- if (x < _xAxisPaddingLeft)
- x = _xAxisPaddingLeft;
- else if (x > _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width)
- x = _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width;
- CGContextAddRect(context, CGRectMake(x, _kLineOrigin.y, dateTimeSize.width, dateTimeSize.height));
- CGContextFillPath(context);
- [_tipTitleColor set];
- [dateTime drawAtPoint:CGPointMake(x, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
- /// 横轴价格
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth;
- /// 价格左边距
- NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSDecimalNumber *yPrice = [self priceWithYPoint:_tipLineYAxis];
- NSString *priceString = [ChartCalculateUtils notRounding:yPrice afterPoint:decimalNumber];
- CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextAddRect(context, CGRectMake(priceXOffset, _tipLineYAxis-priceStringSize.height/2, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
- CGContextFillPath(context);
- [_tipTitleColor set];
- [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, _tipLineYAxis-priceStringSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
-
- break;
- }
- }
-
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- }
- /// 是否需要常显示开高低收
- - (void)showOHLPPriceWithIsKLine:(BOOL)isKine isShow:(BOOL)isShow {
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetRGBStrokeColor(context, _tsRed, _tsGreen, _tsBlue, _tsAlpha);
- CGContextSetLineWidth(context, 1.0f);
-
- /// 不需要显示 不做任何处理
- if (!_isShowOHLP) { return; }
- /// 数据为空不做任何处理
- if (self.chartDataArray.count == 0) { return; }
-
- ChartData *chartData = [self.chartDataArray firstObject];
- UIColor *profileColor = nil;
- if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
- profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
- else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
- profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
- else
- profileColor = _titleColor;
- /// 写数据
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
-
- NSAttributedString *tipString = isShow ? [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"开:%@ 高:%@ 低:%@ 收:%@", [ChartCalculateUtils notRounding:chartData.opened afterPoint:digitCount], [ChartCalculateUtils notRounding:chartData.highest afterPoint:digitCount], [ChartCalculateUtils notRounding:chartData.lowest afterPoint:digitCount], [ChartCalculateUtils notRounding:chartData.closed afterPoint:digitCount]] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:profileColor}] : [[NSAttributedString alloc] initWithString:@""];
-
- CGPoint point = isKine ? CGPointMake(_kLineOrigin.x, _yAxisPaddingTop - [tipString size].height + 15.0) : CGPointMake(_kLineOrigin.x, _yAxisPaddingTop - [tipString size].height + 15.0);
- [tipString drawAtPoint:point];
-
- CGContextFillPath(context);
- }
- /**
- * @brief 画分时图平均线的方法
- */
- - (void)drawTSAverageLine {
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- /// MA5
- CGContextSetRGBStrokeColor(context, _tsMARed, _tsMAGreen, _tsMABlue, _tsMAAlpha);
- CGFloat currentXPoint =_tsStartXPonit;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.tsma && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.tsma]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.tsma]);
- }
- currentXPoint += _xAxisWidth/_kLineCount;
- }
- CGContextStrokePath(context);
-
- if (!_isShowTipLine) {
- /// 平均线说明
- CGFloat currentX = _kLineOrigin.x;
- /// MA5
- [[UIColor colorWithRed:_tsMARed green:_tsMAGreen blue:_tsMABlue alpha:_tsMAAlpha] set];
- CGSize titleSize = [@"MA" sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- [@"MA" drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - titleSize.height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- }
- }
- #pragma mark - 数字货币分时图
- /**
- * @brief 数字火币画分时图的方法
- */
- - (void)drawBBTSPlanLine {
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- CGContextSetRGBStrokeColor(context, _tsRed, _tsGreen, _tsBlue, _tsAlpha);
- CGFloat currentXPoint = _kLineOrigin.x;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.tsma && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.closed]);
- isInit = YES;
- }
- else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.closed]);
- }
- currentXPoint += _xAxisWidth/_kLineCount;
- }
- CGContextStrokePath(context);
-
- currentXPoint = _kLineOrigin.x;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- /// 是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPoint, _yAxisPaddingTop);
- CGContextAddLineToPoint(context, currentXPoint, _kLineOrigin.y);
- /// 画水平线
- CGContextMoveToPoint(context, _kLineOrigin.x, _tipLineYAxis);
- CGContextAddLineToPoint(context, _kLineOrigin.x + _xAxisWidth , _tipLineYAxis);
- CGContextStrokePath(context);
-
- UIColor *profileColor = nil;
- if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
- profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
- else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
- profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
- else
- profileColor = _titleColor;
-
- /// 写数据
- NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSString *ma5 = [ChartCalculateUtils notRounding:chartData.ma5 afterPoint:digitCount];
-
- /// 写数据
- NSMutableAttributedString *MAString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@ ", ma5 ? ma5 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA5Red green:_kMA5Green blue:_kMA5Blue alpha:_kMA5Alpha], NSFontAttributeName:_titleFont}];
- NSString *ma10 = [ChartCalculateUtils notRounding:chartData.ma10 afterPoint:digitCount];
- [MAString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@ ",ma10 ? ma10 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA10Red green:_kMA10Green blue:_kMA10Blue alpha:_kMA10Alpha], NSFontAttributeName:_titleFont}]];
- NSString *ma15 = [ChartCalculateUtils notRounding:chartData.ma15 afterPoint:digitCount];
- [MAString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA15:%@ ",ma15 ? ma15 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA15Red green:_kMA15Green blue:_kMA15Blue alpha:_kMA15Alpha], NSFontAttributeName:_titleFont}]];
- NSAttributedString *tipString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n开:%@ 高:%@ 低:%@ 收:%@", [ChartCalculateUtils notRounding:chartData.opened afterPoint:digitCount], [ChartCalculateUtils notRounding:chartData.highest afterPoint:digitCount] ,[ChartCalculateUtils notRounding:chartData.lowest afterPoint:digitCount],[ChartCalculateUtils notRounding:chartData.closed afterPoint:digitCount]] attributes:@{NSForegroundColorAttributeName:profileColor, NSFontAttributeName:_titleFont}];
- /// 横屏一排显示就够了
- if (self.frame.size.width < self.frame.size.height) {
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, 12.0f)];
- } else {
- [MAString appendAttributedString:tipString];
- }
- [MAString drawAtPoint:CGPointMake(_kLineOrigin.x, 0)];
-
- /// 纵轴时间
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- dateFormatter.dateFormat = @"MM-dd HH:mm";
- NSString *dateTime = [dateFormatter stringFromDate:chartData.startTime];
- CGSize dateTimeSize = [dateTime sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGFloat x = currentXPoint+_kLineWidth/2-dateTimeSize.width/2;
- if (x < _xAxisPaddingLeft)
- x = _xAxisPaddingLeft;
- else if (x > _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width)
- x = _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width;
- CGContextAddRect(context, CGRectMake(x, _kLineOrigin.y, dateTimeSize.width, dateTimeSize.height));
- CGContextFillPath(context);
- [_tipTitleColor set];
- [dateTime drawAtPoint:CGPointMake(x, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
- /// 横轴价格
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSDecimalNumber *yPrice = [self priceWithYPoint:_tipLineYAxis];
- NSString *priceString = [ChartCalculateUtils notRounding:yPrice afterPoint:decimalNumber];
- CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextAddRect(context, CGRectMake(priceXOffset, _tipLineYAxis-priceStringSize.height/2, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
- CGContextFillPath(context);
- [_tipTitleColor set];
- [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, _tipLineYAxis-priceStringSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
-
- break;
- }
- }
-
- currentXPoint += _xAxisWidth/_kLineCount;
- }
- }
- #pragma mark - MACD指标相关
- /**
- * @brief 初始化MACD的可视化的最大值和最小值的方法
- */
- - (void)initMACDData {
- //可视MACD最大值与最小值
- _indicatorMaxValue = [[self maxMACDValueAtVisible] floatValue];
- _indicatorMinValue = [[self minMACDValueAtVisible] floatValue];
- }
- /**
- * @brief 画MACD指标的方法
- */
- - (void)drawMACD {
- if ( isnan([self yMACDPointWithValue:[NSDecimalNumber zero]]))
- return;
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- /// 画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; /// 价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; /// 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _indicatorOrigin.x, [self yMACDPointWithValue:[NSDecimalNumber zero]]);
- CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yMACDPointWithValue:[NSDecimalNumber zero]]);
- CGContextStrokePath(context);
- CGSize zeroTitleSize = [@"0" sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
- [_titleColor set];
-
- [@"0" drawAtPoint:CGPointMake(priceXOffset, [self yMACDPointWithValue:[NSDecimalNumber zero]]-zeroTitleSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- /// 最大与最小值标题
- NSString *maxString = [ChartCalculateUtils notRounding:[self maxMACDValueAtVisible] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [maxString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, _indicatorOrigin.y - _indicatorHight) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *minString = [ChartCalculateUtils notRounding:[self minMACDValueAtVisible] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];//负数
- [minString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, _indicatorOrigin.y - [minString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- /// MACD标题
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- /// 画MACD柱
- currentXPonit = _kLineOrigin.x + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (chartData.macd) {
- if ([chartData.macd compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
- //close < open
- CGContextSetRGBFillColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
- CGContextAddRect(context, CGRectMake(currentXPonit, [self yMACDPointWithValue:[NSDecimalNumber zero]], _kLineWidth, [self yMACDPointWithValue:chartData.macd] - [self yMACDPointWithValue:[NSDecimalNumber zero]]));
- CGContextFillPath(context);
- }
- else if ([chartData.macd compare:[NSDecimalNumber zero]] == NSOrderedDescending) {
- //close < open
- CGContextSetRGBFillColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
- CGContextAddRect(context, CGRectMake(currentXPonit, [self yMACDPointWithValue:[NSDecimalNumber zero]], _kLineWidth, [self yMACDPointWithValue:chartData.macd] - [self yMACDPointWithValue:[NSDecimalNumber zero]]));
- CGContextFillPath(context);
- }
- }
-
- currentXPonit += _kLineWidth + _kLinePadding;
- }
-
- //画DIF线
- CGContextSetRGBStrokeColor(context, _macdDIFRed, _macdDIFGreen, _macdDIFBlue, _macdDIFAlpha);
- CGFloat currentXPoint = _kLineOrigin.x + 1.0f;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.dif) {
- //前25条数据
- } else if (chartData.dif && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dif]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dif]);
- CGContextMoveToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dif]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画DEA线
- CGContextSetRGBStrokeColor(context, _macdDEARed, _macdDEAGreen, _macdDEABlue, _macdDEAAlpha);
- currentXPoint = _kLineOrigin.x + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.dea) {
- //前34条数据
- } else if (chartData.dea && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dea]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dea]);
- CGContextMoveToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dea]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yMACDPointWithValue:[self maxMACDValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yMACDPointWithValue:[self minMACDValueAtVisible]]);
- CGContextStrokePath(context);
-
- //写数据
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"DIF:%@ ",[ChartCalculateUtils notRounding:chartData.dif afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_macdDIFRed green:_macdDIFGreen blue:_macdDIFBlue alpha:_macdDIFAlpha], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringTwo = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"DEA:%@ ",[ChartCalculateUtils notRounding:chartData.dea afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_macdDEARed green:_macdDEAGreen blue:_macdDEABlue alpha:_macdDEAAlpha], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringThree = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MACD:%@",[ChartCalculateUtils notRounding:chartData.macd afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_macdDEARed green:_macdDEAGreen blue:_macdDEABlue alpha:_macdDEAAlpha], NSFontAttributeName:_titleFont}];
- [tipString appendAttributedString:stringTwo];
- [tipString appendAttributedString:stringThree];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yMACDPointWithValue:[self maxMACDValueAtVisible]] - 12.0f)];
-
- break;
- }
- }
-
- currentXPonit += _kLineWidth + _kLinePadding;
- }
- }
- #pragma mark - VOL指标相关
- /**
- * @brief 初始化VOL指标可视区数据
- */
- - (void)initVOLData {
- //获取KDJ可视区最大值与最小值
- _indicatorVOLMaxValue = [[self maxVOLValueAtVisible] floatValue];
- _indicatorVOLMiniValue = [[self miniVOLValueAtVisible] floatValue];
- }
- /**
- * @brief 画VOL指标的方法
- */
- - (void)drawVOL {
- if (isnan([self yVOLPointWithValue:[NSDecimalNumber zero]])) {
- return;
- }
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _indicatorOrigin.x, [self yVOLPointWithValue:[NSDecimalNumber zero]]);
- CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yVOLPointWithValue:[NSDecimalNumber zero]]);
- CGContextStrokePath(context);
- [_titleColor set];
-
- //最大与最小值标题
- NSString *maxString = [ChartCalculateUtils notRounding:[self maxVOLValueAtVisible] afterPoint:[ChartCalculateUtils getDecimalDigits:self.numMinUnit]];
- [maxString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, _indicatorOrigin.y - _indicatorHight) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *minString = [ChartCalculateUtils notRounding:[self miniVOLValueAtVisible] afterPoint:[ChartCalculateUtils getDecimalDigits:self.numMinUnit]];//负数
- [minString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, _indicatorOrigin.y - [minString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- //画VOL柱
- currentXPonit = _kLineOrigin.x + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (chartData.totleVolume) {
- if ([chartData.macd compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
- //close < open
- CGContextSetRGBFillColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
- CGContextAddRect(context, CGRectMake(currentXPonit, [self yVOLPointWithValue:[NSDecimalNumber zero]], _kLineWidth, [self yVOLPointWithValue:chartData.totleVolume] - [self yVOLPointWithValue:[self miniVOLValueAtVisible]]));
- CGContextFillPath(context);
- }
- else if ([chartData.macd compare:[NSDecimalNumber zero]] != NSOrderedAscending) {
- CGContextSetRGBFillColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
- CGContextAddRect(context, CGRectMake(currentXPonit, [self yVOLPointWithValue:[NSDecimalNumber zero]], _kLineWidth, [self yVOLPointWithValue:chartData.totleVolume] - [self yVOLPointWithValue:[self miniVOLValueAtVisible]]));
- CGContextFillPath(context);
- }
- }
- currentXPonit += _kLineWidth + _kLinePadding;
- }
-
- //画vol5线
- CGContextSetRGBStrokeColor(context, _macdDIFRed, _macdDIFGreen, _macdDIFBlue, _macdDIFAlpha);
- CGFloat currentXPoint = _kLineOrigin.x + 1.0f;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.vol5) {
- //前5条数据
- } else if (chartData.vol10 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol5]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol5]);
- CGContextMoveToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol5]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画vol10线
- CGContextSetRGBStrokeColor(context, _macdDEARed, _macdDEAGreen, _macdDEABlue, _macdDEAAlpha);
- currentXPoint = _kLineOrigin.x + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
-
- if (!chartData.vol10) {
- //前10条数据
- } else if (chartData.vol10 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol10]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol10]);
- CGContextMoveToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol10]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yVOLPointWithValue:[self maxVOLValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yVOLPointWithValue:[self miniVOLValueAtVisible]]);
- CGContextStrokePath(context);
-
- //写数据
- NSString *volume = [ChartCalculateUtils notRounding:chartData.totleVolume afterPoint:2];
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"VOLUME:%@ ",volume ? volume : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:_aesKAlpha], NSFontAttributeName:_titleFont}];
- NSString *vol5 = [ChartCalculateUtils notRounding:chartData.vol5 afterPoint:2];
- NSAttributedString *stringTwo = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@ ", vol5 ? vol5 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_macdDIFRed green:_macdDIFGreen blue:_macdDIFBlue alpha:_macdDIFAlpha], NSFontAttributeName:_titleFont}];
- NSString *vol10 = [ChartCalculateUtils notRounding:chartData.vol10 afterPoint:2];
- NSAttributedString *stringThree = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@", vol10 ? vol10 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_macdDEARed green:_macdDEAGreen blue:_macdDEABlue alpha:_macdDEAAlpha], NSFontAttributeName:_titleFont}];
- [tipString appendAttributedString:stringTwo];
- [tipString appendAttributedString:stringThree];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yVOLPointWithValue:[self maxVOLValueAtVisible]] - 12.0f)];
-
- break;
- }
- }
-
- currentXPonit += _kLineWidth + _kLinePadding;
- }
- }
- #pragma mark - KDJ指标相关
- /**
- * @brief 初始化KDJ指标可视区数据
- */
- - (void)initKDJData {
- //获取KDJ可视区最大值与最小值
- _indicatorKDJMaxValue = [[self maxKDJValueAtVisible] floatValue];
- _indicatorKDJMiniValue = [[self miniKDJValueAtVisible] floatValue];
- }
- /**
- * @brief 画KDJ指标的方法
- */
- - (void)drawKDJ {
- if (isnan([self yKDJPointWithValue:[NSDecimalNumber zero]])) {
- return;
- }
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
-
- [_titleColor set];
-
- //上下区间值 20、80
- NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"80"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *downString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"20"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //RSI标题
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- //画80线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
- CGContextStrokePath(context);
-
- //画20线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
- CGContextStrokePath(context);
-
- //画kt线
- CGContextSetRGBStrokeColor(context, _ktRed, _ktGreen, _ktBlue, _ktAlpha);
- CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.kt) {
- //前9根没有
- } else if (chartData.kt && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画dt线
- CGContextSetRGBStrokeColor(context, _dtRed, _dtGreen, _dtBlue, _dtAlpha);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.dt) {
- //前9根没有
- } else if (chartData.dt && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画jt线
- CGContextSetRGBStrokeColor(context, _jtRed, _jtGreen, _jtBlue, _jtAlpha);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.jt) {
- //前9根没有
- } else if (chartData.jt && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.jt]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.jt]);
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.jt]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, [self yKDJPointWithValue:[self maxKDJValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit, [self yKDJPointWithValue:[self miniKDJValueAtVisible]]);
- CGContextStrokePath(context);
-
- //写数据
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"K:%@ ",[ChartCalculateUtils notRounding:chartData.kt afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_ktRed green:_ktGreen blue:_ktBlue alpha:_ktAlpha], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringTwo = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"D:%@ ",[ChartCalculateUtils notRounding:chartData.dt afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_dtRed green:_dtGreen blue:_dtBlue alpha:_dtBlue], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringThree = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"J:%@",[ChartCalculateUtils notRounding:chartData.jt afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_jtRed green:_jtGreen blue:_jtBlue alpha:_jtAlpha], NSFontAttributeName:_titleFont}];
- [tipString appendAttributedString:stringTwo];
- [tipString appendAttributedString:stringThree];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yKDJPointWithValue:[self maxKDJValueAtVisible]] - 12.0f)];
-
- break;
- }
- }
-
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- }
- #pragma mark - KD指标相关
- /**
- * @brief 画KD指标的方法
- */
- - (void)drawKD {
- if (isnan([self yKDJPointWithValue:[NSDecimalNumber zero]])) return;
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
-
- [_titleColor set];
-
- //上下区间值 20、80
- NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"80"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *downString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"20"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //RSI标题
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- //画80线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
- CGContextStrokePath(context);
-
- //画20线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
- CGContextStrokePath(context);
-
- //画kt线
- CGContextSetRGBStrokeColor(context, _ktRed, _ktGreen, _ktBlue, _ktAlpha);
- CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.kt) {
- //前9根没有
- } else if (chartData.kt && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画dt线
- CGContextSetRGBStrokeColor(context, _dtRed, _dtGreen, _dtBlue, _dtBlue);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.dt) {
- //前9根没有
- } else if (chartData.dt && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
- CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, [self yKDJPointWithValue:[self maxKDJValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit, [self yKDJPointWithValue:[self miniKDJValueAtVisible]]);
- CGContextStrokePath(context);
-
- //写数据
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"K:%@ ",[ChartCalculateUtils notRounding:chartData.kt afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_ktRed green:_ktGreen blue:_ktBlue alpha:_ktAlpha], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringTwo = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"D:%@",[ChartCalculateUtils notRounding:chartData.dt afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_dtRed green:_dtGreen blue:_dtBlue alpha:_dtBlue], NSFontAttributeName:_titleFont}];
- [tipString appendAttributedString:stringTwo];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yKDJPointWithValue:[self maxKDJValueAtVisible]] - 12.0f)];
-
- break;
- }
- }
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- }
- #pragma mark - RSI指标相关
- /**
- * @brief 初始化RSI指标可视区数据
- */
- - (void)initRSIData {
- //获取RSI可视区最大值与最小值
- _indicatorRSIMaxValue = [[self maxRSIValueAtVisible] floatValue];
- _indicatorRSIMiniValue = [[self miniRSIValueAtVisible] floatValue];
- }
- /**
- * @brief 画RSI指标的方法
- */
- - (void)drawRSI {
- if (isnan([self yRSIPointWithValue:[NSDecimalNumber zero]])) return;
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _indicatorOrigin.x, [self yRSIPointWithValue:[NSDecimalNumber zero]]);
- CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yRSIPointWithValue:[NSDecimalNumber zero]]);
- CGContextStrokePath(context);
-
- [_titleColor set];
-
- //上下区间值 20、80
- NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"80"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *downString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"20"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //RSI标题
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- //画80线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
- CGContextStrokePath(context);
-
- //画20线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
- CGContextStrokePath(context);
-
- //画RSI1线
- CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
- CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.rsi1) {
- //前6根没有
- } else if (chartData.rsi1 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi1]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi1]);
- CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi1]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画RSI2线
- CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.rsi2) {
- //前12根没有
- } else if (chartData.rsi2 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi2]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi2]);
- CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi2]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画RSI3线
- CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.rsi3) {
- //前24根没有
- } else if (chartData.rsi3 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi3]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi3]);
- CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi3]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, [self yRSIPointWithValue:[self maxRSIValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit, [self yRSIPointWithValue:[self miniRSIValueAtVisible]]);
- CGContextStrokePath(context);
-
- //写数据
- NSString *tipString = [NSString stringWithFormat:@"RSI1:%@ RSI2:%@ RSI3:%@"
- ,[ChartCalculateUtils notRounding:chartData.rsi1 afterPoint:2]
- ,[ChartCalculateUtils notRounding:chartData.rsi2 afterPoint:2]
- ,[ChartCalculateUtils notRounding:chartData.rsi3 afterPoint:2]
- ];
- UIColor *profileColor = nil;
- if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
- profileColor = [UIColor redColor];
- else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
- profileColor = _priceGreenColor;
- else
- profileColor = _titleColor;
- [profileColor set];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yRSIPointWithValue:[self maxRSIValueAtVisible]] - 12.0f) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- break;
- }
- }
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- }
- #pragma mark - CCI指标相关
- /**
- * @brief 初始化CCI指标可视区数据
- */
- - (void)initCCIData {
- //获取RSI可视区最大值与最小值
- _indicatorCCIMaxValue = [[self maxCCIValueAtVisible] floatValue];
- _indicatorCCIMiniValue = [[self miniCCIValueAtVisible] floatValue];
- }
- /**
- * @brief 画CCI指标的方法
- */
- - (void)drawCCI {
- if (isnan([self yCCIPointWithValue:[NSDecimalNumber zero]])) return;
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _indicatorOrigin.x, [self yCCIPointWithValue:[NSDecimalNumber zero]]);
- CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yCCIPointWithValue:[NSDecimalNumber zero]]);
- CGContextStrokePath(context);
-
- [_titleColor set];
-
- //上中下区间值 100、0、-100
- NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"100"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"100"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *midString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"0"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [midString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"0"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *downString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"-100"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"-100"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //CCI标题
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- //画0线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"0"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"0"]]);
- CGContextStrokePath(context);
-
- //画100线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"100"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"100"]]);
- CGContextStrokePath(context);
-
- //画-100线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"-100"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"-100"]]);
- CGContextStrokePath(context);
-
- //画CCI线
- CGContextSetRGBStrokeColor(context, _cciRed, _cciGreen, _cciBlue, _cciAlpha);
- CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f; BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.cci) {
- //前14根没有
- } else if (chartData.cci && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yCCIPointWithValue:chartData.cci]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yCCIPointWithValue:chartData.cci]);
- CGContextMoveToPoint(context, currentXPoint, [self yCCIPointWithValue:chartData.cci]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, [self yCCIPointWithValue:[self maxCCIValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit, [self yCCIPointWithValue:[self miniCCIValueAtVisible]]);
- CGContextStrokePath(context);
-
- if (chartData.cci) {
- //写数据
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"CCI:%@",[ChartCalculateUtils notRounding:chartData.cci afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_cciRed green:_cciGreen blue:_cciBlue alpha:_cciAlpha], NSFontAttributeName:_titleFont}];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yCCIPointWithValue:[self maxCCIValueAtVisible]] - 12.0f)];
- }
-
- break;
- }
- }
-
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- }
- #pragma mark - DMA指标相关
- /**
- * @brief 初始化DMA指标可视区数据
- */
- - (void)initDMAData {
- //获取DMA可视区最大值与最小值
- _indicatorDMAMaxValue = [[self maxDMAValueAtVisible] floatValue];
- _indicatorDMAMiniValue = [[self miniDMAValueAtVisible] floatValue];
- }
- /**
- * @brief 画DMA指标的方法
- */
- - (void)drawDMA {
- if (isnan([self yDMAPointWithValue:[NSDecimalNumber zero]])) return;
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _indicatorOrigin.x, [self yDMAPointWithValue:[NSDecimalNumber zero]]);
- CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yDMAPointWithValue:[NSDecimalNumber zero]]);
- CGContextStrokePath(context);
-
- [_titleColor set];
-
- NSDecimalNumber *maxValue = [self maxDMAValueAtVisible];
- NSDecimalNumber *miniValue = [self miniDMAValueAtVisible];
- NSDecimalNumber *midValue = [[miniValue decimalNumberByAdding:maxValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]];
-
- NSString *upString = [ChartCalculateUtils notRounding:maxValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yDMAPointWithValue:maxValue]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *midString = [ChartCalculateUtils notRounding:midValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [midString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yDMAPointWithValue:midValue]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *downString = [ChartCalculateUtils notRounding:miniValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yDMAPointWithValue:miniValue] - 8.0f) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- //画1线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yDMAPointWithValue:maxValue]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yDMAPointWithValue:maxValue]);
- CGContextStrokePath(context);
-
- //画-1线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yDMAPointWithValue:midValue]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yDMAPointWithValue:midValue]);
- CGContextStrokePath(context);
-
- //画-2线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yDMAPointWithValue:miniValue]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yDMAPointWithValue:miniValue]);
- CGContextStrokePath(context);
-
- //画DMA线
- CGContextSetRGBStrokeColor(context, _dmaRed, _dmaGreen, _dmaBlue, _dmaAlpha);
- CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.dma) {
- //前10根没有
- } else if (chartData.dma && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.dma]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.dma]);
- CGContextMoveToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.dma]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画AMA线
- CGContextSetRGBStrokeColor(context, _amaRed, _amaGreen, _amaBlue, _amaAlpha);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.ama) {
- //前10根没有
- } else if (chartData.ama && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.ama]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.ama]);
- CGContextMoveToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.ama]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, [self yDMAPointWithValue:[self maxDMAValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit, [self yDMAPointWithValue:[self miniDMAValueAtVisible]]);
- CGContextStrokePath(context);
-
- //写数据
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"DIF:%@ ",[ChartCalculateUtils notRounding:chartData.dma afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_dmaRed green:_dmaGreen blue:_dmaBlue alpha:_dmaAlpha], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringTwo = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"AMA:%@",[ChartCalculateUtils notRounding:chartData.ama afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_amaRed green:_amaGreen blue:_amaBlue alpha:_amaAlpha], NSFontAttributeName:_titleFont}];
- [tipString appendAttributedString:stringTwo];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yDMAPointWithValue:[self maxDMAValueAtVisible]] - 12.0f)];
-
- break;
- }
- }
-
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- }
- #pragma mark - BIAS指标相关
- /**
- * @brief 初始化BIAS指标可视区数据
- */
- - (void)initBIASData {
- //获取BIAS可视区最大值与最小值
- _indicatorBIASMaxValue = [[self maxBIASValueAtVisible] floatValue];
- _indicatorBIASMiniValue = [[self miniBIASValueAtVisible] floatValue];
- }
- /**
- * @brief 画DMA指标的方法
- */
- - (void)drawBIAS {
- if (isnan([self yBIASPointWithValue:[NSDecimalNumber zero]])) return;
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _indicatorOrigin.x, [self yBIASPointWithValue:[NSDecimalNumber zero]]);
- CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yBIASPointWithValue:[NSDecimalNumber zero]]);
- CGContextStrokePath(context);
-
- [_titleColor set];
-
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- NSDecimalNumber *maxValue = [self maxBIASValueAtVisible];
- NSDecimalNumber *miniValue = [self miniBIASValueAtVisible];
- NSDecimalNumber *midValue = [[miniValue decimalNumberByAdding:maxValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]];
-
- NSString *upString = [ChartCalculateUtils notRounding:maxValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yBIASPointWithValue:maxValue]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
- NSString *midString = [ChartCalculateUtils notRounding:midValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [midString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yBIASPointWithValue:midValue]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //画1线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yBIASPointWithValue:maxValue]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yBIASPointWithValue:maxValue]);
- CGContextStrokePath(context);
-
- //画-1线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yBIASPointWithValue:midValue]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yBIASPointWithValue:midValue]);
- CGContextStrokePath(context);
-
- //画BIAS1线
- CGContextSetRGBStrokeColor(context, _bias1Red, _bias1Green, _bias1Blue, _bias1Alpha);
- CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.bias1) {
- //前6根没有
- } else if (chartData.bias1 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias1]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias1]);
- CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias1]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画BIAS2线
- CGContextSetRGBStrokeColor(context, _bias2Red, _bias2Green, _bias2Blue, _bias2Alpha);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.bias2) {
- //前12根没有
- } else if (chartData.bias2 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias2]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias2]);
- CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias2]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画BIAS3线
- CGContextSetRGBStrokeColor(context, _bias3Red, _bias3Green, _bias3Blue, _bias3Alpha);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.bias3) {
- //前24根没有
- } else if (chartData.bias3 && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias3]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias3]);
- CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias3]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, [self yBIASPointWithValue:[self maxBIASValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit, [self yBIASPointWithValue:[self miniBIASValueAtVisible]]);
- CGContextStrokePath(context);
-
- //写数据
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"BIAS1:%@ ",[ChartCalculateUtils notRounding:chartData.bias1 afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_bias1Red green:_bias1Green blue:_bias1Blue alpha:_bias1Alpha], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringTwo = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"BIAS2:%@ ",[ChartCalculateUtils notRounding:chartData.bias2 afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_bias2Red green:_bias2Green blue:_bias2Blue alpha:_bias2Alpha], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringThree = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"BIAS2:%@",[ChartCalculateUtils notRounding:chartData.bias3 afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_bias3Red green:_bias3Green blue:_bias3Blue alpha:_bias3Alpha], NSFontAttributeName:_titleFont}];
- [tipString appendAttributedString:stringTwo];
- [tipString appendAttributedString:stringThree];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yBIASPointWithValue:[self maxBIASValueAtVisible]] - 12.0f)];
-
- break;
- }
- }
-
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- }
- #pragma mark - PSY指标相关
- /**
- * @brief 初始化PSY指标可视区数据
- */
- - (void)initPSYData {
- //获取BIAS可视区最大值与最小值
- _indicatorPSYMaxValue = [[self maxPSYValueAtVisible] floatValue];
- _indicatorPSYMiniValue = [[self miniPSYValueAtVisible] floatValue];
- }
- /**
- * @brief 画PSY指标的方法
- */
- - (void)drawPSY {
- if (isnan([self yPSYPointWithValue:[NSDecimalNumber zero]])) return;
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(context, 1.0f);
-
- //画0线与标题
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _indicatorOrigin.x, [self yPSYPointWithValue:[NSDecimalNumber zero]]);
- CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yPSYPointWithValue:[NSDecimalNumber zero]]);
- CGContextStrokePath(context);
-
- [_titleColor set];
-
- CGFloat currentXPonit = _indicatorOrigin.x;
-
- NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"50"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
- [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPSYPointWithValue:[NSDecimalNumber decimalNumberWithString:@"50"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- //画50线
- [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPSYPointWithValue:[NSDecimalNumber decimalNumberWithString:@"50"]]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yPSYPointWithValue:[NSDecimalNumber decimalNumberWithString:@"50"]]);
- CGContextStrokePath(context);
-
- //画PSY线
- CGContextSetRGBStrokeColor(context, _psyRed, _psyGreen, _psyBlue, _psyAlpha);
- CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- BOOL isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.psy) {
- //前12根没有
- } else if (chartData.psy && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psy]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psy]);
- CGContextMoveToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psy]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- //画PSYMA线
- CGContextSetRGBStrokeColor(context, _psymaRed, _psymaGreen, _psymaBlue, _psymaAlpha);
- currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- isInit = NO;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (!chartData.psyma) {
- //前6根没有
- } else if (chartData.psyma && !isInit) {
- CGContextMoveToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psyma]);
- isInit = YES;
- } else {
- CGContextAddLineToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psyma]);
- CGContextMoveToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psyma]);
- }
-
- currentXPoint += _kLineWidth + _kLinePadding;
- }
- CGContextStrokePath(context);
-
- currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
- for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- //是否需要显示十字线
- if (_isShowTipLine) {
- if (_tipLineIndex == i) {
- //画垂直线
- CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
- CGContextSetLineWidth(context, 1.0f);
- CGContextMoveToPoint(context, currentXPonit, [self yPSYPointWithValue:[self maxPSYValueAtVisible]]);
- CGContextAddLineToPoint(context, currentXPonit, [self yPSYPointWithValue:[self miniPSYValueAtVisible]]);
- CGContextStrokePath(context);
-
- //写数据
- NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"PSY:%@ ",[ChartCalculateUtils notRounding:chartData.psy afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_psyRed green:_psyGreen blue:_psyBlue alpha:_psyAlpha], NSFontAttributeName:_titleFont}];
- NSAttributedString *stringTwo = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"PSYMA:%@",[ChartCalculateUtils notRounding:chartData.psyma afterPoint:2]] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_psymaRed green:_psymaGreen blue:_psymaBlue alpha:_psymaAlpha], NSFontAttributeName:_titleFont}];
- [tipString appendAttributedString:stringTwo];
- [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yPSYPointWithValue:[self maxPSYValueAtVisible]] - 12.0f)];
-
- break;
- }
- }
- currentXPonit += _xAxisWidth/_kLineCount;
- }
- }
- #pragma mark - 画现价相关
- /**
- * @brief 画现价的方法
- */
- - (void)drawPrice {
- if (!_isShowPrice) return;
-
- CGContextRef context = UIGraphicsGetCurrentContext();
-
- //横轴价格
- CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
- NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
- NSString *priceString = [ChartCalculateUtils notRounding:_price afterPoint:decimalNumber];
- CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
-
- //最大最小值判断
- CGFloat priceYOffset = [self yPointWithPrice:_price]-priceStringSize.height/2;
- NSDecimalNumber *max = [self maxPriceAtVisible];
- NSDecimalNumber *min = [self minPriceAtVisible];
-
- // 这里有可能最大值和最小值相等
- if ([max compare:min] == NSOrderedSame) {
- ChartData *chartData = _chartDataArray[0];
- max = [chartData.closed decimalNumberByAdding:[_minUnit decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInt:20]]];
- }
-
- if ([_price compare:max] == NSOrderedDescending) priceYOffset = _yAxisPaddingTop - priceStringSize.height;
- if ([_price compare:min] == NSOrderedAscending) priceYOffset = _kLineOrigin.y;
-
- if (priceYOffset != NAN) {
- CGContextSetRGBFillColor(context, 1.0f, 1.0f, 0.0f, 0.5f);
- CGContextAddRect(context, CGRectMake(priceXOffset, priceYOffset, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
- CGContextFillPath(context);
-
- [[UIColor blackColor] set];
- [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, priceYOffset) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
-
- CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
- //画100线
- [[UIColor grayColor] getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
- CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:_price]);
- CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yPointWithPrice:_price]);
- CGFloat arr[] = {3, 1};
- //下面最后一个参数“2”代表排列的个数。
- CGContextSetLineDash(context, 0, arr, 2);
- //画线
- CGContextDrawPath(context, kCGPathStroke);
- }
- }
- #pragma mark - K线数值计算相关
- /**
- * @brief 获取当前可视区K线最大价格值的方法
- *
- * @return 当前可视区K线最大价格值
- */
- - (nullable NSDecimalNumber *)maxPriceAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
- NSDecimalNumber *maxValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if ([chartData.opened compare:maxValue] == NSOrderedDescending) maxValue = chartData.opened;
- if ([chartData.closed compare:maxValue] == NSOrderedDescending) maxValue = chartData.closed;
- if ([chartData.highest compare:maxValue] == NSOrderedDescending) maxValue = chartData.highest;
- if (chartData.ma5) {
- if ([chartData.ma5 compare:maxValue] == NSOrderedDescending) maxValue = chartData.ma5;
- }
- if (chartData.ma10) {
- if ([chartData.ma10 compare:maxValue] == NSOrderedDescending) maxValue = chartData.ma10;
- }
- if (chartData.ma15) {
- if ([chartData.ma15 compare:maxValue] == NSOrderedDescending) maxValue = chartData.ma15;
- }
- }
-
- return maxValue ? maxValue : [NSDecimalNumber zero];
- }
- /**
- * @brief 获取当前可视区K线最小价格值的方法
- *
- * @return 当前可视区K线最小价格值
- */
- - (nullable NSDecimalNumber *)minPriceAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
- NSDecimalNumber *minValue = [NSDecimalNumber maximumDecimalNumber];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if ([chartData.opened compare:minValue] == NSOrderedAscending) minValue = chartData.opened;
- if ([chartData.closed compare:minValue] == NSOrderedAscending) minValue = chartData.closed;
- if ([chartData.lowest compare:minValue] == NSOrderedAscending) minValue = chartData.lowest;
- if (chartData.ma5) {
- if ([chartData.ma5 compare:minValue] == NSOrderedAscending) minValue = chartData.ma5;
- }
- if (chartData.ma10) {
- if ([chartData.ma10 compare:minValue] == NSOrderedAscending) minValue = chartData.ma10;
- }
- if (chartData.ma15) {
- if ([chartData.ma15 compare:minValue] == NSOrderedAscending) minValue = chartData.ma15;
- }
- }
-
- return minValue ? minValue : [NSDecimalNumber zero];
- }
- /**
- * @brief 获取指定价格的K线Y轴坐标
- *
- * @param price 目标价格
- *
- * @return 指定价格的K线Y轴坐标
- */
- - (CGFloat)yPointWithPrice:(nullable NSDecimalNumber *)price {
- CGFloat yPoint = _yAxisHeight - (_yAxisHeight/(_yAxisMaxValue - _yAxisMinValue)) * ([price floatValue] - _yAxisMinValue) + _yAxisPaddingTop;
- return yPoint ;
- }
- /**
- * @brief 获取指定Y轴坐标的价格
- *
- * @param yPoint 目标Y轴坐标
- *
- * @return 指定Y轴坐标的价格
- */
- - (nullable NSDecimalNumber *)priceWithYPoint:(CGFloat)yPoint {
- float priceValue = _yAxisMinValue + (_yAxisHeight + _yAxisPaddingTop - yPoint)/(_yAxisHeight/(_yAxisMaxValue - _yAxisMinValue));
- return [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",priceValue]];
- }
- #pragma mark - 整体指标相关
- /**
- * @brief 设置是否需要显示指标
- *
- * @param isShowIndicator 是否需要显示指标
- */
- - (void)setIsShowIndicator:(BOOL)isShowIndicator {
- _isShowIndicator = isShowIndicator;
- if (!_isShowIndicator) {
- _indicatorHight = 0;
- _indicatorPaddingBottom = 0;
- }
- }
- /// 是否显示开高低收
- /// @param isShowOHLP isShowOHLP
- - (void)setIsShowOHLP:(BOOL)isShowOHLP {
- _isShowOHLP = isShowOHLP;
- }
- #pragma mark - MACD数值计算相关
- /**
- * @brief 获取当前可视区MACD线最大值的方法
- *
- * @return 当前可视区MACD线最大值
- */
- - (nullable NSDecimalNumber *)maxMACDValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *maxValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.dif) {
- if ([chartData.dif compare:maxValue] == NSOrderedDescending) maxValue = chartData.dif;
- }
- if (chartData.dea) {
- if ([chartData.dea compare:maxValue] == NSOrderedDescending) maxValue = chartData.dea;
- }
- if (chartData.macd) {
- if ([chartData.macd compare:maxValue] == NSOrderedDescending) maxValue = chartData.macd;
- }
- }
-
- return maxValue;
- }
- /**
- * @brief 获取当前可视区MACD线最小值的方法
- *
- * @return 当前可视区MACD线最小值
- */
- - (nullable NSDecimalNumber *)minMACDValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *minValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.dif) {
- if ([chartData.dif compare:minValue] == NSOrderedAscending) minValue = chartData.dif;
- }
- if (chartData.dea) {
- if ([chartData.dea compare:minValue] == NSOrderedAscending) minValue = chartData.dea;
- }
- if (chartData.macd) {
- if ([chartData.macd compare:minValue] == NSOrderedAscending) minValue = chartData.macd;
- }
- }
-
- return minValue;
- }
- /**
- * @brief 获取指定值的MACD线Y轴坐标
- *
- * @param value 目标价格
- *
- * @return 指定值的MACD线Y轴坐标
- */
- - (CGFloat)yMACDPointWithValue:(nullable NSDecimalNumber *)value {
- CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorMaxValue - _indicatorMinValue)) * ([value floatValue] - _indicatorMinValue) + _kLineOrigin.y + _yAxisPaddingBottom;
- return yPoitn;
- }
- #pragma mark - VOL数值计算相关
- /**
- * @brief 获取当前可视区VOL线最大值的方法
- *
- * @return 当前可视区VOL线最大值
- */
- - (nullable NSDecimalNumber *)maxVOLValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *maxValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.totleVolume) {
- if ([chartData.totleVolume compare:maxValue] == NSOrderedDescending) maxValue = chartData.totleVolume;
- }
- }
-
- return maxValue;
- }
- /**
- * @brief 获取当前可视区VOL线最大值的方法
- *
- * @return 当前可视区VOL线最大值
- */
- - (nullable NSDecimalNumber *)miniVOLValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *minValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.totleVolume) {
- if ([chartData.totleVolume compare:minValue] != NSOrderedDescending) minValue = chartData.totleVolume;
- }
- }
-
- return minValue;
- }
- /**
- * @brief 获取指定值的VOL线Y轴坐标
- *
- * @param value 目标价格
- *
- * @return 指定值的VOL线Y轴坐标
- */
- - (CGFloat)yVOLPointWithValue:(nullable NSDecimalNumber *)value {
- CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorVOLMaxValue - _indicatorVOLMiniValue)) * ([value floatValue] - _indicatorVOLMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
- return yPoitn;
- }
- #pragma mark - KDJ数值计算相关
- /**
- * @brief 获取当前可视区KDJ线最大值的方法
- *
- * @return 当前可视区KDJ线最大值
- */
- - (nullable NSDecimalNumber *)maxKDJValueAtVisible {
- return [NSDecimalNumber decimalNumberWithString:@"130"];
- }
- /**
- * @brief 获取当前可视区KDJ线最小值的方法
- *
- * @return 当前可视区KDJ线最小值
- */
- - (nullable NSDecimalNumber *)miniKDJValueAtVisible {
- return [NSDecimalNumber decimalNumberWithString:@"-30"];
- }
- /**
- * @brief 获取指定值的KDJ线Y轴坐标
- *
- * @param value 目标价格
- *
- * @return 指定值的KDJ线Y轴坐标
- */
- - (CGFloat)yKDJPointWithValue:(nullable NSDecimalNumber *)value {
- CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorKDJMaxValue - _indicatorKDJMiniValue)) * ([value floatValue] - _indicatorKDJMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
- return yPoitn;
- }
- #pragma mark - RSI数值计算相关
- /**
- * @brief 获取当前可视区RSI线最大值的方法
- *
- * @return 当前可视区RSI线最大值
- */
- - (nullable NSDecimalNumber *)maxRSIValueAtVisible {
- return [NSDecimalNumber decimalNumberWithString:@"100"];
- }
- /**
- * @brief 获取当前可视区RSI线最小值的方法
- *
- * @return 当前可视区RSI线最小值
- */
- - (nullable NSDecimalNumber *)miniRSIValueAtVisible {
- return [NSDecimalNumber decimalNumberWithString:@"0"];
- }
- /**
- * @brief 获取指定值的RSI线Y轴坐标
- *
- * @param value 目标价格
- *
- * @return 指定值的RSI线Y轴坐标
- */
- - (CGFloat)yRSIPointWithValue:(NSDecimalNumber *)value {
- CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorRSIMaxValue - _indicatorRSIMiniValue)) * ([value floatValue] - _indicatorRSIMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
- return yPoitn;
- }
- #pragma mark - CCI数值计算相关
- /**
- * @brief 获取当前可视区CCI线最大值的方法
- *
- * @return 当前可视区CCI线最大值
- */
- - (nullable NSDecimalNumber *)maxCCIValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *maxValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.cci) {
- if ([chartData.cci compare:maxValue] == NSOrderedDescending) maxValue = chartData.cci;
- }
- }
-
- return maxValue;
- }
- /**
- * @brief 获取当前可视区CCI线最小值的方法
- *
- * @return 当前可视区CCI线最小值
- */
- - (nullable NSDecimalNumber *)miniCCIValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *minValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.cci) {
- if ([chartData.cci compare:minValue] != NSOrderedDescending) minValue = chartData.cci;
- }
- }
-
- return minValue;
- }
- /**
- * @brief 获取指定值的CCI线Y轴坐标
- *
- * @param value 目标价格
- *
- * @return 指定值的CCI线Y轴坐标
- */
- - (CGFloat)yCCIPointWithValue:(nullable NSDecimalNumber *)value {
- CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorCCIMaxValue - _indicatorCCIMiniValue)) * ([value floatValue] - _indicatorCCIMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
- return yPoitn;
- }
- #pragma mark - DMA数值计算相关
- /**
- * @brief 获取当前可视区DMA线最大值的方法
- *
- * @return 当前可视区DMA线最大值
- */
- - (nullable NSDecimalNumber *)maxDMAValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *maxValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.dma) {
- if ([chartData.dma compare:maxValue] == NSOrderedDescending) maxValue = chartData.dma;
- }
- if (chartData.ama) {
- if ([chartData.ama compare:maxValue] == NSOrderedDescending) maxValue = chartData.ama;
- }
- }
-
- return maxValue;
- }
- /**
- * @brief 获取当前可视区DMA线最小值的方法
- *
- * @return 当前可视区DMA线最小值
- */
- - (nullable NSDecimalNumber *)miniDMAValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *minValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.dma) {
- if ([chartData.dma compare:minValue] != NSOrderedDescending) minValue = chartData.dma;
- }
- if (chartData.ama) {
- if ([chartData.ama compare:minValue] != NSOrderedDescending) minValue = chartData.ama;
- }
- }
-
- return minValue;
- }
- /**
- * @brief 获取指定值的DMA线Y轴坐标
- *
- * @param value 目标价格
- *
- * @return 指定值的DMA线Y轴坐标
- */
- - (CGFloat)yDMAPointWithValue:(nullable NSDecimalNumber *)value {
- CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorDMAMaxValue - _indicatorDMAMiniValue)) * ([value floatValue] - _indicatorDMAMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
- return yPoitn;
- }
- #pragma mark - BIAS数值计算相关
- /**
- * @brief 获取当前可视区BIAS线最大值的方法
- *
- * @return 当前可视区BIAS线最大值
- */
- - (nullable NSDecimalNumber *)maxBIASValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *maxValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.bias1) {
- if ([chartData.bias1 compare:maxValue] == NSOrderedDescending) maxValue = chartData.bias1;
- }
- if (chartData.bias2) {
- if ([chartData.bias2 compare:maxValue] == NSOrderedDescending) maxValue = chartData.bias2;
- }
- if (chartData.bias3) {
- if ([chartData.bias3 compare:maxValue] == NSOrderedDescending) maxValue = chartData.bias3;
- }
- }
- return maxValue;
- }
- /**
- * @brief 获取当前可视区BIAS线最小值的方法
- *
- * @return 当前可视区BIAS线最小值
- */
- - (nullable NSDecimalNumber *)miniBIASValueAtVisible {
- if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
-
- NSDecimalNumber *minValue = [NSDecimalNumber zero];
- for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
- ChartData *chartData = [_chartDataArray objectAtIndex:i];
- if (chartData.bias1) {
- if ([chartData.bias1 compare:minValue] != NSOrderedDescending) minValue = chartData.bias1;
- }
- if (chartData.bias2) {
- if ([chartData.bias2 compare:minValue] != NSOrderedDescending) minValue = chartData.bias2;
- }
- if (chartData.bias3) {
- if ([chartData.bias3 compare:minValue] != NSOrderedDescending) minValue = chartData.bias3;
- }
- }
-
- return minValue;
- }
- /**
- * @brief 获取指定值的BIAS线Y轴坐标
- *
- * @param value 目标价格
- *
- * @return 指定值的BIAS线Y轴坐标
- */
- - (CGFloat)yBIASPointWithValue:(nullable NSDecimalNumber *)value {
- CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorBIASMaxValue - _indicatorBIASMiniValue)) * ([value floatValue] - _indicatorBIASMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
- return yPoitn;
- }
- #pragma mark - PSY数值计算相关
- /**
- * @brief 获取当前可视区PSY线最大值的方法
- *
- * @return 当前可视区PSY线最大值
- */
- - (NSDecimalNumber *)maxPSYValueAtVisible {
- return [NSDecimalNumber decimalNumberWithString:@"100"];
- }
- /**
- * @brief 获取当前可视区PSY线最小值的方法
- *
- * @return 当前可视区PSY线最小值
- */
- - (NSDecimalNumber *)miniPSYValueAtVisible {
- return [NSDecimalNumber decimalNumberWithString:@"0"];
- }
- /**
- * @brief 获取指定值的PSY线Y轴坐标
- *
- * @param value 目标价格
- *
- * @return 指定值的PSY线Y轴坐标
- */
- - (CGFloat)yPSYPointWithValue:(nullable NSDecimalNumber *)value {
- CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorPSYMaxValue - _indicatorPSYMiniValue)) * ([value floatValue] - _indicatorPSYMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
- return yPoitn;
- }
- #pragma mark - 分时图计算相关
- /**
- * @brief 获取两个时间之间的分钟数
- *
- * @param fromDate 开始时间
- * @param toDate 结束时间
- *
- * @return 分钟数
- */
- - (NSInteger)diffMinuteWithFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
- NSCalendar* chineseClendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
- NSUInteger unitFlags = NSCalendarUnitMinute;
-
- NSDateComponents *cps = [chineseClendar components:unitFlags fromDate:fromDate toDate:toDate options:0];
-
- return [cps minute]/(_cycleInterval/60); /// 使用5分钟线需要除以5得到多余区间
- }
- #pragma mark - 手势交互
- /**
- * @brief 初始化和图标进行交互的相关手势
- */
- - (void)initGestureRecognizer {
- /// 拖动手势
- UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onPanGesture:)];
- panGestureRecognizer.minimumNumberOfTouches = 1;
- panGestureRecognizer.maximumNumberOfTouches = 1;
- [self addGestureRecognizer:panGestureRecognizer];
-
- /// 捏合手势
- UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onPinchGesture:)];
- [self addGestureRecognizer:pinchGestureRecognizer];
-
- /// 长按手势
- UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)];
- longPressGestureRecognizer.delegate = self;
- [self addGestureRecognizer:longPressGestureRecognizer];
- }
- /**
- * @brief 移动手势进行移动时执行的方法
- */
- - (void)onPanGesture:(id)sender {
- UIPanGestureRecognizer *panGestureRecognizer = (UIPanGestureRecognizer *)sender;
- if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) {/// 拖动手势手势开始
- CGPoint point = [panGestureRecognizer locationInView:self];
- _startTouchPosition = point;
- } else if (panGestureRecognizer.state == UIGestureRecognizerStateChanged){/// 拖动手势进行移动
- if (!_isShowTipLine) {
- /// 移动K线
- /// 如果当前是分时图则什么都不做
- if (_chartViewType == ChartViewTypeTSPlan && !self.isBBGoods) return;
-
- /// Warnning:这里取translationInView可能有问题
- CGPoint point = [panGestureRecognizer locationInView:self];
-
- if (_startTouchPosition.x < point.x) {
- /// 向右滑
- if (_kLineStartIndex == _chartDataArray.count-1) return;
-
- _startTouchPosition.x = point.x;
- if (_kLineStartIndex+_panGestureIncrement <= _chartDataArray.count-1) {
- _kLineStartIndex += _panGestureIncrement;
- _kLineEndIndex += _panGestureIncrement;
- } else {
- /// 到达最前面
- NSInteger t = _chartDataArray.count-1 - _kLineStartIndex;
- _kLineStartIndex += t;
- _kLineEndIndex += t;
-
- /// 说明当前已经到达第一个图表数据
- if (t <= 1) {
- if (_chartDataArray.count != 0) {
- /// 触发该方法 告诉上层当前已经拖动到第一个数据
- if (self.delegate) [self.delegate onPanChartDataToTop];
- }
- }
- }
-
- [self setNeedsDisplay];
- } else if (_startTouchPosition.x > point.x) {
- /// 向左滑
- if (_kLineEndIndex == 0) return;
-
- _startTouchPosition.x = point.x;
- if (_kLineEndIndex-_panGestureIncrement >= 0) {
- _kLineStartIndex -= _panGestureIncrement;
- _kLineEndIndex -= _panGestureIncrement;
- } else {
- /// 到达最后面
- NSInteger t = _kLineEndIndex;
- _kLineStartIndex -= t;
- _kLineEndIndex -= t;
- }
- [self setNeedsDisplay];
- }
- } else {
- /// 移动十字线
- CGPoint point = [panGestureRecognizer locationInView:self];
-
- /// 判断是否在图表区域内
- if (CGRectContainsPoint(CGRectMake(_kLineOrigin.x, _yAxisPaddingTop, _xAxisWidth, _yAxisHeight), point)) {
- //判断是否能获取点击位置上的K线
- NSInteger tipIndex = NSNotFound;
- if (_chartViewType != ChartViewTypeTSPlan) tipIndex = [self tipIndexWithXPoint:point.x];
- else tipIndex = [self tipIndexTSPlanWithXPoint:point.x]; //分时图
-
- if (tipIndex != NSNotFound) {
- _tipLineIndex = tipIndex;
- _tipLineYAxis = point.y;
- [self setNeedsDisplay];
- }
- }
- }
- }
- }
- /**
- * @brief 捏合手势进行捏合时执行的方法
- */
- - (void)onPinchGesture:(id)sender {
- //如果当前是分时图则什么都不做
- if (_chartViewType == ChartViewTypeTSPlan) return;
-
- UIPinchGestureRecognizer *pinchGestureRecognizer = (UIPinchGestureRecognizer *)sender;
- //捏合手势开始
- if (pinchGestureRecognizer.state == UIGestureRecognizerStateBegan) {
- _startScale = pinchGestureRecognizer.scale;
- } else if (pinchGestureRecognizer.state == UIGestureRecognizerStateChanged) {//捏合手势进行捏合
- if (pinchGestureRecognizer.scale - _startScale > 0.05f) {
- _startScale = pinchGestureRecognizer.scale;
-
- //放大到最大
- if (_kLineWidth >= _kLineMaxWidth) return;
-
- _kLineWidth++;
- NSInteger lastKLineCount = _kLineCount;
- // _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding)) - _ts_remove_count;
- _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding));
- if (_kLineCount < 0) _kLineCount = 0;
-
- //判断当前最大显示数量是否已经小于原先最大显示数量(这一层好像是多余了,应该都是小于的)
- if (_kLineCount < lastKLineCount) {
- //判断原先已经显示的数量是否已经大于现在最大数量
- if (_kLineStartIndex-_kLineEndIndex+1 > _kLineCount) {
- //是的话就要减少显示数量了
- if (_kLineStartIndex == _chartDataArray.count-1) {
- //动后面
- _kLineEndIndex += (_kLineStartIndex-_kLineEndIndex+1-_kLineCount);
- } else {
- //动前面
- _kLineStartIndex -= (_kLineStartIndex-_kLineEndIndex+1-_kLineCount);
- }
- }
- }
- [self setNeedsDisplay];
- } else if (_startScale - pinchGestureRecognizer.scale > 0.05f) {
- _startScale = pinchGestureRecognizer.scale;
-
- //缩小
- if (_kLineWidth <= _kLineMinWidth) return;
-
- _kLineWidth--;
- NSInteger lastKLineCount = _kLineCount;
- // _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding)) - _ts_remove_count;
- _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding));
- if (_kLineCount < 0) _kLineCount = 0;
-
- //判断当前最大显示数据是否已经大于原先最大显示数量
- if (_kLineCount > lastKLineCount) {
- //判断原先已经显示的数量是否已经小于现在最大数量,同时还能增加显示数量
- if ((_kLineStartIndex-_kLineEndIndex+1<_kLineCount) && (_kLineStartIndex-_kLineEndIndex+1<_chartDataArray.count)) {
- //是的话就要增加显示数量了
- if (_kLineStartIndex == _chartDataArray.count-1) {
- //动后面
- _kLineEndIndex -= (_kLineCount - (_kLineStartIndex-_kLineEndIndex+1));
- if (_kLineEndIndex<0) _kLineEndIndex=0;
- } else {
- //动前面
- _kLineStartIndex += (_kLineCount - (_kLineStartIndex-_kLineEndIndex+1));
- if (_kLineStartIndex>_chartDataArray.count-1) _kLineStartIndex=_chartDataArray.count-1;
- }
- }
- }
- [self setNeedsDisplay];
- }
- }
- }
- /**
- * @brief 长按手势进行长按时执行的方法
- */
- - (void)onLongPressGesture:(id)sender {
- UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)sender;
- if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan) {//手势开始进行
- CGPoint point = [longPressGestureRecognizer locationInView:self];
- //判断是否在K线区域内
- if (CGRectContainsPoint(CGRectMake(_kLineOrigin.x, _yAxisPaddingTop, _xAxisWidth, _yAxisHeight), point)) {
- //判断是否能获取点击位置上的K线
- NSInteger tipIndex = NSNotFound;
- if (_chartViewType != ChartViewTypeTSPlan) {
- tipIndex = [self tipIndexWithXPoint:point.x];
- } else {
- //分时
- tipIndex = [self tipIndexTSPlanWithXPoint:point.x];
- }
-
- if (tipIndex != NSNotFound) {
- //开始长按
- _isShowTipLine = YES;
- _tipLineIndex = tipIndex;
- _tipLineYAxis = point.y;
- [self setNeedsDisplay];
- }
- }
- } else if (longPressGestureRecognizer.state == UIGestureRecognizerStateEnded) {
- //长按松开
- CGPoint point = [longPressGestureRecognizer locationInView:self];
- _startTouchPosition = point;
- _isShowTipLine = NO;
- [self setNeedsDisplay];
- }
- }
- #pragma mark - UIGestureRecognizerDelegate
- - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
- if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) return YES;
- return NO;
- }
- - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
- if ([gestureRecognizer isMemberOfClass:[UIPanGestureRecognizer class]]) {
- CGPoint translation = [(UIPanGestureRecognizer*)gestureRecognizer translationInView:self];
- if (fabs(translation.y) > fabs(translation.x)) { //上下方向
- return NO;
- }
- }
- return YES;
- }
- @end
|