ChartView.m 213 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561
  1. //
  2. // ChartView.m
  3. // ChartView
  4. //
  5. // Created by Simon Zhou on 14-6-11.
  6. // Copyright (c) 2014年 muchinfo. All rights reserved.
  7. //
  8. #import "ChartView.h"
  9. #import "ChartData.h"
  10. #import "ChartCalculateUtils.h"
  11. #define TAG_BUTTON_MACD 1000
  12. #define TAG_BUTTON_KDJ 1001
  13. #define TAG_BUTTON_RSI 1002
  14. @implementation ChartView {
  15. /// X轴相关
  16. /// X轴宽度,通过视图宽度-价格标签宽度-边框Padding计算得出
  17. CGFloat _xAxisWidth;
  18. /// X轴左边距,即价格标签宽度
  19. CGFloat _xAxisPaddingLeft;
  20. /// X轴右边距,默认为5.0f(因为要显示最后一个时间标签)
  21. CGFloat _xAxisPaddingRight;
  22. CGFloat _excessXAxisWidth;
  23. /// Y轴相关
  24. /// Y轴高度,通过视图高度-边框Padding计算得出
  25. CGFloat _yAxisHeight;
  26. /// 当前可视Y轴最大值
  27. CGFloat _yAxisMaxValue;
  28. /// 当前可视Y轴最小值
  29. CGFloat _yAxisMinValue;
  30. /// K起点
  31. /// 坐标原点
  32. CGPoint _kLineOrigin;
  33. /// K线相关
  34. /// K线形状最小宽度
  35. CGFloat _kLineMinWidth;
  36. /// K线形状最大宽度
  37. CGFloat _kLineMaxWidth;
  38. /// K线形状之间的间隔,默认为1.0f
  39. CGFloat _kLinePadding;
  40. /// K线形状宽度,默认为5.0f
  41. CGFloat _kLineWidth;
  42. /// 可显示K线数量,由_xAxisWidth/_kLineWidth 计算得出
  43. NSInteger _kLineCount;
  44. /// 当前可视K线数据起始下标
  45. NSInteger _kLineStartIndex;
  46. /// 当前可视K线数据
  47. NSInteger _kLineEndIndex;
  48. /// 十字线相关
  49. /// 是否显示十字线
  50. BOOL _isShowTipLine;
  51. /// 十字线当前K线下标
  52. NSInteger _tipLineIndex;
  53. /// 十字线Y轴坐标
  54. CGFloat _tipLineYAxis;
  55. /// MACD相关
  56. /// 指标框下边距
  57. CGFloat _indicatorPaddingBottom;
  58. /// 指标原点
  59. CGPoint _indicatorOrigin;
  60. /// MACD可视指标最大值
  61. CGFloat _indicatorMaxValue;
  62. /// MACD可视指标最小值
  63. CGFloat _indicatorMinValue;
  64. /// VOL相关
  65. /// VOL可视指标最大值
  66. CGFloat _indicatorVOLMaxValue;
  67. /// VOL可视指标最小值
  68. CGFloat _indicatorVOLMiniValue;
  69. /// KDJ相关
  70. /// KDJ可视指标最大值
  71. CGFloat _indicatorKDJMaxValue;
  72. /// KDJ可视指标最小值
  73. CGFloat _indicatorKDJMiniValue;
  74. /// RSI相关
  75. /// RSI可视指标最大值
  76. CGFloat _indicatorRSIMaxValue;
  77. /// RSI可视指标最小值
  78. CGFloat _indicatorRSIMiniValue;
  79. /// CCI相关
  80. /// CCI可视指标最大值
  81. CGFloat _indicatorCCIMaxValue;
  82. /// CCI可视指标最小值
  83. CGFloat _indicatorCCIMiniValue;
  84. /// DMA相关
  85. /// DMA可视指标最大值
  86. CGFloat _indicatorDMAMaxValue;
  87. /// DMA可视指标最小值
  88. CGFloat _indicatorDMAMiniValue;
  89. /// BIAS相关
  90. /// BIAS可视指标最大值
  91. CGFloat _indicatorBIASMaxValue;
  92. /// BIAS可视指标最小值
  93. CGFloat _indicatorBIASMiniValue;
  94. /// PSY相关
  95. /// PSY可视指标最大值
  96. CGFloat _indicatorPSYMaxValue;
  97. /// PSY可视指标最小值
  98. CGFloat _indicatorPSYMiniValue;
  99. /// CR相关
  100. /// CR可视指标最大值
  101. CGFloat _indicatorCRMaxValue;
  102. /// CR可视指标最小值
  103. CGFloat _indicatorCRMiniValue;
  104. /// 交互相关
  105. CGPoint _startTouchPosition;
  106. CGFloat _startScale;
  107. /// 分时图相关
  108. /// 分时图最早数据开始X轴(因有时开盘时间与第一口价格有时间差)
  109. CGFloat _tsStartXPonit;
  110. /// 现价相关
  111. /// 行情现价
  112. NSDecimalNumber *_price;
  113. /// 现价报价时间
  114. NSDate *_priceTime;
  115. /// FIXME: 临时变量
  116. BOOL _added;
  117. }
  118. #pragma mark - 重载方法
  119. - (void)layoutSubviews {
  120. // NSLog(@"%s",__func__);
  121. }
  122. - (void)drawRect:(CGRect)rect {
  123. if (!_chartDataArray) {
  124. CGContextRef context = UIGraphicsGetCurrentContext();
  125. CGContextSetRGBFillColor(context, _bgRed, _bgGreen, _bgBlue, 1.0f);
  126. CGContextFillRect(context, self.bounds);
  127. return;
  128. }
  129. /// 更新数据的方法
  130. [self updateData];
  131. /// 画框图表架
  132. [self drawBorder];
  133. /// 画图表X轴
  134. [self drawXAxis];
  135. /// 画图表Y轴
  136. [self drawYAxis];
  137. if (_chartViewType == ChartViewTypeKL) {
  138. if (_isBBGoods) {
  139. /// K线
  140. [self drawBBTSPlanLine];
  141. /// 画平均线
  142. [self drawBBAverageLine];
  143. } else {
  144. /// K线
  145. [self drawKLine];
  146. /// 画平均线
  147. [self drawAverageLine];
  148. if (_isShowIndicator) { /// 需要显示指标
  149. switch (_chartTargetType) {
  150. case MACD: { /// 指标为MACD
  151. /// 初始化MACD可视化数据
  152. [self initMACDData];
  153. /// 画MACD指标的方法
  154. [self drawMACD];
  155. break;
  156. }
  157. case VOL:{ /// 指标为VOL
  158. /// 初始化VOL可视化数据
  159. [self initVOLData];
  160. /// 画VOL指标的方法
  161. [self drawVOL];
  162. break;
  163. }
  164. case KDJ: { /// 指标为KDJ
  165. /// 初始化KDJ可视化数据
  166. [self initKDJData];
  167. /// 画KDJ指标的方法
  168. [self drawKDJ];
  169. break;
  170. }
  171. case CCI: { /// 指标为CCI
  172. /// 初始化CCI可视化数据
  173. [self initCCIData];
  174. /// 画CCI指标的方法
  175. [self drawCCI];
  176. break;
  177. }
  178. case PSY: { /// 指标为PSY
  179. /// 初始化PSY可视化数据
  180. [self initPSYData];
  181. /// 画PSY指标的方法
  182. [self drawPSY];
  183. break;
  184. }
  185. case BIAS: { /// 指标为BIAS
  186. /// 初始化BIAS可视化数据
  187. [self initBIASData];
  188. /// 画BIAS指标的方法
  189. [self drawBIAS];
  190. break;
  191. }
  192. case KD: { /// 指标为KD
  193. /// 初始化KD可视化数据
  194. [self initKDJData];
  195. /// 画KD指标的方法
  196. [self drawKD];
  197. break;
  198. }
  199. case DMA: { /// 指标为DMA
  200. /// 初始化DMA可视化数据
  201. [self initDMAData];
  202. /// 画DMA指标的方法
  203. [self drawDMA];
  204. break;
  205. }
  206. default:
  207. break;
  208. }
  209. }
  210. }
  211. } else if (_chartViewType == ChartViewTypeImmediately) { // 即时图
  212. /// 即时线
  213. [self drawImmediatelyLine];
  214. } else if (_chartViewType == ChartViewTypeTSPlan) { // 分时图
  215. /// 分时图
  216. [self drawTSPlanLine];
  217. /// 分时图平均线
  218. [self drawTSAverageLine];
  219. }
  220. // 画现价的方法
  221. [self drawPrice];
  222. }
  223. #pragma mark - 初始化
  224. /**
  225. * @brief 初始化图表 (图表初始化时调用)
  226. */
  227. - (void)initChartView {
  228. // 视图整体相关
  229. if (!_lineColor) _lineColor = [UIColor colorWithRed:50.0f/225.0f green:50.0f/225.0f blue:50.0f/225.0f alpha:1.0f];
  230. if (!_titleColor) _titleColor = [UIColor whiteColor];
  231. if (!_titleFont) _titleFont = [UIFont systemFontOfSize:8.0f];
  232. // K线阴块颜色
  233. _decKRed = 1.0f;
  234. _decKGreen = 0.0f;
  235. _decKBlue = 0.0f;
  236. _decKAlpha = 1.0f;
  237. // K线阳块颜色
  238. _aesKRed = 0.0f;
  239. _aesKGreen = 1.0f;
  240. _aesKBlue = 0.0f;
  241. _aesKAlpha = 1.0f;
  242. // K线平块颜色
  243. _samKRed = 1.0f;
  244. _samKGreen = 1.0f;
  245. _samKBlue = 1.0f;
  246. _samKAlpha = 1.0f;
  247. // 十字线颜色
  248. _tipRed = 1.0f;
  249. _tipGreen = 1.0f;
  250. _tipBlue = 1.0f;
  251. _tipAlpha = 1.0f;
  252. if (!_tipTitleColor) _tipTitleColor = [UIColor whiteColor];
  253. // K线MA5颜色
  254. _kMA5Red = 1.0f;
  255. _kMA5Green = 0.0f;
  256. _kMA5Blue = 1.0f;
  257. _kMA5Alpha = 0.5f;
  258. // K线MA10颜色 1.0f, 0.3f, 0, 0.5f
  259. _kMA10Red = 1.0f;
  260. _kMA10Green = 0.3f;
  261. _kMA10Blue = 0.0f;
  262. _kMA10Alpha = 0.5f;
  263. // K线MA15颜色 0, 1.0f, 0, 0.5f
  264. _kMA15Red = 0.0f;
  265. _kMA15Green = 1.0f;
  266. _kMA15Blue = 0.0f;
  267. _kMA15Alpha = 0.5f;
  268. // 分时线颜色 168.0f/255.0f, 217.0f/255.0f, 243.0f/255.0f, 1.0f
  269. _tsRed = 168.0f/255.0f;
  270. _tsGreen = 217.0f/255.0f;
  271. _tsBlue = 243.0f/255.0f;
  272. _tsAlpha = 1.0f;
  273. // 分时MA线 1.0f, 1.0f, 0, 1.0f
  274. _tsMARed = 1.0f;
  275. _tsMAGreen = 1.0f;
  276. _tsMABlue = 0.0f;
  277. _tsMAAlpha = 1.0f;
  278. // MACD DIF线颜色 1.0f, 0, 0, 0.5f
  279. _macdDIFRed = 1.0f;
  280. _macdDIFGreen = 0.0f;
  281. _macdDIFBlue = 0.0f;
  282. _macdDIFAlpha = 0.5f;
  283. // MACD DEA线颜色 0, 1.0f, 0, 0.5f
  284. _macdDEARed = 0.0f;
  285. _macdDEAGreen = 1.0f;
  286. _macdDEABlue = 0.0f;
  287. _macdDEAAlpha = 0.5f;
  288. //X轴相关
  289. _xAxisPaddingLeft = 5.0f; //X轴左边距
  290. // _ts_remove_count = 0;
  291. //Y轴相关
  292. _yAxisPaddingTop = 35.0f; //Y轴上边距,默认为10.0f(因为要显示最高标签与平均线说明标签)
  293. _yAxisPaddingBottom = 35.0f; //Y轴上边距,主要由视图高度-指标框高度(可能为0)计算得出
  294. //K线相关
  295. _kLineMinWidth = 1.0f; //K线形状最小宽度
  296. _kLineMaxWidth = 20.0f; //K线形状最大宽度
  297. _kLinePadding = 2.0f; //K线形状之间的间隔
  298. _kLineWidth = 5.0f; //K线形状宽度,默认为5.0f
  299. // _minUnit = [[NSDecimalNumber decimalNumberWithString:@"0.01"] retain];
  300. //交互相关
  301. _panGestureIncrement = 1;
  302. //现价
  303. _isShowPrice = YES;
  304. //指标相关
  305. if (_chartViewType == ChartViewTypeKL) {
  306. _isShowIndicator = YES;
  307. if (_indicatorHight == 0.0f) _indicatorHight = 70.0f;
  308. _indicatorPaddingBottom = 5.0f;
  309. } else {
  310. //分时图不显示指标
  311. _isShowIndicator = NO;
  312. _indicatorHight = 0;
  313. _indicatorPaddingBottom = 0;
  314. }
  315. }
  316. /**
  317. * @brief 初始化整个视图,主要包括计算相关数据 (设置数据时调用)
  318. */
  319. - (void)initData {
  320. /// 如果没有任何图表数据 不做任何处理
  321. if (_chartDataArray.count == 0) return;
  322. /// ************** X轴相关 ***************
  323. /// 计算X轴左边距
  324. NSDecimalNumberHandler *behavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:0 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
  325. ChartData *chartData = [_chartDataArray objectAtIndex:0];
  326. NSDecimalNumber *widthDecimalNumber = [[chartData.closed decimalNumberByRoundingAccordingToBehavior:behavior] decimalNumberByAdding:_minUnit];
  327. _xAxisPaddingRight = [[widthDecimalNumber description] sizeWithAttributes:@{NSFontAttributeName:_titleFont}].width + 10.0f;
  328. ///n计算X轴宽度
  329. _xAxisWidth = self.bounds.size.width - _xAxisPaddingLeft - _xAxisPaddingRight;
  330. if (_chartViewType == ChartViewTypeKL || _chartViewType == ChartViewTypeImmediately) {
  331. /// ************** K线相关 ***************
  332. /// 计算可显示K线数量
  333. _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding));
  334. if (_kLineCount < 0) _kLineCount = 0;
  335. /// 把多余的右边空间加到左边
  336. _excessXAxisWidth = _xAxisWidth - (_kLineWidth + _kLinePadding)*_kLineCount-1.0f;
  337. _xAxisPaddingRight += _excessXAxisWidth;
  338. _xAxisWidth -= _excessXAxisWidth;
  339. /// 当前可视K线数据起始下标 (默认最新的数据在第一条)
  340. _kLineStartIndex = _chartDataArray.count > _kLineCount ? _kLineCount - 1 : _chartDataArray.count - 1;
  341. /// 当前可视K线数据结束下标
  342. _kLineEndIndex = 0;
  343. } else {
  344. /// ************** 分时相关 ***************
  345. _excessXAxisWidth = 0;
  346. /// 遍历计算计划内的有效时间
  347. _kLineCount = 0;
  348. for (NSDictionary<NSString *, NSDate *> *item in _reckonDetails) {
  349. _kLineCount += [self diffMinuteWithFromDate:item[@"openTime"] toDate:item[@"reckonTime"]];
  350. }
  351. if (_kLineCount < 0) _kLineCount = 0;
  352. _kLineStartIndex = _chartDataArray.count-1;
  353. _kLineEndIndex = 0;
  354. }
  355. //************** Y轴相关 ***************
  356. /// 计算Y轴高度
  357. _yAxisHeight = self.bounds.size.height - _yAxisPaddingTop - _yAxisPaddingBottom - _indicatorHight - _indicatorPaddingBottom;
  358. /// ************** 坐标原点 ***************
  359. _kLineOrigin = CGPointMake(_xAxisPaddingLeft,_yAxisHeight + _yAxisPaddingTop);
  360. /// ************** 指标原点 ***************
  361. _indicatorOrigin = CGPointMake(_kLineOrigin.x, _kLineOrigin.y + _yAxisPaddingBottom + _indicatorHight);
  362. if (_chartViewType != ChartViewTypeImmediately) {
  363. /// 初始化平均线数据以及MACD指标数据
  364. [self initAverageLineDataWithIndex:_chartDataArray.count-1];
  365. /// 初始化平均线数据以及VOL指标数据
  366. [self initVOLLineDataWithIndex:_chartDataArray.count-1];
  367. /// 初始化KDJ指标数据
  368. [self initKDJLineDataWithIndex:_chartDataArray.count-1];
  369. /// 初始化CCI指标数据
  370. [self initCCILineDataWithIndex:_chartDataArray.count-1];
  371. /// 初始化BIAS指标数据
  372. [self initBIASLineDataWithIndex:_chartDataArray.count-1];
  373. /// 初始化PSY指标数据
  374. [self initPSYLineDataWithIndex:_chartDataArray.count-1];
  375. /// 初始化DMA指标数据
  376. [self initDMALineDataWithIndex:_chartDataArray.count-1];
  377. /// 回调方法通知上层当前有数据的指标列表
  378. BOOL hasMACD = NO;
  379. BOOL hasVOL = NO;
  380. BOOL hasKDJ = NO;
  381. BOOL hasRSI = NO;
  382. BOOL hasCCI = NO;
  383. BOOL hasDMA = NO;
  384. BOOL hasBIAS = NO;
  385. BOOL hasPSY = NO;
  386. for (ChartData *chartData in self.chartDataArray) {
  387. if (chartData.macd && ![chartData.macd isEqualToNumber:[NSDecimalNumber zero]] && !hasMACD)
  388. hasMACD = YES;
  389. if (chartData.vol5 && ![chartData.vol5 isEqualToNumber:[NSDecimalNumber zero]] && !hasVOL)
  390. hasVOL = YES;
  391. if (chartData.kt && ![chartData.kt isEqualToNumber:[NSDecimalNumber zero]] && !hasKDJ)
  392. hasKDJ = YES;
  393. if (chartData.rsi1 && ![chartData.rsi1 isEqualToNumber:[NSDecimalNumber zero]] && !hasRSI)
  394. hasRSI = YES;
  395. if (chartData.cci && ![chartData.cci isEqualToNumber:[NSDecimalNumber zero]] && !hasCCI)
  396. hasCCI = YES;
  397. if (chartData.dma && ![chartData.dma isEqualToNumber:[NSDecimalNumber zero]] && !hasDMA)
  398. hasDMA = YES;
  399. if (chartData.bias1 && ![chartData.bias1 isEqualToNumber:[NSDecimalNumber zero]] && !hasBIAS)
  400. hasBIAS = YES;
  401. if (chartData.psy && ![chartData.psy isEqualToNumber:[NSDecimalNumber zero]] && !hasPSY)
  402. hasPSY = YES;
  403. }
  404. NSMutableArray<NSString *> *targets = [NSMutableArray arrayWithCapacity:0];
  405. if (hasMACD)
  406. [targets addObject:@"MACD"];
  407. if (hasVOL)
  408. [targets addObject:@"VOL"];
  409. if (hasKDJ)
  410. [targets addObject:@"KDJ"];
  411. if (hasRSI)
  412. [targets addObject:@"RSI"];
  413. if (hasCCI)
  414. [targets addObject:@"CCI"];
  415. if (hasDMA)
  416. [targets addObject:@"DMA"];
  417. if (hasBIAS)
  418. [targets addObject:@"BIAS"];
  419. if (hasPSY)
  420. [targets addObject:@"PSY"];
  421. if (self.delegate)
  422. [self.delegate onFinishInitDataWithTargets:targets];
  423. }
  424. }
  425. #pragma mark - 公开方法
  426. /**
  427. * @brief 初始化方法,一般在buildView时调用
  428. *
  429. * @param chartViewType 图表类型
  430. * @param frame frame
  431. *
  432. * @return self
  433. */
  434. - (nullable instancetype)initWithType:(ChartViewType)chartViewType frame:(CGRect)frame {
  435. /// 设置视图最小宽度与最小高度
  436. if (frame.size.width < 160.0f) frame.size.width = 160.0f;
  437. if (frame.size.height < 200.0f) frame.size.height = 200.0f;
  438. /// 类型
  439. _chartViewType = chartViewType;
  440. self = [super initWithFrame:frame];
  441. if (self) {
  442. /// 初始化图表
  443. [self initChartView];
  444. /// 初始化图表交互的相关手势
  445. [self initGestureRecognizer];
  446. }
  447. return self;
  448. }
  449. /**
  450. * @brief 切换图表类型的方法,一般在用户点击分时图或K线周期时调用
  451. *
  452. * @param chartViewType 目标切换图表类型
  453. * @param chartDataArray 图表数据
  454. */
  455. - (void)changeChartType:(ChartViewType)chartViewType chartDataArray:(nullable NSMutableArray *)chartDataArray {
  456. _chartViewType = chartViewType;
  457. /// 显示K线图以及指标
  458. if (_chartViewType == ChartViewTypeKL && _isShowIndicator) {
  459. if (_indicatorHight == 0.0f) _indicatorHight = 70.0f;
  460. _indicatorPaddingBottom = 5.0f;
  461. } else {
  462. /// 分时图不显示指标
  463. _indicatorHight = 0;
  464. _indicatorPaddingBottom = 0;
  465. }
  466. _yAxisHeight = self.bounds.size.height - _yAxisPaddingTop - _yAxisPaddingBottom - _indicatorHight - _indicatorPaddingBottom;
  467. self.chartDataArray = chartDataArray;
  468. if (_price) {
  469. _price = nil;
  470. }
  471. if (_priceTime) {
  472. _priceTime = nil;
  473. }
  474. [self setNeedsDisplay];
  475. }
  476. /**
  477. * @brief 切换图表指标类型的方法
  478. */
  479. - (void)changeChartTargetType:(ChartTargetType)chartTargetType {
  480. /// 调用上层方法重新描绘图表
  481. [self setNeedsDisplay];
  482. }
  483. /**
  484. * @brief 追加图表数据的方法,一般在图表刷新(包括自动刷新)时调用
  485. *
  486. * @param appendChartDataArray 追加的图表数据
  487. */
  488. - (void)appendChartDataArray:(nullable NSMutableArray *)appendChartDataArray {
  489. if (appendChartDataArray.count == 0) return;
  490. //判断追加完数据后要不要刷新图表
  491. BOOL isNeedRefresh = YES;
  492. if (_kLineEndIndex != 0) isNeedRefresh = NO;
  493. //判断追加的最后一条数据是否原第一条数据
  494. NSInteger appendChartDataEndIndex = _chartDataArray.count-1+appendChartDataArray.count-1;
  495. ChartData *appendLastChartData = [appendChartDataArray objectAtIndex:appendChartDataArray.count-1];
  496. ChartData *sourceFirstChartData = [_chartDataArray objectAtIndex:0];
  497. if ([appendLastChartData.startTime compare:sourceFirstChartData.startTime] == NSOrderedSame) {
  498. [_chartDataArray removeObject:sourceFirstChartData];
  499. appendChartDataEndIndex --;
  500. }
  501. /// 追加数据
  502. [appendChartDataArray addObjectsFromArray:_chartDataArray];
  503. _chartDataArray = appendChartDataArray;
  504. /// 计算平均线等数据
  505. if (_chartViewType == ChartViewTypeKL || _chartViewType == ChartViewTypeImmediately) {
  506. /// 初始化平均线数据以及MACD指标数据
  507. [self initAverageLineDataWithIndex:appendChartDataEndIndex];
  508. /// 初始化平均线数据以及VOL指标数据
  509. [self initVOLLineDataWithIndex:appendChartDataEndIndex];
  510. /// 初始化KDJ指标数据
  511. [self initKDJLineDataWithIndex:appendChartDataEndIndex];
  512. /// 初始化CCI指标数据
  513. [self initCCILineDataWithIndex:appendChartDataEndIndex];
  514. /// 初始化BIAS指标数据
  515. [self initBIASLineDataWithIndex:appendChartDataEndIndex];
  516. /// 初始化PSY指标数据
  517. [self initPSYLineDataWithIndex:appendChartDataEndIndex];
  518. /// 初始化DMA指标数据
  519. [self initDMALineDataWithIndex:appendChartDataEndIndex];
  520. }
  521. if (isNeedRefresh) [self setNeedsDisplay];
  522. }
  523. /**
  524. * @brief 对外公开设置图表数据的方法,内部会调用initData方法
  525. *
  526. * @param chartDataArray 图表数据
  527. */
  528. - (void)setChartDataArray:(nullable NSMutableArray *)chartDataArray {
  529. if (_chartDataArray) {
  530. if (_chartDataArray != chartDataArray) {
  531. _chartDataArray = chartDataArray;
  532. }
  533. } else {
  534. _chartDataArray = chartDataArray;
  535. }
  536. /// 初始化数据
  537. [self initData];
  538. }
  539. /**
  540. * @brief 让图表恢复正常状态的方法。可在十字线显示时离开ViewController等情况下调用。
  541. */
  542. - (void)restoreNormalState {
  543. _isShowTipLine = NO;
  544. [self setNeedsDisplay];
  545. }
  546. /**
  547. 清空图表的方法
  548. */
  549. - (void)clear {
  550. if (_chartDataArray) {
  551. _chartDataArray = nil;
  552. }
  553. [self setNeedsDisplay];
  554. }
  555. /**
  556. * @brief 追加行情现价的方法。
  557. *
  558. * @param price 行情现价
  559. * @param priceTime 行情时间
  560. * @param lastVolume 成交量
  561. *
  562. */
  563. - (ChartErrorType)appendQuotaPrice:(nullable NSDecimalNumber *)price priceTime:(nullable NSDate *)priceTime lastVolume:(nullable NSDecimalNumber *)lastVolume {
  564. if (_cycleInterval == 0.0f) {
  565. /// 没有设置周期间隔秒数则
  566. return ChartErrorTypeNotSetCycleInterval;
  567. }
  568. ChartData *chartDataLast = [_chartDataArray objectAtIndex:0];
  569. /// 如果行情时间比图表最近时间还要早则不做任务处理
  570. if ([priceTime compare:chartDataLast.startTime] == NSOrderedAscending) {
  571. return ChartErrorTypeQuotaTimeOldest;
  572. }
  573. /// 获取下一个周期开始时间和下两个周期开始时间
  574. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  575. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  576. NSInteger cycle = 0;
  577. switch ((NSInteger)_cycleInterval) {
  578. case 60:
  579. cycle = 1;
  580. break;
  581. case 5 * 60:
  582. cycle = 4;
  583. break;
  584. case 15 * 60:
  585. cycle = 14;
  586. break;
  587. case 30 * 60:
  588. cycle = 29;
  589. break;
  590. case 60 * 60:
  591. cycle = 59;
  592. break;
  593. case 60 * 60 * 2:
  594. cycle = (60 * 2) - 1;
  595. break;
  596. case 60 * 60 * 4:
  597. cycle = (60 * 4) - 1;
  598. break;
  599. case 60 * 60 * 24:
  600. cycle = (60 * 24) - 1;
  601. break;
  602. default:
  603. break;
  604. }
  605. NSInteger seconds = cycle * 60 - [[[dateFormatter stringFromDate:chartDataLast.startTime] substringWithRange:NSMakeRange(16, 2)] integerValue];
  606. NSDate *nextOneDate = [[NSDate alloc] initWithTimeInterval:seconds sinceDate:chartDataLast.startTime];
  607. NSDate *nextTwoDate = [[NSDate alloc] initWithTimeInterval:_cycleInterval*2 sinceDate:chartDataLast.startTime];
  608. if ([priceTime compare:nextTwoDate] != NSOrderedAscending) {
  609. /// 行情时间已经超时一个数据块时间周期
  610. if (self.delegate) {
  611. [self.delegate requestRefreshChartDataWithErrorCode:ChartErrorTypeQuotaTimeout];
  612. }
  613. } else {
  614. /// 行情时间在可接收范围之内,则再判断行情数据是图表最近时间块内,还是下一个时间周期块
  615. if ([priceTime compare:nextOneDate] != NSOrderedAscending) {
  616. /// Warning:目前遇到下一个周期不是整数的问题,暂时直接处理
  617. priceTime = [chartDataLast.startTime dateByAddingTimeInterval:_cycleInterval];
  618. ChartData *chartData = [[ChartData alloc] init];
  619. chartData.opened = price;
  620. chartData.closed = price;
  621. chartData.highest = price;
  622. chartData.lowest = price;
  623. chartData.startTime = priceTime;
  624. chartData.totleVolume = lastVolume;
  625. [_chartDataArray insertObject:chartData atIndex:0];
  626. /// 触发图表数据最新时间变更回调
  627. if (self.delegate) [self.delegate onChangeDataLasttime:priceTime];
  628. } else {
  629. /// 行情时间属于图表最近时间周期块
  630. chartDataLast.closed = price;
  631. if ([price compare:chartDataLast.highest] == NSOrderedDescending) {
  632. chartDataLast.highest = price;
  633. }
  634. if ([price compare:chartDataLast.lowest] == NSOrderedAscending) {
  635. chartDataLast.lowest = price;
  636. }
  637. if (chartDataLast.totleVolume && lastVolume) {
  638. chartDataLast.totleVolume = [chartDataLast.totleVolume decimalNumberByAdding:lastVolume];
  639. }
  640. }
  641. /// 记录现价和时间
  642. if (_price) {
  643. if (_price != price) {
  644. _price = price;
  645. }
  646. } else {
  647. _price = price;
  648. }
  649. if (_priceTime) {
  650. if (_priceTime != priceTime) {
  651. _priceTime = priceTime;
  652. }
  653. } else {
  654. _priceTime = priceTime;
  655. }
  656. /// 计算平均线等数据
  657. if (_chartViewType == ChartViewTypeKL || _chartViewType == ChartViewTypeImmediately) {
  658. /// 初始化平均线数据以及MACD指标数据
  659. /// 刷新最近一条数据就可以(错)
  660. [self initAverageLineDataWithIndex:_chartDataArray.count-1];
  661. /// 初始化平均线数据以及VOL指标数据
  662. [self initVOLLineDataWithIndex:_chartDataArray.count-1];
  663. /// 初始化KDJ指标数据
  664. [self initKDJLineDataWithIndex:_chartDataArray.count-1];
  665. /// 初始化CCI指标数据
  666. [self initCCILineDataWithIndex:_chartDataArray.count-1];
  667. /// 初始化BIAS指标数据
  668. [self initBIASLineDataWithIndex:_chartDataArray.count-1];
  669. /// 初始化PSY指标数据
  670. [self initPSYLineDataWithIndex:_chartDataArray.count-1];
  671. /// 初始化DMA指标数据
  672. [self initDMALineDataWithIndex:_chartDataArray.count-1];
  673. } else {
  674. /// 初始化平均线数据以及MACD指标数据
  675. /// 刷新最近一条数据就可以(错)
  676. [self initAverageLineDataWithIndex:_chartDataArray.count-1];
  677. }
  678. /// 调用父类方法 重新去描绘图表
  679. [self setNeedsDisplay];
  680. }
  681. return ChartErrorTypeNone;
  682. }
  683. #pragma mark - 颜色设置
  684. /**
  685. * @brief 设置K线阴块颜色的方法
  686. *
  687. * @param decKRed K线阴块红色值
  688. * @param decKGreen K线阴块绿色值
  689. * @param decKBlue K线阴块蓝色值
  690. * @param decKAlpha K线阴块alpha值
  691. */
  692. - (void)setDecKRed:(CGFloat)decKRed decKGreen:(CGFloat)decKGreen decKBlue:(CGFloat)decKBlue decKAlpha:(CGFloat)decKAlpha {
  693. _decKRed = decKRed;
  694. _decKGreen = decKGreen;
  695. _decKBlue = decKBlue;
  696. _decKAlpha = decKAlpha;
  697. }
  698. /**
  699. * @brief 设置K线阳块颜色的方法
  700. *
  701. * @param aesKRed K线阳块红色值
  702. * @param aesKGreen K线阳块绿色值
  703. * @param aesKBlue K线阳块蓝色值
  704. * @param aesKAlpha K线阳块alpha值
  705. */
  706. - (void)setAesKRed:(CGFloat)aesKRed aesKGreen:(CGFloat)aesKGreen aesKBlue:(CGFloat)aesKBlue aesKAlpha:(CGFloat)aesKAlpha {
  707. _aesKRed = aesKRed;
  708. _aesKGreen = aesKGreen;
  709. _aesKBlue = aesKBlue;
  710. _aesKAlpha = aesKAlpha;
  711. }
  712. /**
  713. * @brief 设置开高低收报价字体颜色为绿色时的颜色
  714. */
  715. - (void)setPriceGreenColor:(nullable UIColor *)priceGreenColor {
  716. if (!_priceGreenColor) {
  717. _priceGreenColor = priceGreenColor;
  718. } else {
  719. _priceGreenColor = nil;
  720. _priceGreenColor = priceGreenColor;
  721. }
  722. }
  723. /**
  724. * @brief 设置K线平块颜色的方法
  725. *
  726. * @param samKRed K线平块红色值
  727. * @param samKGreen K线平块绿色值
  728. * @param samKBlue K线平块蓝色值
  729. * @param samKAlpha K线平块alpha值
  730. */
  731. - (void)setSamKRed:(CGFloat)samKRed samKGreen:(CGFloat)samKGreen samKBlue:(CGFloat)samKBlue samKAlpha:(CGFloat)samKAlpha {
  732. _samKRed = samKRed;
  733. _samKGreen = samKGreen;
  734. _samKBlue = samKBlue;
  735. _samKAlpha = samKAlpha;
  736. }
  737. /**
  738. * @brief 设置十字线颜色的方法
  739. *
  740. * @param tipRed 十字线红色值
  741. * @param tipGreen 十字线绿色值
  742. * @param tipBlue 十字线蓝色值
  743. * @param tipAlpha 十字线alpha值
  744. * @param tipTitleColor 十字线标题颜色对象
  745. */
  746. - (void)setTipRed:(CGFloat)tipRed tipGreen:(CGFloat)tipGreen tipBlue:(CGFloat)tipBlue tipAlpha:(CGFloat)tipAlpha tipTitleColor:(nullable UIColor *)tipTitleColor {
  747. _tipRed = tipRed;
  748. _tipGreen = tipGreen;
  749. _tipBlue = tipBlue;
  750. _tipAlpha = tipAlpha;
  751. if (_tipTitleColor) {
  752. if (_tipTitleColor != tipTitleColor) {
  753. _tipTitleColor = tipTitleColor;
  754. }
  755. } else {
  756. _tipTitleColor = tipTitleColor;
  757. }
  758. }
  759. /**
  760. * @brief 设置分时图昨收线颜色的方法
  761. *
  762. * @param preCloseLineRed 昨收线红色值
  763. * @param preCloseLineGreen 昨收线绿色值
  764. * @param preCloseLineBlue 昨收线蓝色值
  765. * @param preCloseLineAlpha 昨收线alpha值
  766. */
  767. - (void)setPreCloseLineRed:(CGFloat)preCloseLineRed preCloseLineGreen:(CGFloat)preCloseLineGreen preCloseLineBlue:(CGFloat)preCloseLineBlue preCloseLineAlpha:(CGFloat)preCloseLineAlpha {
  768. _preCloseLineRed = preCloseLineRed;
  769. _preCloseLineGreen = preCloseLineGreen;
  770. _preCloseLineBlue = preCloseLineBlue;
  771. _preCloseLineAlpha = preCloseLineAlpha;
  772. }
  773. /**
  774. * @brief 设置K线MA5平均线颜色的方法
  775. *
  776. * @param kMA5Red K线MA5平均线红色值
  777. * @param kMA5Green K线MA5平均线绿色值
  778. * @param kMA5Blue K线MA5平均线蓝色值
  779. * @param kMA5Alpha K线MA5平均线alpha值
  780. */
  781. - (void)setkMA5Red:(CGFloat)kMA5Red kMA5Green:(CGFloat)kMA5Green kMA5Blue:(CGFloat)kMA5Blue kMA5Alpha:(CGFloat)kMA5Alpha {
  782. _kMA5Red = kMA5Red;
  783. _kMA5Green = kMA5Green;
  784. _kMA5Blue = kMA5Blue;
  785. _kMA5Alpha = kMA5Alpha;
  786. }
  787. /**
  788. * @brief 设置K线MA10平均线颜色的方法
  789. *
  790. * @param kMA10Red K线MA10平均线红色值
  791. * @param kMA10Green K线MA10平均线绿色值
  792. * @param kMA10Blue K线MA10平均线蓝色值
  793. * @param kMA10Alpha K线MA10平均线alpha值
  794. */
  795. - (void)setkMA10Red:(CGFloat)kMA10Red kMA10Green:(CGFloat)kMA10Green kMA10Blue:(CGFloat)kMA10Blue kMA10Alpha:(CGFloat)kMA10Alpha {
  796. _kMA10Red = kMA10Red;
  797. _kMA10Green = kMA10Green;
  798. _kMA10Blue = kMA10Blue;
  799. _kMA10Alpha = kMA10Alpha;
  800. }
  801. /**
  802. * @brief 设置K线MA15平均线颜色的方法
  803. *
  804. * @param kMA15Red K线MA15平均线红色值
  805. * @param kMA15Green K线MA15平均线绿色值
  806. * @param kMA15Blue K线MA15平均线蓝色值
  807. * @param kMA15Alpha K线MA15平均线alpha值
  808. */
  809. - (void)setkMA15Red:(CGFloat)kMA15Red kMA15Green:(CGFloat)kMA15Green kMA15Blue:(CGFloat)kMA15Blue kMA15Alpha:(CGFloat)kMA15Alpha {
  810. _kMA15Red = kMA15Red;
  811. _kMA15Green = kMA15Green;
  812. _kMA15Blue = kMA15Blue;
  813. _kMA15Alpha = kMA15Alpha;
  814. }
  815. /**
  816. * @brief 设置分时线颜色的方法
  817. *
  818. * @param tsRed 分时线红色值
  819. * @param tsGreen 分时线绿色值
  820. * @param tsBlue 分时线蓝色值
  821. * @param tsAlpha 分时线alpha值
  822. */
  823. - (void)setTsRed:(CGFloat)tsRed tsGreen:(CGFloat)tsGreen tsBlue:(CGFloat)tsBlue tsAlpha:(CGFloat)tsAlpha {
  824. _tsRed = tsRed;
  825. _tsGreen = tsGreen;
  826. _tsBlue = tsBlue;
  827. }
  828. /**
  829. * @brief 设置分时MA线颜色的方法
  830. *
  831. * @param tsMARed 分时MA线红色值
  832. * @param tsMAGreen 分时MA线绿色值
  833. * @param tsMABlue 分时MA线蓝色值
  834. * @param tsMAAlpha 分时MA线alpha值
  835. */
  836. - (void)setTsMARed:(CGFloat)tsMARed tsMAGreen:(CGFloat)tsMAGreen tsMABlue:(CGFloat)tsMABlue tsMAAlpha:(CGFloat)tsMAAlpha {
  837. _tsMARed = tsMARed;
  838. _tsMAGreen = tsMAGreen;
  839. _tsMABlue = tsMABlue;
  840. _tsMAAlpha = tsMAAlpha;
  841. }
  842. /**
  843. * @brief 设置MACD DIF线颜色的方法
  844. *
  845. * @param macdDIFRed MACD DIF线红色值
  846. * @param macdDIFGreen MACD DIF线绿色值
  847. * @param macdDIFBlue MACD DIF线蓝色值
  848. * @param macdDIFAlpha MACD DIF线alpha值
  849. */
  850. - (void)setMacdDIFRed:(CGFloat)macdDIFRed macdDIFGreen:(CGFloat)macdDIFGreen macdDIFBlue:(CGFloat)macdDIFBlue macdDIFAlpha:(CGFloat)macdDIFAlpha {
  851. _macdDIFRed = macdDIFRed;
  852. _macdDIFGreen = macdDIFGreen;
  853. _macdDIFBlue = macdDIFBlue;
  854. _macdDIFAlpha = macdDIFAlpha;
  855. }
  856. /**
  857. * @brief 设置MACD DEA线颜色的方法
  858. *
  859. * @param macdDEARed MACD DEA线红色值
  860. * @param macdDEAGreen MACD DEA线绿色值
  861. * @param macdDEABlue MACD DEA线蓝色值
  862. * @param macdDEAAlpha MACD DEA线alpha值
  863. */
  864. - (void)setMacdDEARed:(CGFloat)macdDEARed macdDEAGreen:(CGFloat)macdDEAGreen macdDEABlue:(CGFloat)macdDEABlue macdDEAAlpha:(CGFloat)macdDEAAlpha {
  865. _macdDEARed = macdDEARed;
  866. _macdDEAGreen = macdDEAGreen;
  867. _macdDEABlue = macdDEABlue;
  868. _macdDEAAlpha = macdDEAAlpha;
  869. }
  870. /**
  871. * @brief 设置RSI RSI1线颜色的方法
  872. *
  873. * @param rsi1Red RSI RSI1线红色值
  874. * @param rsi1Green RSI RSI1线绿色值
  875. * @param rsi1Blue RSI RSI1线蓝色值
  876. * @param rsi1Alpha RSI RSI1线alpha值
  877. */
  878. - (void)setRSI1Red:(CGFloat)rsi1Red rsi1Green:(CGFloat)rsi1Green rsi1Blue:(CGFloat)rsi1Blue rsi1Alpha:(CGFloat)rsi1Alpha {
  879. _rsi1Red = rsi1Red;
  880. _rsi1Green = rsi1Green;
  881. _rsi1Blue = rsi1Blue;
  882. _rsi1Alpha = rsi1Alpha;
  883. }
  884. /**
  885. * @brief 设置RSI RSI2线颜色的方法
  886. *
  887. * @param rsi2Red RSI RSI2线红色值
  888. * @param rsi2Green RSI RSI2线绿色值
  889. * @param rsi2Blue RSI RSI2线蓝色值
  890. * @param rsi2Alpha RSI RSI2线alpha值
  891. */
  892. - (void)setRSI2Red:(CGFloat)rsi2Red rsi2Green:(CGFloat)rsi2Green rsi2Blue:(CGFloat)rsi2Blue rsi2Alpha:(CGFloat)rsi2Alpha {
  893. _rsi2Red = rsi2Red;
  894. _rsi2Green = rsi2Green;
  895. _rsi2Blue = rsi2Blue;
  896. _rsi2Alpha = rsi2Alpha;
  897. }
  898. /**
  899. * @brief 设置RSI RSI3线颜色的方法
  900. *
  901. * @param rsi3Red RSI RSI3线红色值
  902. * @param rsi3Green RSI RSI3线绿色值
  903. * @param rsi3Blue RSI RSI3线蓝色值
  904. * @param rsi3Alpha RSI RSI3线alpha值
  905. */
  906. - (void)setRSI3Red:(CGFloat)rsi3Red rsi3Green:(CGFloat)rsi3Green rsi3Blue:(CGFloat)rsi3Blue rsi3Alpha:(CGFloat)rsi3Alpha {
  907. _rsi3Red = rsi3Red;
  908. _rsi3Green = rsi3Green;
  909. _rsi3Blue = rsi3Blue;
  910. _rsi3Alpha = rsi3Alpha;
  911. }
  912. /**
  913. * @brief 设置KT KT线颜色的方法
  914. *
  915. * @param ktRed KT KT线红色值
  916. * @param ktGreen KT KT线绿色值
  917. * @param ktBlue KT KT线蓝色值
  918. * @param ktAlpha KT KT线alpha值
  919. */
  920. - (void)setKTRed:(CGFloat)ktRed ktGreen:(CGFloat)ktGreen ktBlue:(CGFloat)ktBlue ktAlpha:(CGFloat)ktAlpha {
  921. _ktRed = ktRed;
  922. _ktGreen = ktGreen;
  923. _ktBlue = ktBlue;
  924. _ktAlpha = ktAlpha;
  925. }
  926. /**
  927. * @brief 设置DT DT线颜色的方法
  928. *
  929. * @param dtRed DT DT线红色值
  930. * @param dtGreen DT DT线绿色值
  931. * @param dtBlue DT DT线蓝色值
  932. * @param dtAlpha DT DT线alpha值
  933. */
  934. - (void)setDTRed:(CGFloat)dtRed dtGreen:(CGFloat)dtGreen dtBlue:(CGFloat)dtBlue dtAlpha:(CGFloat)dtAlpha {
  935. _dtRed = dtRed;
  936. _dtGreen = dtGreen;
  937. _dtBlue = dtBlue;
  938. _dtAlpha = dtAlpha;
  939. }
  940. /**
  941. * @brief 设置JT JT线颜色的方法
  942. *
  943. * @param jtRed JT JT线红色值
  944. * @param jtGreen JT JT线绿色值
  945. * @param jtBlue JT JT线蓝色值
  946. * @param jtAlpha JT JT线alpha值
  947. */
  948. - (void)setJTRed:(CGFloat)jtRed jtGreen:(CGFloat)jtGreen jtBlue:(CGFloat)jtBlue jtAlpha:(CGFloat)jtAlpha {
  949. _jtRed = jtRed;
  950. _jtBlue = jtBlue;
  951. _jtGreen = jtGreen;
  952. _jtAlpha = jtAlpha;
  953. }
  954. /**
  955. * @brief 设置CCI CCI线颜色的方法
  956. *
  957. * @param cciRed CCI CCI线红色值
  958. * @param cciGreen CCI CCI线绿色值
  959. * @param cciBlue CCI CCI线蓝色值
  960. * @param cciAlpha CCI CCI线alpha值
  961. */
  962. - (void)setCCIRed:(CGFloat)cciRed cciGreen:(CGFloat)cciGreen cciBlue:(CGFloat)cciBlue cciAlpha:(CGFloat)cciAlpha {
  963. _cciRed = cciRed;
  964. _cciGreen = cciGreen;
  965. _cciBlue = cciBlue;
  966. _cciAlpha = cciAlpha;
  967. }
  968. /**
  969. * @brief 设置DMA线颜色的方法
  970. *
  971. * @param dmaRed DMA线红色值
  972. * @param dmaGreen DMA线绿色值
  973. * @param dmaBlue DMA线蓝色值
  974. * @param dmaAlpha DMA线alpha值
  975. */
  976. - (void)setDMARed:(CGFloat)dmaRed dmaGreen:(CGFloat)dmaGreen cciBlue:(CGFloat)dmaBlue cciAlpha:(CGFloat)dmaAlpha {
  977. _dmaRed = dmaRed;
  978. _dmaGreen = dmaGreen;
  979. _dmaBlue = dmaBlue;
  980. _dmaAlpha = dmaAlpha;
  981. }
  982. /**
  983. * @brief 设置AMA线颜色的方法
  984. *
  985. * @param amaRed AMA线红色值
  986. * @param amaGreen AMA线绿色值
  987. * @param amaBlue AMA线蓝色值
  988. * @param amaAlpha AMA线alpha值
  989. */
  990. - (void)setAMARed:(CGFloat)amaRed amaGreen:(CGFloat)amaGreen cciBlue:(CGFloat)amaBlue cciAlpha:(CGFloat)amaAlpha {
  991. _amaRed = amaRed;
  992. _amaGreen = amaGreen;
  993. _amaBlue = amaBlue;
  994. _amaAlpha = amaAlpha;
  995. }
  996. /**
  997. * @brief 设置BIAS BIAS1线颜色的方法
  998. *
  999. * @param bias1Red BIAS BIAS1线红色值
  1000. * @param bias1Green BIAS BIAS1线绿色值
  1001. * @param bias1Blue BIAS BIAS1线蓝色值
  1002. * @param bias1Alpha BIAS BIAS1线alpha值
  1003. */
  1004. - (void)setBIAS1Red:(CGFloat)bias1Red bias1Green:(CGFloat)bias1Green bias1Blue:(CGFloat)bias1Blue bias1Alpha:(CGFloat)bias1Alpha {
  1005. _bias1Red = bias1Red;
  1006. _bias1Green = bias1Green;
  1007. _bias1Blue = bias1Blue;
  1008. _bias1Alpha = bias1Alpha;
  1009. }
  1010. /**
  1011. * @brief 设置BIAS BIAS2线颜色的方法
  1012. *
  1013. * @param bias2Red BIAS BIAS2线红色值
  1014. * @param bias2Green BIAS BIAS2线绿色值
  1015. * @param bias2Blue BIAS BIAS2线蓝色值
  1016. * @param bias2Alpha BIAS BIAS2线alpha值
  1017. */
  1018. - (void)setBIAS2Red:(CGFloat)bias2Red bias2Green:(CGFloat)bias2Green bias2Blue:(CGFloat)bias2Blue bias2Alpha:(CGFloat)bias2Alpha {
  1019. _bias2Red = bias2Red;
  1020. _bias2Green = bias2Green;
  1021. _bias2Blue = bias2Blue;
  1022. _bias2Alpha = bias2Alpha;
  1023. }
  1024. /**
  1025. * @brief 设置BIAS BIAS3线颜色的方法
  1026. *
  1027. * @param bias3Red BIAS BIAS3线红色值
  1028. * @param bias3Green BIAS BIAS3线绿色值
  1029. * @param bias3Blue BIAS BIAS3线蓝色值
  1030. * @param bias3Alpha BIAS BIAS3线alpha值
  1031. */
  1032. - (void)setBIAS3Red:(CGFloat)bias3Red bias3Green:(CGFloat)bias3Green bias3Blue:(CGFloat)bias3Blue bias3Alpha:(CGFloat)bias3Alpha {
  1033. _bias3Red = bias3Red;
  1034. _bias3Green = bias3Green;
  1035. _bias3Blue = bias3Blue;
  1036. _bias3Alpha = bias3Alpha;
  1037. }
  1038. /**
  1039. * @brief 设置PSY PSY线颜色的方法
  1040. *
  1041. * @param psyRed PSY PSY线红色值
  1042. * @param psyGreen PSY PSY线绿色值
  1043. * @param psyBlue PSY PSY线蓝色值
  1044. * @param psyAlpha PSY PSY线alpha值
  1045. */
  1046. - (void)setPSYRed:(CGFloat)psyRed psyGreen:(CGFloat)psyGreen psyBlue:(CGFloat)psyBlue psyAlpha:(CGFloat)psyAlpha {
  1047. _psyRed = psyRed;
  1048. _psyGreen = psyGreen;
  1049. _psyBlue = psyBlue;
  1050. _psyAlpha = psyAlpha;
  1051. }
  1052. /**
  1053. * @brief 设置PSYMA PSYMA线颜色的方法
  1054. *
  1055. * @param psymaRed PSYMA PSYMA线红色值
  1056. * @param psymaGreen PSYMA PSYMA线绿色值
  1057. * @param psymaBlue PSYMA PSYMA线蓝色值
  1058. * @param psymaAlpha PSYMA PSYMA线alpha值
  1059. */
  1060. - (void)setPSYMARed:(CGFloat)psymaRed psymaGreen:(CGFloat)psymaGreen psymaBlue:(CGFloat)psymaBlue psymaAlpha:(CGFloat)psymaAlpha {
  1061. _psymaRed = psymaRed;
  1062. _psymaGreen = psymaGreen;
  1063. _psymaBlue = psymaBlue;
  1064. _psymaAlpha = psymaAlpha;
  1065. }
  1066. #pragma mark - 画坐标轴相关
  1067. /**
  1068. * @brief 更新数据的方法,主要用于更新图表
  1069. */
  1070. - (void)updateData {
  1071. //当前可视坐标最高价=当前可视最高价+几个点(这几个点应该从当前可视最高与最低价点差计算得出)
  1072. NSDecimalNumber *maxValue = [self maxPriceAtVisible];
  1073. NSDecimalNumber *minValue = [self minPriceAtVisible];
  1074. // 这里有可能最大值和最小值相等
  1075. if ([maxValue compare:minValue] == NSOrderedSame) {
  1076. ChartData *chartData = _chartDataArray[0];
  1077. maxValue = [chartData.closed decimalNumberByAdding:[_minUnit decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInt:20]]];
  1078. }
  1079. //如果当前是分时图,要重新计算最高最低价,以便让昨收线在中间
  1080. if (_chartViewType == ChartViewTypeTSPlan) {
  1081. NSDecimalNumber *diffMax = [ChartCalculateUtils abs:[_preClose decimalNumberBySubtracting:maxValue]];
  1082. NSDecimalNumber *diffMin = [ChartCalculateUtils abs:[_preClose decimalNumberBySubtracting:minValue]];
  1083. if ([diffMax compare:diffMin] == NSOrderedDescending) {
  1084. //最高与昨收的差比最低的大
  1085. maxValue = [_preClose decimalNumberByAdding:diffMax];
  1086. minValue = [_preClose decimalNumberBySubtracting:diffMax];
  1087. } else {
  1088. //反之
  1089. maxValue = [_preClose decimalNumberByAdding:diffMin];
  1090. minValue = [_preClose decimalNumberBySubtracting:diffMin];
  1091. }
  1092. }
  1093. //最多10个点的高低值
  1094. NSDecimalNumberHandler *behavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:0 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
  1095. NSInteger stepValue = [[[[[maxValue decimalNumberBySubtracting:minValue] decimalNumberByDividingBy:_minUnit] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"10"]] decimalNumberByRoundingAccordingToBehavior:behavior] integerValue];
  1096. if (stepValue > 10)
  1097. stepValue = 10;
  1098. NSString *stepString = [NSString stringWithFormat:@"%d",(int)stepValue];
  1099. _yAxisMaxValue = [[maxValue decimalNumberByAdding:[_minUnit decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:stepString]]] floatValue];
  1100. _yAxisMinValue = [[minValue decimalNumberBySubtracting:[_minUnit decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:stepString]]] floatValue];
  1101. }
  1102. /**
  1103. * @brief 画框架
  1104. */
  1105. - (void)drawBorder {
  1106. CGContextRef context = UIGraphicsGetCurrentContext();
  1107. //整体相关
  1108. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  1109. CGContextSetRGBFillColor(context, _bgRed, _bgGreen, _bgBlue, 1.0f);
  1110. CGContextFillRect(context, self.bounds);
  1111. //边框相关
  1112. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha];
  1113. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  1114. CGContextSetLineWidth(context, 1.0f);
  1115. CGContextAddRect(context, CGRectMake(_kLineOrigin.x, _yAxisPaddingTop, _xAxisWidth, _yAxisHeight));
  1116. #ifdef DEBUG
  1117. // NSLog(@"%s _yAxisHeight:%f", __func__, _yAxisHeight);
  1118. #endif
  1119. NSString *targetTitle = [[NSString alloc] init];
  1120. //指标相关
  1121. if (_isShowIndicator) {
  1122. if (_chartViewType == ChartViewTypeKL) {
  1123. CGContextAddRect(context, CGRectMake(_indicatorOrigin.x, _indicatorOrigin.y-_indicatorHight, _xAxisWidth, _indicatorHight));
  1124. CGContextStrokePath(context);
  1125. if (_chartTargetType == MACD) {
  1126. //MACD标题
  1127. targetTitle = @"MACD(12,26,9)";
  1128. } else if (_chartTargetType == VOL) {
  1129. //VOL标题
  1130. targetTitle = @"VOL(5,10)";
  1131. } else if (_chartTargetType == KDJ) {
  1132. //KDJ标题
  1133. targetTitle = @"KDJ(9,3,3)";
  1134. } else if (_chartTargetType == RSI) {
  1135. //RSI标题
  1136. targetTitle = @"RSI(6,12,24)";
  1137. } else if (_chartTargetType == CCI) {
  1138. //CCI标题
  1139. targetTitle = @"CCI(14)";
  1140. } else if (_chartTargetType == DMA) {
  1141. //DMA标题
  1142. targetTitle = @"DMA(10,50,10)";
  1143. } else if (_chartTargetType == KD) {
  1144. //KD标题
  1145. targetTitle = @"KD(9,3)";
  1146. } else if (_chartTargetType == BIAS) {
  1147. //BIAS标题
  1148. targetTitle = @"BIAS(6,12,24)";
  1149. } else if (_chartTargetType == PSY) {
  1150. //PSY标题
  1151. targetTitle = @"PSY(12,6)";
  1152. }
  1153. }
  1154. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; // 价格左边距
  1155. // 写数据
  1156. NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:targetTitle attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:_titleColor}];
  1157. [tipString drawAtPoint:CGPointMake(priceXOffset - 60.0f, _indicatorOrigin.y - _indicatorHight - 15.0f)];
  1158. }
  1159. }
  1160. /**
  1161. * @brief 画X轴
  1162. */
  1163. - (void)drawXAxis {
  1164. //时间格式化
  1165. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  1166. /// 分时图
  1167. dateFormatter.dateFormat = _chartViewType == ChartViewTypeTSPlan ? @"HH:mm" : @"MM-dd HH:mm";
  1168. if (_chartViewType == ChartViewTypeTSPlan) {//分时图
  1169. //开盘时间
  1170. [_lineColor setFill];
  1171. [_titleColor set];
  1172. [[dateFormatter stringFromDate:_tsStartTime] drawAtPoint:_kLineOrigin withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1173. //收盘时间
  1174. [_titleColor set];
  1175. CGFloat dateStringWidth = [[dateFormatter stringFromDate:_tsCloseTime] sizeWithAttributes:@{NSFontAttributeName:_titleFont}].width;
  1176. [_titleColor set];
  1177. [[dateFormatter stringFromDate:_tsCloseTime] drawAtPoint:CGPointMake(_kLineOrigin.x + _xAxisWidth - dateStringWidth, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1178. } else {//K线或即时线
  1179. //起始时间
  1180. ChartData *startChartData = [_chartDataArray objectAtIndex:_kLineStartIndex];
  1181. [_lineColor setFill];
  1182. [_titleColor set];
  1183. [[dateFormatter stringFromDate:startChartData.startTime] drawAtPoint:_kLineOrigin withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1184. //结束时间,如果K线数量不足整屏则不显示结束时间
  1185. if (_chartDataArray.count >= _kLineCount) {
  1186. ChartData *endChartData = [_chartDataArray objectAtIndex:_kLineEndIndex];
  1187. CGFloat dateStringWidth = [[dateFormatter stringFromDate:endChartData.startTime] sizeWithAttributes:@{NSFontAttributeName:_titleFont}].width;
  1188. [_titleColor set];
  1189. [[dateFormatter stringFromDate:endChartData.startTime] drawAtPoint:CGPointMake(_kLineOrigin.x + _xAxisWidth - dateStringWidth, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1190. }
  1191. }
  1192. }
  1193. /**
  1194. * @brief 画Y轴
  1195. */
  1196. - (void)drawYAxis {
  1197. //当前可视坐标最高价=当前可视最高价+几个点(这几个点应该从当前可视最高与最低价点差计算得出)
  1198. NSDecimalNumber *maxValue = [self maxPriceAtVisible];
  1199. NSDecimalNumber *minValue = [self minPriceAtVisible];
  1200. // 这里有可能最大值和最小值相等
  1201. if ([maxValue compare:minValue] == NSOrderedSame) {
  1202. ChartData *chartData = _chartDataArray[0];
  1203. maxValue = [chartData.closed decimalNumberByAdding:[_minUnit decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInt:20]]];
  1204. }
  1205. //如果当前是分时图,要重新计算最高最低价,以便让昨收线在中间
  1206. if (_chartViewType == ChartViewTypeTSPlan) {
  1207. NSDecimalNumber *diffMax = [ChartCalculateUtils abs:[_preClose decimalNumberBySubtracting:maxValue]];
  1208. NSDecimalNumber *diffMin = [ChartCalculateUtils abs:[_preClose decimalNumberBySubtracting:minValue]];
  1209. if ([diffMax compare:diffMin] == NSOrderedDescending) {
  1210. //最高与昨收的差比最低的大
  1211. maxValue = [_preClose decimalNumberByAdding:diffMax];
  1212. minValue = [_preClose decimalNumberBySubtracting:diffMax];
  1213. } else {
  1214. //反之
  1215. maxValue = [_preClose decimalNumberByAdding:diffMin];
  1216. minValue = [_preClose decimalNumberBySubtracting:diffMin];
  1217. }
  1218. }
  1219. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  1220. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha];
  1221. CGContextRef context = UIGraphicsGetCurrentContext();
  1222. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  1223. //画线
  1224. CGContextSetLineWidth(context, 1.0f);
  1225. //当前可视最高价线
  1226. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:maxValue]);
  1227. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:maxValue]);
  1228. //当前可视最低价线
  1229. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:minValue]);
  1230. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:minValue]);
  1231. //二等分价线
  1232. NSDecimalNumber *averagePrice = [[[maxValue decimalNumberBySubtracting:minValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]] decimalNumberByAdding:minValue];
  1233. if (_chartViewType != ChartViewTypeTSPlan) {
  1234. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:averagePrice]);
  1235. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:averagePrice]);
  1236. }
  1237. //四等分价线(高)
  1238. NSDecimalNumber *quarterHighPrice = [averagePrice decimalNumberByAdding:[[averagePrice decimalNumberBySubtracting:minValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]]];
  1239. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:quarterHighPrice]);
  1240. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:quarterHighPrice]);
  1241. //四等分价线(低)
  1242. NSDecimalNumber *quarterLowPrice = [averagePrice decimalNumberBySubtracting:[[averagePrice decimalNumberBySubtracting:minValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]]];
  1243. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:quarterLowPrice]);
  1244. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:quarterLowPrice]);
  1245. CGContextStrokePath(context);
  1246. //写价格
  1247. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  1248. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  1249. //K线最高价
  1250. [_titleColor set];
  1251. NSString *maxPriceString = [ChartCalculateUtils notRounding:maxValue afterPoint:digitCount];
  1252. [maxPriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:maxValue] - [maxPriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1253. //K线最低价
  1254. NSString *minPriceString = [ChartCalculateUtils notRounding:minValue afterPoint:digitCount];
  1255. [minPriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:minValue] - [maxPriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1256. //二等分价
  1257. if (_chartViewType != ChartViewTypeTSPlan) {
  1258. NSString *averagePriceString = [ChartCalculateUtils notRounding:averagePrice afterPoint:digitCount];
  1259. [averagePriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:averagePrice] - [averagePriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1260. }
  1261. //四等分价(高)
  1262. NSString *quarterHighPriceString = [ChartCalculateUtils notRounding:quarterHighPrice afterPoint:digitCount];
  1263. [quarterHighPriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:quarterHighPrice] - [quarterHighPriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1264. //四等分价(低)
  1265. NSString *quarterLowPriceString = [ChartCalculateUtils notRounding:quarterLowPrice afterPoint:digitCount];
  1266. [quarterLowPriceString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:quarterLowPrice] - [quarterLowPriceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1267. //分时图画昨收线与昨收价
  1268. if (_chartViewType == ChartViewTypeTSPlan) {
  1269. CGContextSetRGBStrokeColor(context, _preCloseLineRed, _preCloseLineGreen, _preCloseLineBlue, _preCloseLineAlpha);
  1270. CGFloat dashes[] = { 4, 3 };
  1271. CGContextSetLineDash( context, 0.0, dashes, 2 );
  1272. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:_preClose]);
  1273. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth,[self yPointWithPrice:_preClose]);
  1274. CGContextStrokePath(context);
  1275. CGContextSetLineDash(context, 0.0, dashes, 0);
  1276. [[UIColor colorWithRed:_preCloseLineRed green:_preCloseLineGreen blue:_preCloseLineBlue alpha:_preCloseLineAlpha] set];
  1277. NSString *preCloseString = [ChartCalculateUtils notRounding:_preClose afterPoint:digitCount];
  1278. [preCloseString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPointWithPrice:_preClose] - [preCloseString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  1279. }
  1280. }
  1281. #pragma mark - 画K线相关
  1282. /**
  1283. * @brief 画K线的方法
  1284. */
  1285. - (void)drawKLine {
  1286. CGContextRef context = UIGraphicsGetCurrentContext();
  1287. CGFloat currentXPonit = _kLineOrigin.x + 1.0f;
  1288. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1289. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1290. if ([chartData.closed compare:chartData.opened] == NSOrderedAscending) {
  1291. //close < open
  1292. CGContextSetRGBFillColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
  1293. CGContextAddRect(context, CGRectMake(currentXPonit, [self yPointWithPrice:chartData.opened], _kLineWidth, [self yPointWithPrice:chartData.closed] - [self yPointWithPrice:chartData.opened]));
  1294. CGContextFillPath(context);
  1295. if ([chartData.highest compare:chartData.opened] == NSOrderedDescending) {
  1296. //high > open
  1297. CGContextSetRGBStrokeColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
  1298. CGContextSetLineWidth(context, 1.0f);
  1299. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.highest]);
  1300. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.opened]);
  1301. CGContextStrokePath(context);
  1302. }
  1303. if ([chartData.lowest compare:chartData.closed] == NSOrderedAscending) {
  1304. //low < close
  1305. CGContextSetRGBStrokeColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
  1306. CGContextSetLineWidth(context, 1.0f);
  1307. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.closed]);
  1308. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.lowest]);
  1309. CGContextStrokePath(context);
  1310. }
  1311. } else if ([chartData.closed compare:chartData.opened] == NSOrderedDescending) {
  1312. //close > open
  1313. CGContextSetRGBFillColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
  1314. CGContextAddRect(context, CGRectMake(currentXPonit, [self yPointWithPrice:chartData.closed], _kLineWidth, [self yPointWithPrice:chartData.opened] - [self yPointWithPrice:chartData.closed]));
  1315. CGContextFillPath(context);
  1316. if ([chartData.highest compare:chartData.closed] == NSOrderedDescending) {
  1317. CGContextSetRGBStrokeColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
  1318. //high > close
  1319. CGContextSetLineWidth(context, 1.0f);
  1320. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.highest]);
  1321. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.closed]);
  1322. CGContextStrokePath(context);
  1323. }
  1324. if ([chartData.lowest compare:chartData.opened] == NSOrderedAscending) {
  1325. //low < close
  1326. CGContextSetRGBStrokeColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
  1327. //low < open
  1328. CGContextSetLineWidth(context, 1.0f);
  1329. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.opened]);
  1330. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.lowest]);
  1331. CGContextStrokePath(context);
  1332. }
  1333. CGContextStrokePath(context);
  1334. } else {
  1335. //close == open
  1336. CGContextSetRGBStrokeColor(context, _samKRed, _samKGreen, _samKBlue, _samKAlpha);
  1337. CGContextSetLineWidth(context, 1.0f);
  1338. CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
  1339. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth, [self yPointWithPrice:chartData.closed]);
  1340. if ([chartData.highest compare:chartData.closed] == NSOrderedDescending) {
  1341. //high > close
  1342. CGContextSetLineWidth(context, 1.0f);
  1343. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.highest]);
  1344. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.closed]);
  1345. }
  1346. if ([chartData.lowest compare:chartData.closed] == NSOrderedAscending) {
  1347. //low < open
  1348. CGContextSetLineWidth(context, 1.0f);
  1349. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.closed]);
  1350. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yPointWithPrice:chartData.lowest]);
  1351. }
  1352. CGContextStrokePath(context);
  1353. }
  1354. //是否需要显示十字线
  1355. if (_isShowTipLine) {
  1356. /// 是否需要长显示开高低收
  1357. [self showOHLPPriceWithIsKLine:YES isShow:NO];
  1358. if (_tipLineIndex == i) {
  1359. /// 画垂直线
  1360. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  1361. CGContextSetLineWidth(context, 1.0f);
  1362. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, _yAxisPaddingTop);
  1363. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, _kLineOrigin.y);
  1364. /// 画水平线
  1365. CGContextMoveToPoint(context, _kLineOrigin.x, _tipLineYAxis);
  1366. CGContextAddLineToPoint(context, _kLineOrigin.x + _xAxisWidth , _tipLineYAxis);
  1367. CGContextStrokePath(context);
  1368. /// 写数据
  1369. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  1370. NSString *ma5 = [ChartCalculateUtils notRounding:chartData.ma5 afterPoint:digitCount];
  1371. UIColor *profileColor = nil;
  1372. if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
  1373. profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
  1374. else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
  1375. profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
  1376. else
  1377. profileColor = _titleColor;
  1378. /// 写数据
  1379. NSMutableAttributedString *MAString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@ ", ma5 ? ma5 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA5Red green:_kMA5Green blue:_kMA5Blue alpha:_kMA5Alpha], NSFontAttributeName:_titleFont}];
  1380. NSString *ma10 = [ChartCalculateUtils notRounding:chartData.ma10 afterPoint:digitCount];
  1381. [MAString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@ ",ma10 ? ma10 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA10Red green:_kMA10Green blue:_kMA10Blue alpha:_kMA10Alpha], NSFontAttributeName:_titleFont}]];
  1382. NSString *ma15 = [ChartCalculateUtils notRounding:chartData.ma15 afterPoint:digitCount];
  1383. [MAString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA15:%@ ",ma15 ? ma15 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA15Red green:_kMA15Green blue:_kMA15Blue alpha:_kMA15Alpha], NSFontAttributeName:_titleFont}]];
  1384. 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}];
  1385. // 横屏一排显示就够了
  1386. if (self.frame.size.width < self.frame.size.height) {
  1387. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, 12.0f)];
  1388. } else {
  1389. [MAString appendAttributedString:tipString];
  1390. }
  1391. [MAString drawAtPoint:CGPointMake(_kLineOrigin.x, 0)];
  1392. //纵轴时间
  1393. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  1394. if (self.cycleInterval == 30 * 24 * 60 * 60) {
  1395. dateFormatter.dateFormat = @"MM-dd";
  1396. } else {
  1397. dateFormatter.dateFormat = @"MM-dd HH:mm";
  1398. }
  1399. NSString *dateTime = [dateFormatter stringFromDate:chartData.startTime];
  1400. CGSize dateTimeSize = [dateTime sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  1401. CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  1402. CGFloat x = currentXPonit+_kLineWidth/2-dateTimeSize.width/2;
  1403. if (x < _xAxisPaddingLeft)
  1404. x = _xAxisPaddingLeft;
  1405. else if (x > _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width)
  1406. x = _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width;
  1407. CGContextAddRect(context, CGRectMake(x, _kLineOrigin.y, dateTimeSize.width, dateTimeSize.height));
  1408. CGContextFillPath(context);
  1409. [_tipTitleColor set];
  1410. [dateTime drawAtPoint:CGPointMake(x, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
  1411. //横轴价格
  1412. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  1413. NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
  1414. NSDecimalNumber *yPrice = [self priceWithYPoint:_tipLineYAxis];
  1415. NSString *priceString = [ChartCalculateUtils notRounding:yPrice afterPoint:decimalNumber];
  1416. CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  1417. CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  1418. CGContextAddRect(context, CGRectMake(priceXOffset, _tipLineYAxis-priceStringSize.height/2, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
  1419. CGContextFillPath(context);
  1420. [_tipTitleColor set];
  1421. [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, _tipLineYAxis-priceStringSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
  1422. }
  1423. } else {
  1424. /// 是否需要长显示开高低收
  1425. [self showOHLPPriceWithIsKLine:YES isShow:YES];
  1426. }
  1427. currentXPonit += _kLineWidth + _kLinePadding;
  1428. }
  1429. }
  1430. #pragma mark - 十字线相关
  1431. /**
  1432. * @brief 通过x坐标获取对应K线数据下标
  1433. *
  1434. * @param xPoint x坐标
  1435. *
  1436. * @return K线数据下标
  1437. */
  1438. - (NSInteger)tipIndexWithXPoint:(CGFloat)xPoint {
  1439. NSInteger tipIndex = NSNotFound;
  1440. CGFloat currentXPonit = _kLineOrigin.x + 1.0f;
  1441. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1442. //要把K线的间隔也算上
  1443. CGRect kLineRect = CGRectMake(currentXPonit, _yAxisPaddingTop, _kLineWidth+_kLinePadding, _yAxisHeight);
  1444. if (CGRectContainsPoint(kLineRect, CGPointMake(xPoint, _yAxisPaddingTop+10.0f))) {
  1445. tipIndex = i;
  1446. break;
  1447. }
  1448. currentXPonit += _kLineWidth + _kLinePadding;
  1449. }
  1450. return tipIndex;
  1451. }
  1452. /**
  1453. * @brief 通过x坐标获取对应分时数据下标
  1454. *
  1455. * @param xPoint x坐标
  1456. *
  1457. * @return 分时数据下标
  1458. */
  1459. - (NSInteger)tipIndexTSPlanWithXPoint:(CGFloat)xPoint {
  1460. NSInteger tipIndex = NSNotFound;
  1461. CGFloat currentXPonit = _tsStartXPonit;
  1462. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1463. //要把K线的间隔也算上
  1464. CGRect kLineRect = CGRectMake(currentXPonit, _yAxisPaddingTop, _xAxisWidth/_kLineCount, _yAxisHeight);
  1465. if (CGRectContainsPoint(kLineRect, CGPointMake(xPoint, _yAxisPaddingTop+10.0f))) {
  1466. tipIndex = i;
  1467. break;
  1468. }
  1469. currentXPonit += _xAxisWidth/_kLineCount;
  1470. }
  1471. return tipIndex;
  1472. }
  1473. #pragma mark - 图表数据计算相关
  1474. /**
  1475. * @brief 初始计算各平均线数据的方法
  1476. *
  1477. * @param index 需要刷新数据的0-index的范围
  1478. */
  1479. - (void)initAverageLineDataWithIndex:(NSInteger)index {
  1480. //当前总合,主要用于分时图
  1481. NSDecimalNumber *totalPrice = [NSDecimalNumber zero];
  1482. NSDecimalNumber *totalNumber = [NSDecimalNumber zero];
  1483. for (NSInteger i=index ; i>=0 ; i--) {
  1484. /// m5
  1485. if (index-i>=4) {
  1486. ChartData *chartData = nil;
  1487. NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
  1488. for (NSInteger j=i+4; j>=i ; j--) {
  1489. chartData = [_chartDataArray objectAtIndex:j];
  1490. totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
  1491. }
  1492. chartData.ma5 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"5"]];
  1493. }
  1494. /// m10
  1495. if (index-i>=9) {
  1496. ChartData *chartData = nil;
  1497. NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
  1498. for (NSInteger j=i+9; j>=i ; j--) {
  1499. chartData = [_chartDataArray objectAtIndex:j];
  1500. totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
  1501. }
  1502. chartData.ma10 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"10"]];
  1503. }
  1504. /// m15
  1505. if (index-i>=14) {
  1506. ChartData *chartData = nil;
  1507. NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
  1508. for (NSInteger j=i+14; j>=i ; j--) {
  1509. chartData = [_chartDataArray objectAtIndex:j];
  1510. totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
  1511. }
  1512. chartData.ma15 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"15"]];
  1513. }
  1514. /// m50
  1515. if (index-i>=49) {
  1516. ChartData *chartData = nil;
  1517. NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
  1518. for (NSInteger j=i+49 ; j>=i ; j--) {
  1519. chartData = [_chartDataArray objectAtIndex:j];
  1520. totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
  1521. }
  1522. chartData.ma50 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"50"]];
  1523. }
  1524. //****************** MACD ********************
  1525. //EMA12
  1526. if (index-i>=11) {
  1527. if (index-i == 11) {
  1528. //第一个EMA12是前12个收盘价代数平均
  1529. NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
  1530. ChartData *chartData = nil;
  1531. for (NSInteger j=i+11 ; j>=i ; j--) {
  1532. chartData = [_chartDataArray objectAtIndex:j];
  1533. totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
  1534. }
  1535. chartData.ema12 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"]];
  1536. }
  1537. else {
  1538. //今日EMA(12) = 2/(12+1)×今日收盘价 + 11/(12+1)×昨日EMA(12)<-错的 EMA12 = 前一日EMA12 X 11/13 + 今日收盘 X 2/13
  1539. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1540. ChartData *yesterdayChartData = [_chartDataArray objectAtIndex:i+1];
  1541. 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"]])];
  1542. }
  1543. }
  1544. //EMA26 & DIF
  1545. if (index-i>=25) {
  1546. if (index-i == 25) {
  1547. NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
  1548. ChartData *chartData = nil;
  1549. for (NSInteger j=i+25 ; j>=i ; j--) {
  1550. chartData = [_chartDataArray objectAtIndex:j];
  1551. totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.closed];
  1552. }
  1553. chartData.ema26 = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"26"]];
  1554. chartData.dif = [chartData.ema12 decimalNumberBySubtracting:chartData.ema26];
  1555. }
  1556. else {
  1557. //今日EMA(26)=2/(26+1)×今日收盘价+25/(26+1)×昨日EMA(26)<-错的 EMA26 = 前一日EMA26 X 25/27 + 今日收盘 X 2/27
  1558. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1559. ChartData *yesterdayChartData = [_chartDataArray objectAtIndex:i+1];
  1560. 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"]])];
  1561. chartData.dif = [chartData.ema12 decimalNumberBySubtracting:chartData.ema26];
  1562. }
  1563. }
  1564. //DEA & MACD
  1565. if (index-i>=34) {
  1566. if (index-i == 34) {
  1567. ChartData *chartData = nil;
  1568. NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
  1569. for (NSInteger j=i+9 ; j>=i ; j--) {
  1570. chartData = [_chartDataArray objectAtIndex:j];
  1571. totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.dif];
  1572. }
  1573. chartData.dea = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"9"]];
  1574. // macd = (dif-dea)*2
  1575. chartData.macd = [[NSDecimalNumber decimalNumberWithString:@"2"] decimalNumberByMultiplyingBy:([chartData.dif decimalNumberBySubtracting:chartData.dea])];
  1576. }
  1577. else {
  1578. //今日DEA=(前一日DEA X 8/10 + 今日DIF X 2/10)
  1579. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1580. ChartData *yesterdayChartData = [_chartDataArray objectAtIndex:i+1];
  1581. chartData.dea = [[[ChartCalculateUtils notRoundingWithDecimalNumber:yesterdayChartData.dea afterPoint:5] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"0.8"]] decimalNumberByAdding:([chartData.dif decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"0.2"]])];
  1582. chartData.macd = [[NSDecimalNumber decimalNumberWithString:@"2"] decimalNumberByMultiplyingBy:([chartData.dif decimalNumberBySubtracting:chartData.dea])];
  1583. }
  1584. }
  1585. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1586. if (i == 0 || !chartData.isSupp) {
  1587. totalPrice = [totalPrice decimalNumberByAdding:chartData.closed];
  1588. totalNumber = [totalNumber decimalNumberByAdding:[NSDecimalNumber decimalNumberWithString:@"1"]];
  1589. chartData.tsma = [totalPrice decimalNumberByDividingBy:totalNumber];
  1590. } else {
  1591. if (i != _chartDataArray.count - 1) {
  1592. // 这里去对补的数据不进行处理
  1593. ChartData *yesterdayChartData = [_chartDataArray objectAtIndex:i+1];
  1594. // 如果是补的数据 当前的平均数据为上一口的数据
  1595. chartData.tsma = yesterdayChartData.tsma;
  1596. }
  1597. }
  1598. }
  1599. }
  1600. /**
  1601. * @brief 初始计算VOL线数据的方法
  1602. *
  1603. * @param index 需要刷新数据的0-index的范围
  1604. */
  1605. - (void)initVOLLineDataWithIndex:(NSInteger)index {
  1606. for (NSInteger i=index ; i>=0 ; i--) {
  1607. //期5为周期算
  1608. if (index - i >= 4) {
  1609. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1610. NSDecimalNumber *averagevolume= [NSDecimalNumber zero];
  1611. //算出周期里面收盘价的总和
  1612. for (NSInteger j=i+4 ; j>=i ; j--) {
  1613. chartData = [_chartDataArray objectAtIndex:j];
  1614. if (chartData.totleVolume)
  1615. averagevolume = [averagevolume decimalNumberByAdding:chartData.totleVolume];
  1616. }
  1617. //vol5 = sum(totalVolume, N)/N
  1618. chartData.vol5 = [averagevolume decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"5"]];
  1619. }
  1620. //期10为周期算
  1621. if (index - i >= 9) {
  1622. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1623. NSDecimalNumber *averagevolume= [NSDecimalNumber zero];
  1624. //算出周期里面收盘价的总和
  1625. for (NSInteger j=i+9 ; j>=i ; j--) {
  1626. chartData = [_chartDataArray objectAtIndex:j];
  1627. if (chartData.totleVolume)
  1628. averagevolume = [averagevolume decimalNumberByAdding:chartData.totleVolume];
  1629. }
  1630. //BIAS = sum(totalVolume, N)/N
  1631. chartData.vol10 = [averagevolume decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"10"]];
  1632. }
  1633. }
  1634. }
  1635. /**
  1636. * @brief 初始计算KDJ线数据的方法
  1637. *
  1638. * @param index 需要刷新数据的0-index的范围
  1639. */
  1640. - (void)initKDJLineDataWithIndex:(NSInteger)index {
  1641. for (NSInteger i=index ; i>=0 ; i--) {
  1642. /// 取前九根为一周期
  1643. if (index - i >= 8) {
  1644. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1645. NSDecimalNumber *highDecimalNumber = chartData.highest;
  1646. NSDecimalNumber *lowDecimalNumber = chartData.lowest;
  1647. /// 循环算出周期里面的最高值和最低值
  1648. for (NSInteger j=i; j-i<8; j++) {
  1649. ChartData *yesterdayData = [_chartDataArray objectAtIndex:j+1];
  1650. if ([highDecimalNumber compare:yesterdayData.highest] == NSOrderedAscending) {
  1651. highDecimalNumber = yesterdayData.highest;
  1652. }
  1653. if ([lowDecimalNumber compare:yesterdayData.lowest] == NSOrderedDescending) {
  1654. lowDecimalNumber = yesterdayData.lowest;
  1655. }
  1656. }
  1657. /// 如果最高价和最低价相等 则默认rsv值为50
  1658. if ([lowDecimalNumber compare:highDecimalNumber] == NSOrderedSame) {
  1659. chartData.rsv = [NSDecimalNumber decimalNumberWithString:@"50"];
  1660. } else {
  1661. chartData.rsv = [[[chartData.closed decimalNumberBySubtracting:lowDecimalNumber] decimalNumberByDividingBy:[highDecimalNumber decimalNumberBySubtracting:lowDecimalNumber]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
  1662. }
  1663. /// 如果前一日的KT值不存在则默认为50
  1664. if (!((ChartData *)[_chartDataArray objectAtIndex:i+1]).kt) {
  1665. ((ChartData *)[_chartDataArray objectAtIndex:i+1]).kt = [NSDecimalNumber decimalNumberWithString:@"50"];
  1666. }
  1667. /// 如果前一日的DT值不存在则默认为50
  1668. if (!((ChartData *)[_chartDataArray objectAtIndex:i+1]).dt) {
  1669. ((ChartData *)[_chartDataArray objectAtIndex:i+1]).dt = [NSDecimalNumber decimalNumberWithString:@"50"];
  1670. }
  1671. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  1672. /// KT = 2/3*前一日的KT+1/3*当日的RSV
  1673. 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]];
  1674. /// DT = 2/3*前一日的DT+1/3*当日的KT
  1675. 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]];
  1676. /// JT = 3*当前的KT-2*当日的DT
  1677. chartData.jt = [[[NSDecimalNumber decimalNumberWithString:@"3"] decimalNumberByMultiplyingBy:chartData.kt] decimalNumberBySubtracting:[[NSDecimalNumber decimalNumberWithString:@"2"] decimalNumberByMultiplyingBy:chartData.dt]];
  1678. }
  1679. }
  1680. }
  1681. /**
  1682. * @brief 初始计算CCI线数据的方法
  1683. *
  1684. * @param index 需要刷新数据的0-index的范围
  1685. */
  1686. - (void)initCCILineDataWithIndex:(NSInteger)index {
  1687. for (NSInteger i=index ; i>=0 ; i--) {
  1688. /// 取14根为一周期
  1689. if (index - i >=13) {
  1690. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1691. ///TP = (highest + lowest + close)/3
  1692. chartData.tp = [[[chartData.highest decimalNumberByAdding:chartData.lowest] decimalNumberByAdding:chartData.closed] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"3"]];
  1693. /// MA = N日的TP的和/N
  1694. NSDecimalNumber *totleDecimalNumber = [NSDecimalNumber zero];
  1695. /// 循环算出周期里面收盘价的总和
  1696. for (NSInteger j=i+13; j>=i ; j--) {
  1697. chartData = [_chartDataArray objectAtIndex:j];
  1698. if (chartData.tp)
  1699. totleDecimalNumber = [totleDecimalNumber decimalNumberByAdding:chartData.tp];
  1700. }
  1701. chartData.ma = [totleDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"14"]];
  1702. /// MD = N日的|((N)TP-MA)|的和/N(平均绝对方差)
  1703. NSDecimalNumber *totalMDSum = [NSDecimalNumber zero];
  1704. NSDecimalNumber *decimal = [NSDecimalNumber zero];
  1705. /// 循环算出周期里面收盘价的总和
  1706. for (NSInteger j=i+13 ; j>=i ; j--) {
  1707. ChartData *nowChartData = [_chartDataArray objectAtIndex:j];
  1708. if (chartData.ma && nowChartData.tp)
  1709. decimal = [nowChartData.tp decimalNumberBySubtracting:chartData.ma];
  1710. /// 如果算出来的值为负数 则去绝对值
  1711. if ([decimal compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
  1712. decimal = [decimal decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"-1"]];
  1713. }
  1714. totalMDSum = [totalMDSum decimalNumberByAdding:decimal];
  1715. }
  1716. chartData.md = [totalMDSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"14"]];
  1717. /// CCI = (TP-MA)/MD/0.015
  1718. if (chartData.tp && chartData.ma && chartData.md && [chartData.md compare:[NSDecimalNumber zero]] != NSOrderedSame)
  1719. chartData.cci = [[chartData.tp decimalNumberBySubtracting:chartData.ma] decimalNumberByDividingBy:[chartData.md decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"0.015"]]];
  1720. }
  1721. }
  1722. }
  1723. /**
  1724. * @brief 初始计算DMA线数据的方法
  1725. *
  1726. * @param index 需要刷新数据的0-index的范围
  1727. */
  1728. - (void)initDMALineDataWithIndex:(NSInteger)index {
  1729. for (NSInteger i=index ; i>=0 ; i--) {
  1730. //以10为一周期进行计算
  1731. if (index - i >= 9) {
  1732. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1733. //DMA = MA10 - MA50
  1734. if (chartData.ma10 && chartData.ma50)
  1735. chartData.dma = [chartData.ma10 decimalNumberBySubtracting:chartData.ma50];
  1736. NSDecimalNumber *totalAMASum = [NSDecimalNumber zero];
  1737. //算出周期里面dma的和
  1738. for (NSInteger j=i+9 ; j>=i ; j--) {
  1739. chartData = [_chartDataArray objectAtIndex:j];
  1740. if (chartData.dma)
  1741. totalAMASum = [totalAMASum decimalNumberByAdding:chartData.dma];
  1742. }
  1743. chartData.ama = [totalAMASum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"10"]];
  1744. }
  1745. }
  1746. }
  1747. /**
  1748. * @brief 初始计算BIAS线数据的方法
  1749. *
  1750. * @param index 需要刷新数据的0-index的范围
  1751. */
  1752. - (void)initBIASLineDataWithIndex:(NSInteger)index {
  1753. for (NSInteger i=index ; i>=0 ; i--) {
  1754. //期6为周期算
  1755. if (index - i >= 5) {
  1756. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1757. NSDecimalNumber *totalCloseSum = [NSDecimalNumber zero];
  1758. //算出周期里面收盘价的总和
  1759. for (NSInteger j=i+5 ; j>=i ; j--) {
  1760. chartData = [_chartDataArray objectAtIndex:j];
  1761. totalCloseSum = [totalCloseSum decimalNumberByAdding:chartData.closed];
  1762. }
  1763. if ([totalCloseSum compare:[NSDecimalNumber zero]] != NSOrderedSame) {
  1764. //BIAS = (closed - N(closed))/N(closed)*100
  1765. chartData.bias1 = [[[chartData.closed decimalNumberBySubtracting:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"6"]]] decimalNumberByDividingBy:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"6"]]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
  1766. } else {
  1767. chartData.bias1 = [NSDecimalNumber zero];
  1768. }
  1769. }
  1770. //期12为周期算
  1771. if (index - i >= 11) {
  1772. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1773. NSDecimalNumber *totalCloseSum = [NSDecimalNumber zero];
  1774. //算出周期里面收盘价的总和
  1775. for (NSInteger j=i+11 ; j>=i ; j--) {
  1776. chartData = [_chartDataArray objectAtIndex:j];
  1777. totalCloseSum = [totalCloseSum decimalNumberByAdding:chartData.closed];
  1778. }
  1779. if ([totalCloseSum compare:[NSDecimalNumber zero]] != NSOrderedSame) {
  1780. //BIAS = (closed - N(closed))/N(closed)*100
  1781. chartData.bias2 = [[[chartData.closed decimalNumberBySubtracting:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"]]] decimalNumberByDividingBy:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"]]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
  1782. } else {
  1783. chartData.bias2 = [NSDecimalNumber zero];
  1784. }
  1785. }
  1786. //期24为周期算
  1787. if (index - i >= 23) {
  1788. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1789. NSDecimalNumber *totalCloseSum = [NSDecimalNumber zero];
  1790. //算出周期里面收盘价的总和
  1791. for (NSInteger j=i+23 ; j>=i ; j--) {
  1792. chartData = [_chartDataArray objectAtIndex:j];
  1793. totalCloseSum = [totalCloseSum decimalNumberByAdding:chartData.closed];
  1794. }
  1795. if ([totalCloseSum compare:[NSDecimalNumber zero]] != NSOrderedSame) {
  1796. //BIAS = (closed - N(closed))/N(closed)*100
  1797. chartData.bias3 = [[[chartData.closed decimalNumberBySubtracting:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"24"]]] decimalNumberByDividingBy:[totalCloseSum decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"24"]]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
  1798. } else {
  1799. chartData.bias3 = [NSDecimalNumber zero];
  1800. }
  1801. }
  1802. }
  1803. }
  1804. /**
  1805. * @brief 初始计算PSY线数据的方法
  1806. *
  1807. * @param index 需要刷新数据的0-index的范围
  1808. */
  1809. - (void)initPSYLineDataWithIndex:(NSInteger)index {
  1810. for (NSInteger i=index ; i>=0 ; i--) {
  1811. //取前12根为一周期
  1812. if (index - i >= 12) {
  1813. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1814. NSDecimalNumber *upFlagDecimalNumber = [NSDecimalNumber zero];
  1815. //循环算出周期里面上涨的天数
  1816. for (NSInteger j=i; j-i<12; j++) {
  1817. ChartData *nowChartData = [_chartDataArray objectAtIndex:j];
  1818. ChartData *yesterdayData = [_chartDataArray objectAtIndex:j+1];
  1819. if ([nowChartData.closed compare:yesterdayData.closed] == NSOrderedDescending) {
  1820. upFlagDecimalNumber = [upFlagDecimalNumber decimalNumberByAdding:[NSDecimalNumber decimalNumberWithString:@"1"]];
  1821. }
  1822. }
  1823. //PSY = 上涨的天数/周期 * 100
  1824. chartData.psy = [[upFlagDecimalNumber decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
  1825. }
  1826. //取前6根为一周期
  1827. if (index - i >= 6) {
  1828. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1829. NSDecimalNumber *sumPsyDecimal = [NSDecimalNumber zero];
  1830. //循环算出周期里面上涨的天数
  1831. for (NSInteger j=i; j-i<6; j++) {
  1832. ChartData *nowChartData = [_chartDataArray objectAtIndex:j];
  1833. if (nowChartData.psy) {
  1834. sumPsyDecimal = [sumPsyDecimal decimalNumberByAdding:nowChartData.psy];
  1835. }
  1836. }
  1837. //PSYMA = PSY的M日简单移动平均
  1838. chartData.psyma = [sumPsyDecimal decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"6"]];
  1839. }
  1840. }
  1841. }
  1842. #pragma mark - 画平均线相关
  1843. /**
  1844. * @brief 画平均线的方法(MACD相关计算目前也放在这个方法完成)
  1845. */
  1846. - (void)drawAverageLine {
  1847. CGContextRef context = UIGraphicsGetCurrentContext();
  1848. CGContextSetLineWidth(context, 1.0f);
  1849. /// MA5
  1850. CGContextSetRGBStrokeColor(context, _kMA5Red, _kMA5Green, _kMA5Blue, _kMA5Alpha);
  1851. CGFloat currentXPoint = _kLineOrigin.x + 1.0f+_kLineWidth/2;
  1852. BOOL isInit = NO;
  1853. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1854. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1855. if (!chartData.ma5) {
  1856. /// 前4条数据
  1857. }
  1858. else if (chartData.ma5 && !isInit) {
  1859. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
  1860. isInit = YES;
  1861. }
  1862. else {
  1863. CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
  1864. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
  1865. }
  1866. currentXPoint += _kLineWidth + _kLinePadding;
  1867. }
  1868. CGContextStrokePath(context);
  1869. //MA10
  1870. CGContextSetRGBStrokeColor(context, _kMA10Red, _kMA10Green, _kMA10Blue, _kMA10Alpha);
  1871. currentXPoint = _kLineOrigin.x + 1.0f+_kLineWidth/2;
  1872. isInit = NO;
  1873. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1874. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1875. if (!chartData.ma10) {
  1876. //前9条数据
  1877. }
  1878. else if (chartData.ma10 && !isInit) {
  1879. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
  1880. isInit = YES;
  1881. }
  1882. else {
  1883. CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
  1884. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
  1885. }
  1886. currentXPoint += _kLineWidth + _kLinePadding;
  1887. }
  1888. CGContextStrokePath(context);
  1889. //MA15
  1890. CGContextSetRGBStrokeColor(context, _kMA15Red, _kMA15Green, _kMA15Blue, _kMA15Alpha);
  1891. currentXPoint = _kLineOrigin.x + 1.0f+_kLineWidth/2;
  1892. isInit = NO;
  1893. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1894. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1895. if (!chartData.ma15) {
  1896. //前14条数据
  1897. }
  1898. else if (chartData.ma15 && !isInit) {
  1899. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
  1900. isInit = YES;
  1901. }
  1902. else {
  1903. CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
  1904. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
  1905. }
  1906. currentXPoint += _kLineWidth + _kLinePadding;
  1907. }
  1908. CGContextStrokePath(context);
  1909. if (!_isShowTipLine) {
  1910. // 获取最后一根数据
  1911. ChartData *chartData = [_chartDataArray objectAtIndex:0];
  1912. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  1913. //平均线说明
  1914. CGFloat currentX = _kLineOrigin.x;
  1915. //MA5
  1916. NSString *ma5 = [ChartCalculateUtils notRounding:chartData.ma5 afterPoint:digitCount];
  1917. NSAttributedString *MA5 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@", ma5 ? ma5 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA5Red green:_kMA5Green blue:_kMA5Blue alpha:_kMA5Alpha]}];
  1918. CGSize titleSize = [MA5 size];
  1919. [MA5 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
  1920. currentX += titleSize.width + 4.0f;
  1921. //MA10
  1922. NSString *ma10 = [ChartCalculateUtils notRounding:chartData.ma10 afterPoint:digitCount];
  1923. NSAttributedString *MA10 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@", ma10 ? ma10 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA10Red green:_kMA10Green blue:_kMA10Blue alpha:_kMA10Alpha]}];
  1924. titleSize = [MA10 size];
  1925. [MA10 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
  1926. currentX += titleSize.width + 4.0f;
  1927. //MA15
  1928. NSString *ma15 = [ChartCalculateUtils notRounding:chartData.ma15 afterPoint:digitCount];
  1929. NSAttributedString *MA15 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA15:%@", ma15 ? ma15 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA15Red green:_kMA15Green blue:_kMA15Blue alpha:_kMA15Alpha]}];
  1930. titleSize = [MA15 size];
  1931. [MA15 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
  1932. }
  1933. }
  1934. /**
  1935. * @brief 画平均线的方法(MACD相关计算目前也放在这个方法完成)
  1936. */
  1937. - (void)drawBBAverageLine {
  1938. CGContextRef context = UIGraphicsGetCurrentContext();
  1939. CGContextSetLineWidth(context, 1.0f);
  1940. //MA5
  1941. CGContextSetRGBStrokeColor(context, _kMA5Red, _kMA5Green, _kMA5Blue, _kMA5Alpha);
  1942. CGFloat currentXPoint = _kLineOrigin.x;
  1943. BOOL isInit = NO;
  1944. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1945. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1946. if (!chartData.ma5) {
  1947. //前4条数据
  1948. }
  1949. else if (chartData.ma5 && !isInit) {
  1950. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
  1951. isInit = YES;
  1952. }
  1953. else {
  1954. CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
  1955. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma5]);
  1956. }
  1957. currentXPoint += _xAxisWidth/_kLineCount;
  1958. }
  1959. CGContextStrokePath(context);
  1960. //MA10
  1961. CGContextSetRGBStrokeColor(context, _kMA10Red, _kMA10Green, _kMA10Blue, _kMA10Alpha);
  1962. currentXPoint = _kLineOrigin.x;
  1963. isInit = NO;
  1964. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1965. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1966. if (!chartData.ma10) {
  1967. //前9条数据
  1968. }
  1969. else if (chartData.ma10 && !isInit) {
  1970. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
  1971. isInit = YES;
  1972. }
  1973. else {
  1974. CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
  1975. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma10]);
  1976. }
  1977. currentXPoint += _xAxisWidth/_kLineCount;
  1978. }
  1979. CGContextStrokePath(context);
  1980. //MA15
  1981. CGContextSetRGBStrokeColor(context, _kMA15Red, _kMA15Green, _kMA15Blue, _kMA15Alpha);
  1982. currentXPoint = _kLineOrigin.x;
  1983. isInit = NO;
  1984. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  1985. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  1986. if (!chartData.ma15) {
  1987. //前14条数据
  1988. }
  1989. else if (chartData.ma15 && !isInit) {
  1990. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
  1991. isInit = YES;
  1992. }
  1993. else {
  1994. CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
  1995. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.ma15]);
  1996. }
  1997. currentXPoint += _xAxisWidth/_kLineCount;
  1998. }
  1999. CGContextStrokePath(context);
  2000. if (!_isShowTipLine) {
  2001. // 获取最后一根数据
  2002. ChartData *chartData = [_chartDataArray objectAtIndex:0];
  2003. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  2004. //平均线说明
  2005. CGFloat currentX = _kLineOrigin.x;
  2006. //MA5
  2007. NSString *ma5 = [ChartCalculateUtils notRounding:chartData.ma5 afterPoint:digitCount];
  2008. NSAttributedString *MA5 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@", ma5 ? ma5 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA5Red green:_kMA5Green blue:_kMA5Blue alpha:_kMA5Alpha]}];
  2009. CGSize titleSize = [MA5 size];
  2010. [MA5 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
  2011. currentX += titleSize.width + 4.0f;
  2012. //MA10
  2013. NSString *ma10 = [ChartCalculateUtils notRounding:chartData.ma10 afterPoint:digitCount];
  2014. NSAttributedString *MA10 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@", ma10 ? ma10 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA10Red green:_kMA10Green blue:_kMA10Blue alpha:_kMA10Alpha]}];
  2015. titleSize = [MA10 size];
  2016. [MA10 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
  2017. currentX += titleSize.width + 4.0f;
  2018. //MA15
  2019. NSString *ma15 = [ChartCalculateUtils notRounding:chartData.ma15 afterPoint:digitCount];
  2020. NSAttributedString *MA15 = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA15:%@", ma15 ? ma15 : @"--"] attributes:@{NSFontAttributeName:_titleFont, NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA15Red green:_kMA15Green blue:_kMA15Blue alpha:_kMA15Alpha]}];
  2021. titleSize = [MA15 size];
  2022. [MA15 drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - 18.0f)];
  2023. }
  2024. }
  2025. #pragma mark - 画即时图相关
  2026. /**
  2027. * @brief 画即时图的方法
  2028. */
  2029. - (void)drawImmediatelyLine {
  2030. CGContextRef context = UIGraphicsGetCurrentContext();
  2031. CGContextSetRGBStrokeColor(context, 1.0f, 1.0, 1.0f, 1.0f);
  2032. BOOL isInit = NO;
  2033. CGFloat currentXPonit = _kLineOrigin.x + 1.0f;
  2034. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2035. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2036. if (!isInit) {
  2037. CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
  2038. isInit = YES;
  2039. }
  2040. else {
  2041. CGContextAddLineToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
  2042. CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
  2043. }
  2044. currentXPonit += _kLineWidth + _kLinePadding;
  2045. }
  2046. CGContextStrokePath(context);
  2047. currentXPonit = _kLineOrigin.x + 1.0f;
  2048. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2049. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2050. /// 是否需要显示十字线
  2051. if (_isShowTipLine) {
  2052. if (_tipLineIndex == i) {
  2053. /// 画垂直线
  2054. CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
  2055. CGContextSetLineWidth(context, 1.0f);
  2056. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, _yAxisPaddingTop);
  2057. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, _kLineOrigin.y);
  2058. /// 画水平线
  2059. CGContextMoveToPoint(context, _kLineOrigin.x, _tipLineYAxis);
  2060. CGContextAddLineToPoint(context, _kLineOrigin.x + _xAxisWidth , _tipLineYAxis);
  2061. CGContextStrokePath(context);
  2062. /// 写数据
  2063. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  2064. NSString *tipString = [NSString stringWithFormat:@"Open:%@ High:%@ Low:%@ Close:%@"
  2065. ,[ChartCalculateUtils notRounding:chartData.opened afterPoint:digitCount]
  2066. ,[ChartCalculateUtils notRounding:chartData.highest afterPoint:digitCount]
  2067. ,[ChartCalculateUtils notRounding:chartData.lowest afterPoint:digitCount]
  2068. ,[ChartCalculateUtils notRounding:chartData.closed afterPoint:digitCount]
  2069. ];
  2070. UIColor *profileColor = nil;
  2071. if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
  2072. profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
  2073. else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
  2074. profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
  2075. else
  2076. profileColor = _titleColor;
  2077. [profileColor set];
  2078. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, _yAxisPaddingTop - [tipString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2079. /// 纵轴时间
  2080. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  2081. dateFormatter.dateFormat = @"MM-dd HH:mm";
  2082. NSString *dateTime = [dateFormatter stringFromDate:chartData.startTime];
  2083. CGSize dateTimeSize = [dateTime sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  2084. CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 0.9f);
  2085. CGFloat x = currentXPonit+_kLineWidth/2-dateTimeSize.width/2;
  2086. if (x < _xAxisPaddingLeft)
  2087. x = _xAxisPaddingLeft;
  2088. else if (x > _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width)
  2089. x = _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width;
  2090. CGContextAddRect(context, CGRectMake(x, _kLineOrigin.y, dateTimeSize.width, dateTimeSize.height));
  2091. CGContextFillPath(context);
  2092. [[UIColor blackColor] set];
  2093. [dateTime drawAtPoint:CGPointMake(x, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
  2094. /// 横轴价格
  2095. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  2096. NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
  2097. NSDecimalNumber *yPrice = [self priceWithYPoint:_tipLineYAxis];
  2098. NSString *priceString = [ChartCalculateUtils notRounding:yPrice afterPoint:decimalNumber];
  2099. CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  2100. CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 0.9f);
  2101. CGContextAddRect(context, CGRectMake(priceXOffset, _tipLineYAxis-priceStringSize.height/2, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
  2102. CGContextFillPath(context);
  2103. [[UIColor blackColor] set];
  2104. [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, _tipLineYAxis-priceStringSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
  2105. break;
  2106. }
  2107. }
  2108. currentXPonit += _kLineWidth + _kLinePadding;
  2109. }
  2110. }
  2111. #pragma mark - 画分时图相关
  2112. /**
  2113. * @brief 画分时图的方法
  2114. */
  2115. - (void)drawTSPlanLine {
  2116. CGContextRef context = UIGraphicsGetCurrentContext();
  2117. CGContextSetRGBStrokeColor(context, _tsRed, _tsGreen, _tsBlue, _tsAlpha);
  2118. CGContextSetLineWidth(context, 1.0f);
  2119. NSMutableArray<NSValue *> *pointArray = [[NSMutableArray alloc] init];
  2120. /// FIXME: 临时性解决有完整数据(交易日已完整休市)后,总数据条数对不上的问题
  2121. if (self.chartDataArray.count > 0) {
  2122. ChartData *lastData = self.chartDataArray[0];
  2123. if ([lastData.startTime compare:self.tsCloseTime] == NSOrderedSame && !_added) {
  2124. _kLineCount = self.chartDataArray.count;
  2125. _added = YES;
  2126. }
  2127. }
  2128. /// 判断最早的数据时间是否开盘时间
  2129. BOOL isInit = NO;
  2130. NSInteger diffTime = [self diffMinuteWithFromDate:_tsStartTime toDate:((ChartData *)[_chartDataArray objectAtIndex:_chartDataArray.count-1]).startTime];
  2131. _tsStartXPonit = _kLineOrigin.x;
  2132. if (diffTime != 0) {
  2133. /// 在昨价线上画一条到最早数据的直线
  2134. _tsStartXPonit += diffTime * (_xAxisWidth/_kLineCount);
  2135. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:_preClose]);
  2136. CGContextAddLineToPoint(context, _tsStartXPonit, [self yPointWithPrice:_preClose]);
  2137. isInit = YES;
  2138. /// 记录第一个点
  2139. [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(_kLineOrigin.x, [self yPointWithPrice:_preClose])]];
  2140. /// 记录第二个点
  2141. [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(_tsStartXPonit, [self yPointWithPrice:_preClose])]];
  2142. }
  2143. CGFloat currentXPonit = _tsStartXPonit;
  2144. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2145. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2146. /// 记录位置
  2147. CGPoint point = CGPointMake(currentXPonit, [self yPointWithPrice:chartData.closed]);
  2148. [pointArray addObject:[NSValue valueWithCGPoint:point]];
  2149. if (!isInit) {
  2150. CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
  2151. isInit = YES;
  2152. } else {
  2153. CGContextAddLineToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
  2154. CGContextMoveToPoint(context, currentXPonit, [self yPointWithPrice:chartData.closed]);
  2155. }
  2156. currentXPonit += _xAxisWidth/_kLineCount;
  2157. }
  2158. CGContextStrokePath(context);
  2159. if (pointArray.count > 0) {
  2160. /// 画填充
  2161. CGContextMoveToPoint(context, _kLineOrigin.x, _kLineOrigin.y);
  2162. for (int i=0 ; i<pointArray.count ; i++) {
  2163. CGPoint point = [[pointArray objectAtIndex:i] CGPointValue];
  2164. CGContextAddLineToPoint(context, point.x, point.y);
  2165. }
  2166. CGPoint point = [[pointArray objectAtIndex:pointArray.count-1] CGPointValue];
  2167. CGContextAddLineToPoint(context, point.x,_kLineOrigin.y);
  2168. CGContextAddLineToPoint(context, _kLineOrigin.x,_kLineOrigin.y);
  2169. CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0xe3/0xff green:0xef/0xff blue:0xff/0xff alpha:0.1f].CGColor);
  2170. CGContextFillPath(context);
  2171. }
  2172. currentXPonit = _tsStartXPonit;
  2173. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2174. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2175. /// 是否需要显示十字线
  2176. if (_isShowTipLine) {
  2177. if (_tipLineIndex == i) {
  2178. /// 画垂直线
  2179. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2180. CGContextSetLineWidth(context, 1.0f);
  2181. CGContextMoveToPoint(context, currentXPonit, _yAxisPaddingTop);
  2182. CGContextAddLineToPoint(context, currentXPonit, _kLineOrigin.y);
  2183. /// 画水平线
  2184. CGContextMoveToPoint(context, _kLineOrigin.x, _tipLineYAxis);
  2185. CGContextAddLineToPoint(context, _kLineOrigin.x + _xAxisWidth , _tipLineYAxis);
  2186. CGContextStrokePath(context);
  2187. UIColor *profileColor = nil;
  2188. if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
  2189. profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
  2190. else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
  2191. profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
  2192. else
  2193. profileColor = _titleColor;
  2194. /// 写数据
  2195. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  2196. NSString *tipString = [NSString stringWithFormat:@"开:%@ 高:%@ 低:%@ 收:%@"
  2197. ,[ChartCalculateUtils notRounding:chartData.opened afterPoint:digitCount]
  2198. ,[ChartCalculateUtils notRounding:chartData.highest afterPoint:digitCount]
  2199. ,[ChartCalculateUtils notRounding:chartData.lowest afterPoint:digitCount]
  2200. ,[ChartCalculateUtils notRounding:chartData.closed afterPoint:digitCount]
  2201. ];
  2202. [profileColor set];
  2203. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, _yAxisPaddingTop - [tipString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: profileColor}];
  2204. /// 纵轴时间
  2205. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  2206. dateFormatter.dateFormat = _chartViewType == ChartViewTypeTSPlan ? @"HH:mm" : @"MM-dd HH:mm";
  2207. NSString *dateTime = [dateFormatter stringFromDate:chartData.startTime];
  2208. CGSize dateTimeSize = [dateTime sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  2209. CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2210. CGFloat x = currentXPonit+_kLineWidth/2-dateTimeSize.width/2;
  2211. if (x < _xAxisPaddingLeft)
  2212. x = _xAxisPaddingLeft;
  2213. else if (x > _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width)
  2214. x = _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width;
  2215. CGContextAddRect(context, CGRectMake(x, _kLineOrigin.y, dateTimeSize.width, dateTimeSize.height));
  2216. CGContextFillPath(context);
  2217. [_tipTitleColor set];
  2218. [dateTime drawAtPoint:CGPointMake(x, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
  2219. /// 横轴价格
  2220. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth;
  2221. /// 价格左边距
  2222. NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
  2223. NSDecimalNumber *yPrice = [self priceWithYPoint:_tipLineYAxis];
  2224. NSString *priceString = [ChartCalculateUtils notRounding:yPrice afterPoint:decimalNumber];
  2225. CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  2226. CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2227. CGContextAddRect(context, CGRectMake(priceXOffset, _tipLineYAxis-priceStringSize.height/2, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
  2228. CGContextFillPath(context);
  2229. [_tipTitleColor set];
  2230. [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, _tipLineYAxis-priceStringSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
  2231. break;
  2232. }
  2233. }
  2234. currentXPonit += _xAxisWidth/_kLineCount;
  2235. }
  2236. }
  2237. /// 是否需要常显示开高低收
  2238. - (void)showOHLPPriceWithIsKLine:(BOOL)isKine isShow:(BOOL)isShow {
  2239. CGContextRef context = UIGraphicsGetCurrentContext();
  2240. CGContextSetRGBStrokeColor(context, _tsRed, _tsGreen, _tsBlue, _tsAlpha);
  2241. CGContextSetLineWidth(context, 1.0f);
  2242. /// 不需要显示 不做任何处理
  2243. if (!_isShowOHLP) { return; }
  2244. /// 数据为空不做任何处理
  2245. if (self.chartDataArray.count == 0) { return; }
  2246. ChartData *chartData = [self.chartDataArray firstObject];
  2247. UIColor *profileColor = nil;
  2248. if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
  2249. profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
  2250. else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
  2251. profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
  2252. else
  2253. profileColor = _titleColor;
  2254. /// 写数据
  2255. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  2256. 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:@""];
  2257. CGPoint point = isKine ? CGPointMake(_kLineOrigin.x, _yAxisPaddingTop - [tipString size].height + 15.0) : CGPointMake(_kLineOrigin.x, _yAxisPaddingTop - [tipString size].height + 15.0);
  2258. [tipString drawAtPoint:point];
  2259. CGContextFillPath(context);
  2260. }
  2261. /**
  2262. * @brief 画分时图平均线的方法
  2263. */
  2264. - (void)drawTSAverageLine {
  2265. CGContextRef context = UIGraphicsGetCurrentContext();
  2266. CGContextSetLineWidth(context, 1.0f);
  2267. /// MA5
  2268. CGContextSetRGBStrokeColor(context, _tsMARed, _tsMAGreen, _tsMABlue, _tsMAAlpha);
  2269. CGFloat currentXPoint =_tsStartXPonit;
  2270. BOOL isInit = NO;
  2271. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2272. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2273. if (chartData.tsma && !isInit) {
  2274. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.tsma]);
  2275. isInit = YES;
  2276. }
  2277. else {
  2278. CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.tsma]);
  2279. }
  2280. currentXPoint += _xAxisWidth/_kLineCount;
  2281. }
  2282. CGContextStrokePath(context);
  2283. if (!_isShowTipLine) {
  2284. /// 平均线说明
  2285. CGFloat currentX = _kLineOrigin.x;
  2286. /// MA5
  2287. [[UIColor colorWithRed:_tsMARed green:_tsMAGreen blue:_tsMABlue alpha:_tsMAAlpha] set];
  2288. CGSize titleSize = [@"MA" sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  2289. [@"MA" drawAtPoint:CGPointMake(currentX, _yAxisPaddingTop - titleSize.height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2290. }
  2291. }
  2292. #pragma mark - 数字货币分时图
  2293. /**
  2294. * @brief 数字火币画分时图的方法
  2295. */
  2296. - (void)drawBBTSPlanLine {
  2297. CGContextRef context = UIGraphicsGetCurrentContext();
  2298. CGContextSetLineWidth(context, 1.0f);
  2299. CGContextSetRGBStrokeColor(context, _tsRed, _tsGreen, _tsBlue, _tsAlpha);
  2300. CGFloat currentXPoint = _kLineOrigin.x;
  2301. BOOL isInit = NO;
  2302. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2303. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2304. if (chartData.tsma && !isInit) {
  2305. CGContextMoveToPoint(context, currentXPoint, [self yPointWithPrice:chartData.closed]);
  2306. isInit = YES;
  2307. }
  2308. else {
  2309. CGContextAddLineToPoint(context, currentXPoint, [self yPointWithPrice:chartData.closed]);
  2310. }
  2311. currentXPoint += _xAxisWidth/_kLineCount;
  2312. }
  2313. CGContextStrokePath(context);
  2314. currentXPoint = _kLineOrigin.x;
  2315. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2316. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2317. /// 是否需要显示十字线
  2318. if (_isShowTipLine) {
  2319. if (_tipLineIndex == i) {
  2320. CGContextSetLineWidth(context, 1.0f);
  2321. CGContextMoveToPoint(context, currentXPoint, _yAxisPaddingTop);
  2322. CGContextAddLineToPoint(context, currentXPoint, _kLineOrigin.y);
  2323. /// 画水平线
  2324. CGContextMoveToPoint(context, _kLineOrigin.x, _tipLineYAxis);
  2325. CGContextAddLineToPoint(context, _kLineOrigin.x + _xAxisWidth , _tipLineYAxis);
  2326. CGContextStrokePath(context);
  2327. UIColor *profileColor = nil;
  2328. if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
  2329. profileColor = [UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:1.0];
  2330. else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
  2331. profileColor = [UIColor colorWithRed:_decKRed green:_decKGreen blue:_decKBlue alpha:1.0];
  2332. else
  2333. profileColor = _titleColor;
  2334. /// 写数据
  2335. NSInteger digitCount = [ChartCalculateUtils getDecimalDigits:_minUnit];
  2336. NSString *ma5 = [ChartCalculateUtils notRounding:chartData.ma5 afterPoint:digitCount];
  2337. /// 写数据
  2338. NSMutableAttributedString *MAString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@ ", ma5 ? ma5 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA5Red green:_kMA5Green blue:_kMA5Blue alpha:_kMA5Alpha], NSFontAttributeName:_titleFont}];
  2339. NSString *ma10 = [ChartCalculateUtils notRounding:chartData.ma10 afterPoint:digitCount];
  2340. [MAString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@ ",ma10 ? ma10 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA10Red green:_kMA10Green blue:_kMA10Blue alpha:_kMA10Alpha], NSFontAttributeName:_titleFont}]];
  2341. NSString *ma15 = [ChartCalculateUtils notRounding:chartData.ma15 afterPoint:digitCount];
  2342. [MAString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA15:%@ ",ma15 ? ma15 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_kMA15Red green:_kMA15Green blue:_kMA15Blue alpha:_kMA15Alpha], NSFontAttributeName:_titleFont}]];
  2343. 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}];
  2344. /// 横屏一排显示就够了
  2345. if (self.frame.size.width < self.frame.size.height) {
  2346. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, 12.0f)];
  2347. } else {
  2348. [MAString appendAttributedString:tipString];
  2349. }
  2350. [MAString drawAtPoint:CGPointMake(_kLineOrigin.x, 0)];
  2351. /// 纵轴时间
  2352. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  2353. dateFormatter.dateFormat = @"MM-dd HH:mm";
  2354. NSString *dateTime = [dateFormatter stringFromDate:chartData.startTime];
  2355. CGSize dateTimeSize = [dateTime sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  2356. CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2357. CGFloat x = currentXPoint+_kLineWidth/2-dateTimeSize.width/2;
  2358. if (x < _xAxisPaddingLeft)
  2359. x = _xAxisPaddingLeft;
  2360. else if (x > _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width)
  2361. x = _xAxisPaddingLeft + _xAxisWidth - dateTimeSize.width;
  2362. CGContextAddRect(context, CGRectMake(x, _kLineOrigin.y, dateTimeSize.width, dateTimeSize.height));
  2363. CGContextFillPath(context);
  2364. [_tipTitleColor set];
  2365. [dateTime drawAtPoint:CGPointMake(x, _kLineOrigin.y) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
  2366. /// 横轴价格
  2367. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  2368. NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
  2369. NSDecimalNumber *yPrice = [self priceWithYPoint:_tipLineYAxis];
  2370. NSString *priceString = [ChartCalculateUtils notRounding:yPrice afterPoint:decimalNumber];
  2371. CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  2372. CGContextSetRGBFillColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2373. CGContextAddRect(context, CGRectMake(priceXOffset, _tipLineYAxis-priceStringSize.height/2, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
  2374. CGContextFillPath(context);
  2375. [_tipTitleColor set];
  2376. [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, _tipLineYAxis-priceStringSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _tipTitleColor}];
  2377. break;
  2378. }
  2379. }
  2380. currentXPoint += _xAxisWidth/_kLineCount;
  2381. }
  2382. }
  2383. #pragma mark - MACD指标相关
  2384. /**
  2385. * @brief 初始化MACD的可视化的最大值和最小值的方法
  2386. */
  2387. - (void)initMACDData {
  2388. //可视MACD最大值与最小值
  2389. _indicatorMaxValue = [[self maxMACDValueAtVisible] floatValue];
  2390. _indicatorMinValue = [[self minMACDValueAtVisible] floatValue];
  2391. }
  2392. /**
  2393. * @brief 画MACD指标的方法
  2394. */
  2395. - (void)drawMACD {
  2396. if ( isnan([self yMACDPointWithValue:[NSDecimalNumber zero]]))
  2397. return;
  2398. CGContextRef context = UIGraphicsGetCurrentContext();
  2399. CGContextSetLineWidth(context, 1.0f);
  2400. /// 画0线与标题
  2401. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; /// 价格左边距
  2402. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  2403. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; /// 向red等设置值
  2404. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2405. CGContextMoveToPoint(context, _indicatorOrigin.x, [self yMACDPointWithValue:[NSDecimalNumber zero]]);
  2406. CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yMACDPointWithValue:[NSDecimalNumber zero]]);
  2407. CGContextStrokePath(context);
  2408. CGSize zeroTitleSize = [@"0" sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  2409. [_titleColor set];
  2410. [@"0" drawAtPoint:CGPointMake(priceXOffset, [self yMACDPointWithValue:[NSDecimalNumber zero]]-zeroTitleSize.height/2) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2411. /// 最大与最小值标题
  2412. NSString *maxString = [ChartCalculateUtils notRounding:[self maxMACDValueAtVisible] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2413. [maxString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, _indicatorOrigin.y - _indicatorHight) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2414. NSString *minString = [ChartCalculateUtils notRounding:[self minMACDValueAtVisible] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];//负数
  2415. [minString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, _indicatorOrigin.y - [minString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2416. /// MACD标题
  2417. CGFloat currentXPonit = _indicatorOrigin.x;
  2418. /// 画MACD柱
  2419. currentXPonit = _kLineOrigin.x + 1.0f;
  2420. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2421. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2422. if (chartData.macd) {
  2423. if ([chartData.macd compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
  2424. //close < open
  2425. CGContextSetRGBFillColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
  2426. CGContextAddRect(context, CGRectMake(currentXPonit, [self yMACDPointWithValue:[NSDecimalNumber zero]], _kLineWidth, [self yMACDPointWithValue:chartData.macd] - [self yMACDPointWithValue:[NSDecimalNumber zero]]));
  2427. CGContextFillPath(context);
  2428. }
  2429. else if ([chartData.macd compare:[NSDecimalNumber zero]] == NSOrderedDescending) {
  2430. //close < open
  2431. CGContextSetRGBFillColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
  2432. CGContextAddRect(context, CGRectMake(currentXPonit, [self yMACDPointWithValue:[NSDecimalNumber zero]], _kLineWidth, [self yMACDPointWithValue:chartData.macd] - [self yMACDPointWithValue:[NSDecimalNumber zero]]));
  2433. CGContextFillPath(context);
  2434. }
  2435. }
  2436. currentXPonit += _kLineWidth + _kLinePadding;
  2437. }
  2438. //画DIF线
  2439. CGContextSetRGBStrokeColor(context, _macdDIFRed, _macdDIFGreen, _macdDIFBlue, _macdDIFAlpha);
  2440. CGFloat currentXPoint = _kLineOrigin.x + 1.0f;
  2441. BOOL isInit = NO;
  2442. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2443. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2444. if (!chartData.dif) {
  2445. //前25条数据
  2446. } else if (chartData.dif && !isInit) {
  2447. CGContextMoveToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dif]);
  2448. isInit = YES;
  2449. } else {
  2450. CGContextAddLineToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dif]);
  2451. CGContextMoveToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dif]);
  2452. }
  2453. currentXPoint += _kLineWidth + _kLinePadding;
  2454. }
  2455. CGContextStrokePath(context);
  2456. //画DEA线
  2457. CGContextSetRGBStrokeColor(context, _macdDEARed, _macdDEAGreen, _macdDEABlue, _macdDEAAlpha);
  2458. currentXPoint = _kLineOrigin.x + 1.0f;
  2459. isInit = NO;
  2460. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2461. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2462. if (!chartData.dea) {
  2463. //前34条数据
  2464. } else if (chartData.dea && !isInit) {
  2465. CGContextMoveToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dea]);
  2466. isInit = YES;
  2467. } else {
  2468. CGContextAddLineToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dea]);
  2469. CGContextMoveToPoint(context, currentXPoint, [self yMACDPointWithValue:chartData.dea]);
  2470. }
  2471. currentXPoint += _kLineWidth + _kLinePadding;
  2472. }
  2473. CGContextStrokePath(context);
  2474. currentXPonit = _kLineOrigin.x + 1.0f;
  2475. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2476. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2477. //是否需要显示十字线
  2478. if (_isShowTipLine) {
  2479. if (_tipLineIndex == i) {
  2480. //画垂直线
  2481. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2482. CGContextSetLineWidth(context, 1.0f);
  2483. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yMACDPointWithValue:[self maxMACDValueAtVisible]]);
  2484. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yMACDPointWithValue:[self minMACDValueAtVisible]]);
  2485. CGContextStrokePath(context);
  2486. //写数据
  2487. 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}];
  2488. 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}];
  2489. 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}];
  2490. [tipString appendAttributedString:stringTwo];
  2491. [tipString appendAttributedString:stringThree];
  2492. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yMACDPointWithValue:[self maxMACDValueAtVisible]] - 12.0f)];
  2493. break;
  2494. }
  2495. }
  2496. currentXPonit += _kLineWidth + _kLinePadding;
  2497. }
  2498. }
  2499. #pragma mark - VOL指标相关
  2500. /**
  2501. * @brief 初始化VOL指标可视区数据
  2502. */
  2503. - (void)initVOLData {
  2504. //获取KDJ可视区最大值与最小值
  2505. _indicatorVOLMaxValue = [[self maxVOLValueAtVisible] floatValue];
  2506. _indicatorVOLMiniValue = [[self miniVOLValueAtVisible] floatValue];
  2507. }
  2508. /**
  2509. * @brief 画VOL指标的方法
  2510. */
  2511. - (void)drawVOL {
  2512. if (isnan([self yVOLPointWithValue:[NSDecimalNumber zero]])) {
  2513. return;
  2514. }
  2515. CGContextRef context = UIGraphicsGetCurrentContext();
  2516. CGContextSetLineWidth(context, 1.0f);
  2517. //画0线与标题
  2518. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  2519. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  2520. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2521. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2522. CGContextMoveToPoint(context, _indicatorOrigin.x, [self yVOLPointWithValue:[NSDecimalNumber zero]]);
  2523. CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yVOLPointWithValue:[NSDecimalNumber zero]]);
  2524. CGContextStrokePath(context);
  2525. [_titleColor set];
  2526. //最大与最小值标题
  2527. NSString *maxString = [ChartCalculateUtils notRounding:[self maxVOLValueAtVisible] afterPoint:[ChartCalculateUtils getDecimalDigits:self.numMinUnit]];
  2528. [maxString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, _indicatorOrigin.y - _indicatorHight) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2529. NSString *minString = [ChartCalculateUtils notRounding:[self miniVOLValueAtVisible] afterPoint:[ChartCalculateUtils getDecimalDigits:self.numMinUnit]];//负数
  2530. [minString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, _indicatorOrigin.y - [minString sizeWithAttributes:@{NSFontAttributeName:_titleFont}].height) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2531. CGFloat currentXPonit = _indicatorOrigin.x;
  2532. //画VOL柱
  2533. currentXPonit = _kLineOrigin.x + 1.0f;
  2534. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2535. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2536. if (chartData.totleVolume) {
  2537. if ([chartData.macd compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
  2538. //close < open
  2539. CGContextSetRGBFillColor(context, _decKRed, _decKGreen, _decKBlue, _decKAlpha);
  2540. CGContextAddRect(context, CGRectMake(currentXPonit, [self yVOLPointWithValue:[NSDecimalNumber zero]], _kLineWidth, [self yVOLPointWithValue:chartData.totleVolume] - [self yVOLPointWithValue:[self miniVOLValueAtVisible]]));
  2541. CGContextFillPath(context);
  2542. }
  2543. else if ([chartData.macd compare:[NSDecimalNumber zero]] != NSOrderedAscending) {
  2544. CGContextSetRGBFillColor(context, _aesKRed, _aesKGreen, _aesKBlue, _aesKAlpha);
  2545. CGContextAddRect(context, CGRectMake(currentXPonit, [self yVOLPointWithValue:[NSDecimalNumber zero]], _kLineWidth, [self yVOLPointWithValue:chartData.totleVolume] - [self yVOLPointWithValue:[self miniVOLValueAtVisible]]));
  2546. CGContextFillPath(context);
  2547. }
  2548. }
  2549. currentXPonit += _kLineWidth + _kLinePadding;
  2550. }
  2551. //画vol5线
  2552. CGContextSetRGBStrokeColor(context, _macdDIFRed, _macdDIFGreen, _macdDIFBlue, _macdDIFAlpha);
  2553. CGFloat currentXPoint = _kLineOrigin.x + 1.0f;
  2554. BOOL isInit = NO;
  2555. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2556. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2557. if (!chartData.vol5) {
  2558. //前5条数据
  2559. } else if (chartData.vol10 && !isInit) {
  2560. CGContextMoveToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol5]);
  2561. isInit = YES;
  2562. } else {
  2563. CGContextAddLineToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol5]);
  2564. CGContextMoveToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol5]);
  2565. }
  2566. currentXPoint += _kLineWidth + _kLinePadding;
  2567. }
  2568. CGContextStrokePath(context);
  2569. //画vol10线
  2570. CGContextSetRGBStrokeColor(context, _macdDEARed, _macdDEAGreen, _macdDEABlue, _macdDEAAlpha);
  2571. currentXPoint = _kLineOrigin.x + 1.0f;
  2572. isInit = NO;
  2573. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2574. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2575. if (!chartData.vol10) {
  2576. //前10条数据
  2577. } else if (chartData.vol10 && !isInit) {
  2578. CGContextMoveToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol10]);
  2579. isInit = YES;
  2580. } else {
  2581. CGContextAddLineToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol10]);
  2582. CGContextMoveToPoint(context, currentXPoint, [self yVOLPointWithValue:chartData.vol10]);
  2583. }
  2584. currentXPoint += _kLineWidth + _kLinePadding;
  2585. }
  2586. CGContextStrokePath(context);
  2587. currentXPonit = _kLineOrigin.x + 1.0f;
  2588. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2589. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2590. //是否需要显示十字线
  2591. if (_isShowTipLine) {
  2592. if (_tipLineIndex == i) {
  2593. //画垂直线
  2594. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2595. CGContextSetLineWidth(context, 1.0f);
  2596. CGContextMoveToPoint(context, currentXPonit + _kLineWidth/2, [self yVOLPointWithValue:[self maxVOLValueAtVisible]]);
  2597. CGContextAddLineToPoint(context, currentXPonit + _kLineWidth/2, [self yVOLPointWithValue:[self miniVOLValueAtVisible]]);
  2598. CGContextStrokePath(context);
  2599. //写数据
  2600. NSString *volume = [ChartCalculateUtils notRounding:chartData.totleVolume afterPoint:2];
  2601. NSMutableAttributedString *tipString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"VOLUME:%@ ",volume ? volume : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_aesKRed green:_aesKGreen blue:_aesKBlue alpha:_aesKAlpha], NSFontAttributeName:_titleFont}];
  2602. NSString *vol5 = [ChartCalculateUtils notRounding:chartData.vol5 afterPoint:2];
  2603. NSAttributedString *stringTwo = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA5:%@ ", vol5 ? vol5 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_macdDIFRed green:_macdDIFGreen blue:_macdDIFBlue alpha:_macdDIFAlpha], NSFontAttributeName:_titleFont}];
  2604. NSString *vol10 = [ChartCalculateUtils notRounding:chartData.vol10 afterPoint:2];
  2605. NSAttributedString *stringThree = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"MA10:%@", vol10 ? vol10 : @"--"] attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:_macdDEARed green:_macdDEAGreen blue:_macdDEABlue alpha:_macdDEAAlpha], NSFontAttributeName:_titleFont}];
  2606. [tipString appendAttributedString:stringTwo];
  2607. [tipString appendAttributedString:stringThree];
  2608. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yVOLPointWithValue:[self maxVOLValueAtVisible]] - 12.0f)];
  2609. break;
  2610. }
  2611. }
  2612. currentXPonit += _kLineWidth + _kLinePadding;
  2613. }
  2614. }
  2615. #pragma mark - KDJ指标相关
  2616. /**
  2617. * @brief 初始化KDJ指标可视区数据
  2618. */
  2619. - (void)initKDJData {
  2620. //获取KDJ可视区最大值与最小值
  2621. _indicatorKDJMaxValue = [[self maxKDJValueAtVisible] floatValue];
  2622. _indicatorKDJMiniValue = [[self miniKDJValueAtVisible] floatValue];
  2623. }
  2624. /**
  2625. * @brief 画KDJ指标的方法
  2626. */
  2627. - (void)drawKDJ {
  2628. if (isnan([self yKDJPointWithValue:[NSDecimalNumber zero]])) {
  2629. return;
  2630. }
  2631. CGContextRef context = UIGraphicsGetCurrentContext();
  2632. CGContextSetLineWidth(context, 1.0f);
  2633. //画0线与标题
  2634. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  2635. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  2636. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2637. [_titleColor set];
  2638. //上下区间值 20、80
  2639. NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"80"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2640. [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2641. NSString *downString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"20"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2642. [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2643. //RSI标题
  2644. CGFloat currentXPonit = _indicatorOrigin.x;
  2645. //画80线
  2646. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2647. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2648. CGContextMoveToPoint(context, _kLineOrigin.x, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
  2649. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
  2650. CGContextStrokePath(context);
  2651. //画20线
  2652. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2653. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2654. CGContextMoveToPoint(context, _kLineOrigin.x, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
  2655. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
  2656. CGContextStrokePath(context);
  2657. //画kt线
  2658. CGContextSetRGBStrokeColor(context, _ktRed, _ktGreen, _ktBlue, _ktAlpha);
  2659. CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2660. BOOL isInit = NO;
  2661. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2662. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2663. if (!chartData.kt) {
  2664. //前9根没有
  2665. } else if (chartData.kt && !isInit) {
  2666. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
  2667. isInit = YES;
  2668. } else {
  2669. CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
  2670. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
  2671. }
  2672. currentXPoint += _kLineWidth + _kLinePadding;
  2673. }
  2674. CGContextStrokePath(context);
  2675. //画dt线
  2676. CGContextSetRGBStrokeColor(context, _dtRed, _dtGreen, _dtBlue, _dtAlpha);
  2677. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2678. isInit = NO;
  2679. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2680. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2681. if (!chartData.dt) {
  2682. //前9根没有
  2683. } else if (chartData.dt && !isInit) {
  2684. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
  2685. isInit = YES;
  2686. } else {
  2687. CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
  2688. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
  2689. }
  2690. currentXPoint += _kLineWidth + _kLinePadding;
  2691. }
  2692. CGContextStrokePath(context);
  2693. //画jt线
  2694. CGContextSetRGBStrokeColor(context, _jtRed, _jtGreen, _jtBlue, _jtAlpha);
  2695. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2696. isInit = NO;
  2697. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2698. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2699. if (!chartData.jt) {
  2700. //前9根没有
  2701. } else if (chartData.jt && !isInit) {
  2702. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.jt]);
  2703. isInit = YES;
  2704. } else {
  2705. CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.jt]);
  2706. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.jt]);
  2707. }
  2708. currentXPoint += _kLineWidth + _kLinePadding;
  2709. }
  2710. CGContextStrokePath(context);
  2711. currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2712. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2713. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2714. //是否需要显示十字线
  2715. if (_isShowTipLine) {
  2716. if (_tipLineIndex == i) {
  2717. //画垂直线
  2718. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2719. CGContextSetLineWidth(context, 1.0f);
  2720. CGContextMoveToPoint(context, currentXPonit, [self yKDJPointWithValue:[self maxKDJValueAtVisible]]);
  2721. CGContextAddLineToPoint(context, currentXPonit, [self yKDJPointWithValue:[self miniKDJValueAtVisible]]);
  2722. CGContextStrokePath(context);
  2723. //写数据
  2724. 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}];
  2725. 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}];
  2726. 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}];
  2727. [tipString appendAttributedString:stringTwo];
  2728. [tipString appendAttributedString:stringThree];
  2729. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yKDJPointWithValue:[self maxKDJValueAtVisible]] - 12.0f)];
  2730. break;
  2731. }
  2732. }
  2733. currentXPonit += _xAxisWidth/_kLineCount;
  2734. }
  2735. }
  2736. #pragma mark - KD指标相关
  2737. /**
  2738. * @brief 画KD指标的方法
  2739. */
  2740. - (void)drawKD {
  2741. if (isnan([self yKDJPointWithValue:[NSDecimalNumber zero]])) return;
  2742. CGContextRef context = UIGraphicsGetCurrentContext();
  2743. CGContextSetLineWidth(context, 1.0f);
  2744. //画0线与标题
  2745. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  2746. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  2747. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2748. [_titleColor set];
  2749. //上下区间值 20、80
  2750. NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"80"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2751. [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2752. NSString *downString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"20"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2753. [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2754. //RSI标题
  2755. CGFloat currentXPonit = _indicatorOrigin.x;
  2756. //画80线
  2757. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2758. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2759. CGContextMoveToPoint(context, _kLineOrigin.x, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
  2760. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
  2761. CGContextStrokePath(context);
  2762. //画20线
  2763. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2764. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2765. CGContextMoveToPoint(context, _kLineOrigin.x, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
  2766. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yKDJPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
  2767. CGContextStrokePath(context);
  2768. //画kt线
  2769. CGContextSetRGBStrokeColor(context, _ktRed, _ktGreen, _ktBlue, _ktAlpha);
  2770. CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2771. BOOL isInit = NO;
  2772. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2773. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2774. if (!chartData.kt) {
  2775. //前9根没有
  2776. } else if (chartData.kt && !isInit) {
  2777. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
  2778. isInit = YES;
  2779. } else {
  2780. CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
  2781. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.kt]);
  2782. }
  2783. currentXPoint += _kLineWidth + _kLinePadding;
  2784. }
  2785. CGContextStrokePath(context);
  2786. //画dt线
  2787. CGContextSetRGBStrokeColor(context, _dtRed, _dtGreen, _dtBlue, _dtBlue);
  2788. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2789. isInit = NO;
  2790. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2791. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2792. if (!chartData.dt) {
  2793. //前9根没有
  2794. } else if (chartData.dt && !isInit) {
  2795. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
  2796. isInit = YES;
  2797. } else {
  2798. CGContextAddLineToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
  2799. CGContextMoveToPoint(context, currentXPoint, [self yKDJPointWithValue:chartData.dt]);
  2800. }
  2801. currentXPoint += _kLineWidth + _kLinePadding;
  2802. }
  2803. CGContextStrokePath(context);
  2804. currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2805. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2806. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2807. //是否需要显示十字线
  2808. if (_isShowTipLine) {
  2809. if (_tipLineIndex == i) {
  2810. //画垂直线
  2811. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2812. CGContextSetLineWidth(context, 1.0f);
  2813. CGContextMoveToPoint(context, currentXPonit, [self yKDJPointWithValue:[self maxKDJValueAtVisible]]);
  2814. CGContextAddLineToPoint(context, currentXPonit, [self yKDJPointWithValue:[self miniKDJValueAtVisible]]);
  2815. CGContextStrokePath(context);
  2816. //写数据
  2817. 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}];
  2818. 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}];
  2819. [tipString appendAttributedString:stringTwo];
  2820. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yKDJPointWithValue:[self maxKDJValueAtVisible]] - 12.0f)];
  2821. break;
  2822. }
  2823. }
  2824. currentXPonit += _xAxisWidth/_kLineCount;
  2825. }
  2826. }
  2827. #pragma mark - RSI指标相关
  2828. /**
  2829. * @brief 初始化RSI指标可视区数据
  2830. */
  2831. - (void)initRSIData {
  2832. //获取RSI可视区最大值与最小值
  2833. _indicatorRSIMaxValue = [[self maxRSIValueAtVisible] floatValue];
  2834. _indicatorRSIMiniValue = [[self miniRSIValueAtVisible] floatValue];
  2835. }
  2836. /**
  2837. * @brief 画RSI指标的方法
  2838. */
  2839. - (void)drawRSI {
  2840. if (isnan([self yRSIPointWithValue:[NSDecimalNumber zero]])) return;
  2841. CGContextRef context = UIGraphicsGetCurrentContext();
  2842. CGContextSetLineWidth(context, 1.0f);
  2843. //画0线与标题
  2844. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  2845. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  2846. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2847. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2848. CGContextMoveToPoint(context, _indicatorOrigin.x, [self yRSIPointWithValue:[NSDecimalNumber zero]]);
  2849. CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yRSIPointWithValue:[NSDecimalNumber zero]]);
  2850. CGContextStrokePath(context);
  2851. [_titleColor set];
  2852. //上下区间值 20、80
  2853. NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"80"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2854. [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2855. NSString *downString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"20"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2856. [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2857. //RSI标题
  2858. CGFloat currentXPonit = _indicatorOrigin.x;
  2859. //画80线
  2860. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2861. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2862. CGContextMoveToPoint(context, _kLineOrigin.x, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
  2863. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"80"]]);
  2864. CGContextStrokePath(context);
  2865. //画20线
  2866. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2867. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2868. CGContextMoveToPoint(context, _kLineOrigin.x, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
  2869. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yRSIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"20"]]);
  2870. CGContextStrokePath(context);
  2871. //画RSI1线
  2872. CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
  2873. CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2874. BOOL isInit = NO;
  2875. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2876. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2877. if (!chartData.rsi1) {
  2878. //前6根没有
  2879. } else if (chartData.rsi1 && !isInit) {
  2880. CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi1]);
  2881. isInit = YES;
  2882. } else {
  2883. CGContextAddLineToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi1]);
  2884. CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi1]);
  2885. }
  2886. currentXPoint += _kLineWidth + _kLinePadding;
  2887. }
  2888. CGContextStrokePath(context);
  2889. //画RSI2线
  2890. CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
  2891. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2892. isInit = NO;
  2893. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2894. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2895. if (!chartData.rsi2) {
  2896. //前12根没有
  2897. } else if (chartData.rsi2 && !isInit) {
  2898. CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi2]);
  2899. isInit = YES;
  2900. } else {
  2901. CGContextAddLineToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi2]);
  2902. CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi2]);
  2903. }
  2904. currentXPoint += _kLineWidth + _kLinePadding;
  2905. }
  2906. CGContextStrokePath(context);
  2907. //画RSI3线
  2908. CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
  2909. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2910. isInit = NO;
  2911. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2912. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2913. if (!chartData.rsi3) {
  2914. //前24根没有
  2915. } else if (chartData.rsi3 && !isInit) {
  2916. CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi3]);
  2917. isInit = YES;
  2918. } else {
  2919. CGContextAddLineToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi3]);
  2920. CGContextMoveToPoint(context, currentXPoint, [self yRSIPointWithValue:chartData.rsi3]);
  2921. }
  2922. currentXPoint += _kLineWidth + _kLinePadding;
  2923. }
  2924. CGContextStrokePath(context);
  2925. currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  2926. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  2927. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  2928. //是否需要显示十字线
  2929. if (_isShowTipLine) {
  2930. if (_tipLineIndex == i) {
  2931. //画垂直线
  2932. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  2933. CGContextSetLineWidth(context, 1.0f);
  2934. CGContextMoveToPoint(context, currentXPonit, [self yRSIPointWithValue:[self maxRSIValueAtVisible]]);
  2935. CGContextAddLineToPoint(context, currentXPonit, [self yRSIPointWithValue:[self miniRSIValueAtVisible]]);
  2936. CGContextStrokePath(context);
  2937. //写数据
  2938. NSString *tipString = [NSString stringWithFormat:@"RSI1:%@ RSI2:%@ RSI3:%@"
  2939. ,[ChartCalculateUtils notRounding:chartData.rsi1 afterPoint:2]
  2940. ,[ChartCalculateUtils notRounding:chartData.rsi2 afterPoint:2]
  2941. ,[ChartCalculateUtils notRounding:chartData.rsi3 afterPoint:2]
  2942. ];
  2943. UIColor *profileColor = nil;
  2944. if ([chartData.closed compare:chartData.opened] == NSOrderedDescending)
  2945. profileColor = [UIColor redColor];
  2946. else if ([chartData.closed compare:chartData.opened] == NSOrderedAscending)
  2947. profileColor = _priceGreenColor;
  2948. else
  2949. profileColor = _titleColor;
  2950. [profileColor set];
  2951. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yRSIPointWithValue:[self maxRSIValueAtVisible]] - 12.0f) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2952. break;
  2953. }
  2954. }
  2955. currentXPonit += _xAxisWidth/_kLineCount;
  2956. }
  2957. }
  2958. #pragma mark - CCI指标相关
  2959. /**
  2960. * @brief 初始化CCI指标可视区数据
  2961. */
  2962. - (void)initCCIData {
  2963. //获取RSI可视区最大值与最小值
  2964. _indicatorCCIMaxValue = [[self maxCCIValueAtVisible] floatValue];
  2965. _indicatorCCIMiniValue = [[self miniCCIValueAtVisible] floatValue];
  2966. }
  2967. /**
  2968. * @brief 画CCI指标的方法
  2969. */
  2970. - (void)drawCCI {
  2971. if (isnan([self yCCIPointWithValue:[NSDecimalNumber zero]])) return;
  2972. CGContextRef context = UIGraphicsGetCurrentContext();
  2973. CGContextSetLineWidth(context, 1.0f);
  2974. //画0线与标题
  2975. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  2976. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  2977. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2978. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2979. CGContextMoveToPoint(context, _indicatorOrigin.x, [self yCCIPointWithValue:[NSDecimalNumber zero]]);
  2980. CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yCCIPointWithValue:[NSDecimalNumber zero]]);
  2981. CGContextStrokePath(context);
  2982. [_titleColor set];
  2983. //上中下区间值 100、0、-100
  2984. NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"100"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2985. [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"100"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2986. NSString *midString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"0"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2987. [midString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"0"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2988. NSString *downString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"-100"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  2989. [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"-100"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  2990. //CCI标题
  2991. CGFloat currentXPonit = _indicatorOrigin.x;
  2992. //画0线
  2993. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  2994. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  2995. CGContextMoveToPoint(context, _kLineOrigin.x, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"0"]]);
  2996. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"0"]]);
  2997. CGContextStrokePath(context);
  2998. //画100线
  2999. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3000. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3001. CGContextMoveToPoint(context, _kLineOrigin.x, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"100"]]);
  3002. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"100"]]);
  3003. CGContextStrokePath(context);
  3004. //画-100线
  3005. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3006. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3007. CGContextMoveToPoint(context, _kLineOrigin.x, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"-100"]]);
  3008. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yCCIPointWithValue:[NSDecimalNumber decimalNumberWithString:@"-100"]]);
  3009. CGContextStrokePath(context);
  3010. //画CCI线
  3011. CGContextSetRGBStrokeColor(context, _cciRed, _cciGreen, _cciBlue, _cciAlpha);
  3012. CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f; BOOL isInit = NO;
  3013. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3014. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3015. if (!chartData.cci) {
  3016. //前14根没有
  3017. } else if (chartData.cci && !isInit) {
  3018. CGContextMoveToPoint(context, currentXPoint, [self yCCIPointWithValue:chartData.cci]);
  3019. isInit = YES;
  3020. } else {
  3021. CGContextAddLineToPoint(context, currentXPoint, [self yCCIPointWithValue:chartData.cci]);
  3022. CGContextMoveToPoint(context, currentXPoint, [self yCCIPointWithValue:chartData.cci]);
  3023. }
  3024. currentXPoint += _kLineWidth + _kLinePadding;
  3025. }
  3026. CGContextStrokePath(context);
  3027. currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3028. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3029. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3030. //是否需要显示十字线
  3031. if (_isShowTipLine) {
  3032. if (_tipLineIndex == i) {
  3033. //画垂直线
  3034. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  3035. CGContextSetLineWidth(context, 1.0f);
  3036. CGContextMoveToPoint(context, currentXPonit, [self yCCIPointWithValue:[self maxCCIValueAtVisible]]);
  3037. CGContextAddLineToPoint(context, currentXPonit, [self yCCIPointWithValue:[self miniCCIValueAtVisible]]);
  3038. CGContextStrokePath(context);
  3039. if (chartData.cci) {
  3040. //写数据
  3041. 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}];
  3042. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yCCIPointWithValue:[self maxCCIValueAtVisible]] - 12.0f)];
  3043. }
  3044. break;
  3045. }
  3046. }
  3047. currentXPonit += _xAxisWidth/_kLineCount;
  3048. }
  3049. }
  3050. #pragma mark - DMA指标相关
  3051. /**
  3052. * @brief 初始化DMA指标可视区数据
  3053. */
  3054. - (void)initDMAData {
  3055. //获取DMA可视区最大值与最小值
  3056. _indicatorDMAMaxValue = [[self maxDMAValueAtVisible] floatValue];
  3057. _indicatorDMAMiniValue = [[self miniDMAValueAtVisible] floatValue];
  3058. }
  3059. /**
  3060. * @brief 画DMA指标的方法
  3061. */
  3062. - (void)drawDMA {
  3063. if (isnan([self yDMAPointWithValue:[NSDecimalNumber zero]])) return;
  3064. CGContextRef context = UIGraphicsGetCurrentContext();
  3065. CGContextSetLineWidth(context, 1.0f);
  3066. //画0线与标题
  3067. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  3068. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  3069. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3070. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3071. CGContextMoveToPoint(context, _indicatorOrigin.x, [self yDMAPointWithValue:[NSDecimalNumber zero]]);
  3072. CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yDMAPointWithValue:[NSDecimalNumber zero]]);
  3073. CGContextStrokePath(context);
  3074. [_titleColor set];
  3075. NSDecimalNumber *maxValue = [self maxDMAValueAtVisible];
  3076. NSDecimalNumber *miniValue = [self miniDMAValueAtVisible];
  3077. NSDecimalNumber *midValue = [[miniValue decimalNumberByAdding:maxValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]];
  3078. NSString *upString = [ChartCalculateUtils notRounding:maxValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  3079. [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yDMAPointWithValue:maxValue]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  3080. NSString *midString = [ChartCalculateUtils notRounding:midValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  3081. [midString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yDMAPointWithValue:midValue]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  3082. NSString *downString = [ChartCalculateUtils notRounding:miniValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  3083. [downString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yDMAPointWithValue:miniValue] - 8.0f) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  3084. CGFloat currentXPonit = _indicatorOrigin.x;
  3085. //画1线
  3086. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3087. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3088. CGContextMoveToPoint(context, _kLineOrigin.x, [self yDMAPointWithValue:maxValue]);
  3089. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yDMAPointWithValue:maxValue]);
  3090. CGContextStrokePath(context);
  3091. //画-1线
  3092. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3093. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3094. CGContextMoveToPoint(context, _kLineOrigin.x, [self yDMAPointWithValue:midValue]);
  3095. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yDMAPointWithValue:midValue]);
  3096. CGContextStrokePath(context);
  3097. //画-2线
  3098. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3099. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3100. CGContextMoveToPoint(context, _kLineOrigin.x, [self yDMAPointWithValue:miniValue]);
  3101. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yDMAPointWithValue:miniValue]);
  3102. CGContextStrokePath(context);
  3103. //画DMA线
  3104. CGContextSetRGBStrokeColor(context, _dmaRed, _dmaGreen, _dmaBlue, _dmaAlpha);
  3105. CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3106. BOOL isInit = NO;
  3107. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3108. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3109. if (!chartData.dma) {
  3110. //前10根没有
  3111. } else if (chartData.dma && !isInit) {
  3112. CGContextMoveToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.dma]);
  3113. isInit = YES;
  3114. } else {
  3115. CGContextAddLineToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.dma]);
  3116. CGContextMoveToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.dma]);
  3117. }
  3118. currentXPoint += _kLineWidth + _kLinePadding;
  3119. }
  3120. CGContextStrokePath(context);
  3121. //画AMA线
  3122. CGContextSetRGBStrokeColor(context, _amaRed, _amaGreen, _amaBlue, _amaAlpha);
  3123. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3124. isInit = NO;
  3125. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3126. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3127. if (!chartData.ama) {
  3128. //前10根没有
  3129. } else if (chartData.ama && !isInit) {
  3130. CGContextMoveToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.ama]);
  3131. isInit = YES;
  3132. } else {
  3133. CGContextAddLineToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.ama]);
  3134. CGContextMoveToPoint(context, currentXPoint, [self yDMAPointWithValue:chartData.ama]);
  3135. }
  3136. currentXPoint += _kLineWidth + _kLinePadding;
  3137. }
  3138. CGContextStrokePath(context);
  3139. currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3140. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3141. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3142. //是否需要显示十字线
  3143. if (_isShowTipLine) {
  3144. if (_tipLineIndex == i) {
  3145. //画垂直线
  3146. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  3147. CGContextSetLineWidth(context, 1.0f);
  3148. CGContextMoveToPoint(context, currentXPonit, [self yDMAPointWithValue:[self maxDMAValueAtVisible]]);
  3149. CGContextAddLineToPoint(context, currentXPonit, [self yDMAPointWithValue:[self miniDMAValueAtVisible]]);
  3150. CGContextStrokePath(context);
  3151. //写数据
  3152. 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}];
  3153. 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}];
  3154. [tipString appendAttributedString:stringTwo];
  3155. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yDMAPointWithValue:[self maxDMAValueAtVisible]] - 12.0f)];
  3156. break;
  3157. }
  3158. }
  3159. currentXPonit += _xAxisWidth/_kLineCount;
  3160. }
  3161. }
  3162. #pragma mark - BIAS指标相关
  3163. /**
  3164. * @brief 初始化BIAS指标可视区数据
  3165. */
  3166. - (void)initBIASData {
  3167. //获取BIAS可视区最大值与最小值
  3168. _indicatorBIASMaxValue = [[self maxBIASValueAtVisible] floatValue];
  3169. _indicatorBIASMiniValue = [[self miniBIASValueAtVisible] floatValue];
  3170. }
  3171. /**
  3172. * @brief 画DMA指标的方法
  3173. */
  3174. - (void)drawBIAS {
  3175. if (isnan([self yBIASPointWithValue:[NSDecimalNumber zero]])) return;
  3176. CGContextRef context = UIGraphicsGetCurrentContext();
  3177. CGContextSetLineWidth(context, 1.0f);
  3178. //画0线与标题
  3179. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  3180. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  3181. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3182. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3183. CGContextMoveToPoint(context, _indicatorOrigin.x, [self yBIASPointWithValue:[NSDecimalNumber zero]]);
  3184. CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yBIASPointWithValue:[NSDecimalNumber zero]]);
  3185. CGContextStrokePath(context);
  3186. [_titleColor set];
  3187. CGFloat currentXPonit = _indicatorOrigin.x;
  3188. NSDecimalNumber *maxValue = [self maxBIASValueAtVisible];
  3189. NSDecimalNumber *miniValue = [self miniBIASValueAtVisible];
  3190. NSDecimalNumber *midValue = [[miniValue decimalNumberByAdding:maxValue] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"2"]];
  3191. NSString *upString = [ChartCalculateUtils notRounding:maxValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  3192. [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yBIASPointWithValue:maxValue]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  3193. NSString *midString = [ChartCalculateUtils notRounding:midValue afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  3194. [midString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yBIASPointWithValue:midValue]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  3195. //画1线
  3196. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3197. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3198. CGContextMoveToPoint(context, _kLineOrigin.x, [self yBIASPointWithValue:maxValue]);
  3199. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yBIASPointWithValue:maxValue]);
  3200. CGContextStrokePath(context);
  3201. //画-1线
  3202. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3203. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3204. CGContextMoveToPoint(context, _kLineOrigin.x, [self yBIASPointWithValue:midValue]);
  3205. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yBIASPointWithValue:midValue]);
  3206. CGContextStrokePath(context);
  3207. //画BIAS1线
  3208. CGContextSetRGBStrokeColor(context, _bias1Red, _bias1Green, _bias1Blue, _bias1Alpha);
  3209. CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3210. BOOL isInit = NO;
  3211. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3212. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3213. if (!chartData.bias1) {
  3214. //前6根没有
  3215. } else if (chartData.bias1 && !isInit) {
  3216. CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias1]);
  3217. isInit = YES;
  3218. } else {
  3219. CGContextAddLineToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias1]);
  3220. CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias1]);
  3221. }
  3222. currentXPoint += _kLineWidth + _kLinePadding;
  3223. }
  3224. CGContextStrokePath(context);
  3225. //画BIAS2线
  3226. CGContextSetRGBStrokeColor(context, _bias2Red, _bias2Green, _bias2Blue, _bias2Alpha);
  3227. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3228. isInit = NO;
  3229. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3230. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3231. if (!chartData.bias2) {
  3232. //前12根没有
  3233. } else if (chartData.bias2 && !isInit) {
  3234. CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias2]);
  3235. isInit = YES;
  3236. } else {
  3237. CGContextAddLineToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias2]);
  3238. CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias2]);
  3239. }
  3240. currentXPoint += _kLineWidth + _kLinePadding;
  3241. }
  3242. CGContextStrokePath(context);
  3243. //画BIAS3线
  3244. CGContextSetRGBStrokeColor(context, _bias3Red, _bias3Green, _bias3Blue, _bias3Alpha);
  3245. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3246. isInit = NO;
  3247. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3248. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3249. if (!chartData.bias3) {
  3250. //前24根没有
  3251. } else if (chartData.bias3 && !isInit) {
  3252. CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias3]);
  3253. isInit = YES;
  3254. } else {
  3255. CGContextAddLineToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias3]);
  3256. CGContextMoveToPoint(context, currentXPoint, [self yBIASPointWithValue:chartData.bias3]);
  3257. }
  3258. currentXPoint += _kLineWidth + _kLinePadding;
  3259. }
  3260. CGContextStrokePath(context);
  3261. currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3262. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3263. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3264. //是否需要显示十字线
  3265. if (_isShowTipLine) {
  3266. if (_tipLineIndex == i) {
  3267. //画垂直线
  3268. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  3269. CGContextSetLineWidth(context, 1.0f);
  3270. CGContextMoveToPoint(context, currentXPonit, [self yBIASPointWithValue:[self maxBIASValueAtVisible]]);
  3271. CGContextAddLineToPoint(context, currentXPonit, [self yBIASPointWithValue:[self miniBIASValueAtVisible]]);
  3272. CGContextStrokePath(context);
  3273. //写数据
  3274. 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}];
  3275. 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}];
  3276. 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}];
  3277. [tipString appendAttributedString:stringTwo];
  3278. [tipString appendAttributedString:stringThree];
  3279. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yBIASPointWithValue:[self maxBIASValueAtVisible]] - 12.0f)];
  3280. break;
  3281. }
  3282. }
  3283. currentXPonit += _xAxisWidth/_kLineCount;
  3284. }
  3285. }
  3286. #pragma mark - PSY指标相关
  3287. /**
  3288. * @brief 初始化PSY指标可视区数据
  3289. */
  3290. - (void)initPSYData {
  3291. //获取BIAS可视区最大值与最小值
  3292. _indicatorPSYMaxValue = [[self maxPSYValueAtVisible] floatValue];
  3293. _indicatorPSYMiniValue = [[self miniPSYValueAtVisible] floatValue];
  3294. }
  3295. /**
  3296. * @brief 画PSY指标的方法
  3297. */
  3298. - (void)drawPSY {
  3299. if (isnan([self yPSYPointWithValue:[NSDecimalNumber zero]])) return;
  3300. CGContextRef context = UIGraphicsGetCurrentContext();
  3301. CGContextSetLineWidth(context, 1.0f);
  3302. //画0线与标题
  3303. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  3304. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  3305. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3306. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3307. CGContextMoveToPoint(context, _indicatorOrigin.x, [self yPSYPointWithValue:[NSDecimalNumber zero]]);
  3308. CGContextAddLineToPoint(context, _indicatorOrigin.x + _xAxisWidth,[self yPSYPointWithValue:[NSDecimalNumber zero]]);
  3309. CGContextStrokePath(context);
  3310. [_titleColor set];
  3311. CGFloat currentXPonit = _indicatorOrigin.x;
  3312. NSString *upString = [ChartCalculateUtils notRounding:[NSDecimalNumber decimalNumberWithString:@"50"] afterPoint:[ChartCalculateUtils getDecimalDigits:_minUnit]];
  3313. [upString drawAtPoint:CGPointMake(priceXOffset + _excessXAxisWidth, [self yPSYPointWithValue:[NSDecimalNumber decimalNumberWithString:@"50"]]) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  3314. //画50线
  3315. [_lineColor getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3316. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3317. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPSYPointWithValue:[NSDecimalNumber decimalNumberWithString:@"50"]]);
  3318. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yPSYPointWithValue:[NSDecimalNumber decimalNumberWithString:@"50"]]);
  3319. CGContextStrokePath(context);
  3320. //画PSY线
  3321. CGContextSetRGBStrokeColor(context, _psyRed, _psyGreen, _psyBlue, _psyAlpha);
  3322. CGFloat currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3323. BOOL isInit = NO;
  3324. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3325. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3326. if (!chartData.psy) {
  3327. //前12根没有
  3328. } else if (chartData.psy && !isInit) {
  3329. CGContextMoveToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psy]);
  3330. isInit = YES;
  3331. } else {
  3332. CGContextAddLineToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psy]);
  3333. CGContextMoveToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psy]);
  3334. }
  3335. currentXPoint += _kLineWidth + _kLinePadding;
  3336. }
  3337. CGContextStrokePath(context);
  3338. //画PSYMA线
  3339. CGContextSetRGBStrokeColor(context, _psymaRed, _psymaGreen, _psymaBlue, _psymaAlpha);
  3340. currentXPoint = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3341. isInit = NO;
  3342. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3343. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3344. if (!chartData.psyma) {
  3345. //前6根没有
  3346. } else if (chartData.psyma && !isInit) {
  3347. CGContextMoveToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psyma]);
  3348. isInit = YES;
  3349. } else {
  3350. CGContextAddLineToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psyma]);
  3351. CGContextMoveToPoint(context, currentXPoint, [self yPSYPointWithValue:chartData.psyma]);
  3352. }
  3353. currentXPoint += _kLineWidth + _kLinePadding;
  3354. }
  3355. CGContextStrokePath(context);
  3356. currentXPonit = _kLineOrigin.x + _kLineWidth/2 + 1.0f;
  3357. for (NSInteger i=_kLineStartIndex ; i>=_kLineEndIndex ; i--) {
  3358. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3359. //是否需要显示十字线
  3360. if (_isShowTipLine) {
  3361. if (_tipLineIndex == i) {
  3362. //画垂直线
  3363. CGContextSetRGBStrokeColor(context, _tipRed, _tipGreen, _tipBlue, _tipAlpha);
  3364. CGContextSetLineWidth(context, 1.0f);
  3365. CGContextMoveToPoint(context, currentXPonit, [self yPSYPointWithValue:[self maxPSYValueAtVisible]]);
  3366. CGContextAddLineToPoint(context, currentXPonit, [self yPSYPointWithValue:[self miniPSYValueAtVisible]]);
  3367. CGContextStrokePath(context);
  3368. //写数据
  3369. 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}];
  3370. 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}];
  3371. [tipString appendAttributedString:stringTwo];
  3372. [tipString drawAtPoint:CGPointMake(_kLineOrigin.x, [self yPSYPointWithValue:[self maxPSYValueAtVisible]] - 12.0f)];
  3373. break;
  3374. }
  3375. }
  3376. currentXPonit += _xAxisWidth/_kLineCount;
  3377. }
  3378. }
  3379. #pragma mark - 画现价相关
  3380. /**
  3381. * @brief 画现价的方法
  3382. */
  3383. - (void)drawPrice {
  3384. if (!_isShowPrice) return;
  3385. CGContextRef context = UIGraphicsGetCurrentContext();
  3386. //横轴价格
  3387. CGFloat priceXOffset = _xAxisPaddingLeft + _xAxisWidth; //价格左边距
  3388. NSInteger decimalNumber = [ChartCalculateUtils getDecimalDigits:_minUnit];
  3389. NSString *priceString = [ChartCalculateUtils notRounding:_price afterPoint:decimalNumber];
  3390. CGSize priceStringSize = [priceString sizeWithAttributes:@{NSFontAttributeName:_titleFont}];
  3391. //最大最小值判断
  3392. CGFloat priceYOffset = [self yPointWithPrice:_price]-priceStringSize.height/2;
  3393. NSDecimalNumber *max = [self maxPriceAtVisible];
  3394. NSDecimalNumber *min = [self minPriceAtVisible];
  3395. // 这里有可能最大值和最小值相等
  3396. if ([max compare:min] == NSOrderedSame) {
  3397. ChartData *chartData = _chartDataArray[0];
  3398. max = [chartData.closed decimalNumberByAdding:[_minUnit decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInt:20]]];
  3399. }
  3400. if ([_price compare:max] == NSOrderedDescending) priceYOffset = _yAxisPaddingTop - priceStringSize.height;
  3401. if ([_price compare:min] == NSOrderedAscending) priceYOffset = _kLineOrigin.y;
  3402. if (priceYOffset != NAN) {
  3403. CGContextSetRGBFillColor(context, 1.0f, 1.0f, 0.0f, 0.5f);
  3404. CGContextAddRect(context, CGRectMake(priceXOffset, priceYOffset, priceXOffset +_xAxisPaddingRight, priceStringSize.height));
  3405. CGContextFillPath(context);
  3406. [[UIColor blackColor] set];
  3407. [priceString drawAtPoint:CGPointMake(priceXOffset+_excessXAxisWidth, priceYOffset) withAttributes:@{NSFontAttributeName: _titleFont, NSForegroundColorAttributeName: _titleColor}];
  3408. CGFloat red = 1.0, green = 1.0, blue = 1.0, alpha = 1.0;
  3409. //画100线
  3410. [[UIColor grayColor] getRed:&red green:&green blue:&blue alpha:&alpha]; // 向red等设置值
  3411. CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
  3412. CGContextMoveToPoint(context, _kLineOrigin.x, [self yPointWithPrice:_price]);
  3413. CGContextAddLineToPoint(context, _xAxisPaddingLeft + _xAxisWidth, [self yPointWithPrice:_price]);
  3414. CGFloat arr[] = {3, 1};
  3415. //下面最后一个参数“2”代表排列的个数。
  3416. CGContextSetLineDash(context, 0, arr, 2);
  3417. //画线
  3418. CGContextDrawPath(context, kCGPathStroke);
  3419. }
  3420. }
  3421. #pragma mark - K线数值计算相关
  3422. /**
  3423. * @brief 获取当前可视区K线最大价格值的方法
  3424. *
  3425. * @return 当前可视区K线最大价格值
  3426. */
  3427. - (nullable NSDecimalNumber *)maxPriceAtVisible {
  3428. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3429. NSDecimalNumber *maxValue = [NSDecimalNumber zero];
  3430. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3431. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3432. if ([chartData.opened compare:maxValue] == NSOrderedDescending) maxValue = chartData.opened;
  3433. if ([chartData.closed compare:maxValue] == NSOrderedDescending) maxValue = chartData.closed;
  3434. if ([chartData.highest compare:maxValue] == NSOrderedDescending) maxValue = chartData.highest;
  3435. if (chartData.ma5) {
  3436. if ([chartData.ma5 compare:maxValue] == NSOrderedDescending) maxValue = chartData.ma5;
  3437. }
  3438. if (chartData.ma10) {
  3439. if ([chartData.ma10 compare:maxValue] == NSOrderedDescending) maxValue = chartData.ma10;
  3440. }
  3441. if (chartData.ma15) {
  3442. if ([chartData.ma15 compare:maxValue] == NSOrderedDescending) maxValue = chartData.ma15;
  3443. }
  3444. }
  3445. return maxValue ? maxValue : [NSDecimalNumber zero];
  3446. }
  3447. /**
  3448. * @brief 获取当前可视区K线最小价格值的方法
  3449. *
  3450. * @return 当前可视区K线最小价格值
  3451. */
  3452. - (nullable NSDecimalNumber *)minPriceAtVisible {
  3453. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3454. NSDecimalNumber *minValue = [NSDecimalNumber maximumDecimalNumber];
  3455. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3456. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3457. if ([chartData.opened compare:minValue] == NSOrderedAscending) minValue = chartData.opened;
  3458. if ([chartData.closed compare:minValue] == NSOrderedAscending) minValue = chartData.closed;
  3459. if ([chartData.lowest compare:minValue] == NSOrderedAscending) minValue = chartData.lowest;
  3460. if (chartData.ma5) {
  3461. if ([chartData.ma5 compare:minValue] == NSOrderedAscending) minValue = chartData.ma5;
  3462. }
  3463. if (chartData.ma10) {
  3464. if ([chartData.ma10 compare:minValue] == NSOrderedAscending) minValue = chartData.ma10;
  3465. }
  3466. if (chartData.ma15) {
  3467. if ([chartData.ma15 compare:minValue] == NSOrderedAscending) minValue = chartData.ma15;
  3468. }
  3469. }
  3470. return minValue ? minValue : [NSDecimalNumber zero];
  3471. }
  3472. /**
  3473. * @brief 获取指定价格的K线Y轴坐标
  3474. *
  3475. * @param price 目标价格
  3476. *
  3477. * @return 指定价格的K线Y轴坐标
  3478. */
  3479. - (CGFloat)yPointWithPrice:(nullable NSDecimalNumber *)price {
  3480. CGFloat yPoint = _yAxisHeight - (_yAxisHeight/(_yAxisMaxValue - _yAxisMinValue)) * ([price floatValue] - _yAxisMinValue) + _yAxisPaddingTop;
  3481. return yPoint ;
  3482. }
  3483. /**
  3484. * @brief 获取指定Y轴坐标的价格
  3485. *
  3486. * @param yPoint 目标Y轴坐标
  3487. *
  3488. * @return 指定Y轴坐标的价格
  3489. */
  3490. - (nullable NSDecimalNumber *)priceWithYPoint:(CGFloat)yPoint {
  3491. float priceValue = _yAxisMinValue + (_yAxisHeight + _yAxisPaddingTop - yPoint)/(_yAxisHeight/(_yAxisMaxValue - _yAxisMinValue));
  3492. return [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",priceValue]];
  3493. }
  3494. #pragma mark - 整体指标相关
  3495. /**
  3496. * @brief 设置是否需要显示指标
  3497. *
  3498. * @param isShowIndicator 是否需要显示指标
  3499. */
  3500. - (void)setIsShowIndicator:(BOOL)isShowIndicator {
  3501. _isShowIndicator = isShowIndicator;
  3502. if (!_isShowIndicator) {
  3503. _indicatorHight = 0;
  3504. _indicatorPaddingBottom = 0;
  3505. }
  3506. }
  3507. /// 是否显示开高低收
  3508. /// @param isShowOHLP isShowOHLP
  3509. - (void)setIsShowOHLP:(BOOL)isShowOHLP {
  3510. _isShowOHLP = isShowOHLP;
  3511. }
  3512. #pragma mark - MACD数值计算相关
  3513. /**
  3514. * @brief 获取当前可视区MACD线最大值的方法
  3515. *
  3516. * @return 当前可视区MACD线最大值
  3517. */
  3518. - (nullable NSDecimalNumber *)maxMACDValueAtVisible {
  3519. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3520. NSDecimalNumber *maxValue = [NSDecimalNumber zero];
  3521. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3522. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3523. if (chartData.dif) {
  3524. if ([chartData.dif compare:maxValue] == NSOrderedDescending) maxValue = chartData.dif;
  3525. }
  3526. if (chartData.dea) {
  3527. if ([chartData.dea compare:maxValue] == NSOrderedDescending) maxValue = chartData.dea;
  3528. }
  3529. if (chartData.macd) {
  3530. if ([chartData.macd compare:maxValue] == NSOrderedDescending) maxValue = chartData.macd;
  3531. }
  3532. }
  3533. return maxValue;
  3534. }
  3535. /**
  3536. * @brief 获取当前可视区MACD线最小值的方法
  3537. *
  3538. * @return 当前可视区MACD线最小值
  3539. */
  3540. - (nullable NSDecimalNumber *)minMACDValueAtVisible {
  3541. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3542. NSDecimalNumber *minValue = [NSDecimalNumber zero];
  3543. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3544. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3545. if (chartData.dif) {
  3546. if ([chartData.dif compare:minValue] == NSOrderedAscending) minValue = chartData.dif;
  3547. }
  3548. if (chartData.dea) {
  3549. if ([chartData.dea compare:minValue] == NSOrderedAscending) minValue = chartData.dea;
  3550. }
  3551. if (chartData.macd) {
  3552. if ([chartData.macd compare:minValue] == NSOrderedAscending) minValue = chartData.macd;
  3553. }
  3554. }
  3555. return minValue;
  3556. }
  3557. /**
  3558. * @brief 获取指定值的MACD线Y轴坐标
  3559. *
  3560. * @param value 目标价格
  3561. *
  3562. * @return 指定值的MACD线Y轴坐标
  3563. */
  3564. - (CGFloat)yMACDPointWithValue:(nullable NSDecimalNumber *)value {
  3565. CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorMaxValue - _indicatorMinValue)) * ([value floatValue] - _indicatorMinValue) + _kLineOrigin.y + _yAxisPaddingBottom;
  3566. return yPoitn;
  3567. }
  3568. #pragma mark - VOL数值计算相关
  3569. /**
  3570. * @brief 获取当前可视区VOL线最大值的方法
  3571. *
  3572. * @return 当前可视区VOL线最大值
  3573. */
  3574. - (nullable NSDecimalNumber *)maxVOLValueAtVisible {
  3575. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3576. NSDecimalNumber *maxValue = [NSDecimalNumber zero];
  3577. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3578. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3579. if (chartData.totleVolume) {
  3580. if ([chartData.totleVolume compare:maxValue] == NSOrderedDescending) maxValue = chartData.totleVolume;
  3581. }
  3582. }
  3583. return maxValue;
  3584. }
  3585. /**
  3586. * @brief 获取当前可视区VOL线最大值的方法
  3587. *
  3588. * @return 当前可视区VOL线最大值
  3589. */
  3590. - (nullable NSDecimalNumber *)miniVOLValueAtVisible {
  3591. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3592. NSDecimalNumber *minValue = [NSDecimalNumber zero];
  3593. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3594. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3595. if (chartData.totleVolume) {
  3596. if ([chartData.totleVolume compare:minValue] != NSOrderedDescending) minValue = chartData.totleVolume;
  3597. }
  3598. }
  3599. return minValue;
  3600. }
  3601. /**
  3602. * @brief 获取指定值的VOL线Y轴坐标
  3603. *
  3604. * @param value 目标价格
  3605. *
  3606. * @return 指定值的VOL线Y轴坐标
  3607. */
  3608. - (CGFloat)yVOLPointWithValue:(nullable NSDecimalNumber *)value {
  3609. CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorVOLMaxValue - _indicatorVOLMiniValue)) * ([value floatValue] - _indicatorVOLMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
  3610. return yPoitn;
  3611. }
  3612. #pragma mark - KDJ数值计算相关
  3613. /**
  3614. * @brief 获取当前可视区KDJ线最大值的方法
  3615. *
  3616. * @return 当前可视区KDJ线最大值
  3617. */
  3618. - (nullable NSDecimalNumber *)maxKDJValueAtVisible {
  3619. return [NSDecimalNumber decimalNumberWithString:@"130"];
  3620. }
  3621. /**
  3622. * @brief 获取当前可视区KDJ线最小值的方法
  3623. *
  3624. * @return 当前可视区KDJ线最小值
  3625. */
  3626. - (nullable NSDecimalNumber *)miniKDJValueAtVisible {
  3627. return [NSDecimalNumber decimalNumberWithString:@"-30"];
  3628. }
  3629. /**
  3630. * @brief 获取指定值的KDJ线Y轴坐标
  3631. *
  3632. * @param value 目标价格
  3633. *
  3634. * @return 指定值的KDJ线Y轴坐标
  3635. */
  3636. - (CGFloat)yKDJPointWithValue:(nullable NSDecimalNumber *)value {
  3637. CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorKDJMaxValue - _indicatorKDJMiniValue)) * ([value floatValue] - _indicatorKDJMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
  3638. return yPoitn;
  3639. }
  3640. #pragma mark - RSI数值计算相关
  3641. /**
  3642. * @brief 获取当前可视区RSI线最大值的方法
  3643. *
  3644. * @return 当前可视区RSI线最大值
  3645. */
  3646. - (nullable NSDecimalNumber *)maxRSIValueAtVisible {
  3647. return [NSDecimalNumber decimalNumberWithString:@"100"];
  3648. }
  3649. /**
  3650. * @brief 获取当前可视区RSI线最小值的方法
  3651. *
  3652. * @return 当前可视区RSI线最小值
  3653. */
  3654. - (nullable NSDecimalNumber *)miniRSIValueAtVisible {
  3655. return [NSDecimalNumber decimalNumberWithString:@"0"];
  3656. }
  3657. /**
  3658. * @brief 获取指定值的RSI线Y轴坐标
  3659. *
  3660. * @param value 目标价格
  3661. *
  3662. * @return 指定值的RSI线Y轴坐标
  3663. */
  3664. - (CGFloat)yRSIPointWithValue:(NSDecimalNumber *)value {
  3665. CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorRSIMaxValue - _indicatorRSIMiniValue)) * ([value floatValue] - _indicatorRSIMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
  3666. return yPoitn;
  3667. }
  3668. #pragma mark - CCI数值计算相关
  3669. /**
  3670. * @brief 获取当前可视区CCI线最大值的方法
  3671. *
  3672. * @return 当前可视区CCI线最大值
  3673. */
  3674. - (nullable NSDecimalNumber *)maxCCIValueAtVisible {
  3675. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3676. NSDecimalNumber *maxValue = [NSDecimalNumber zero];
  3677. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3678. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3679. if (chartData.cci) {
  3680. if ([chartData.cci compare:maxValue] == NSOrderedDescending) maxValue = chartData.cci;
  3681. }
  3682. }
  3683. return maxValue;
  3684. }
  3685. /**
  3686. * @brief 获取当前可视区CCI线最小值的方法
  3687. *
  3688. * @return 当前可视区CCI线最小值
  3689. */
  3690. - (nullable NSDecimalNumber *)miniCCIValueAtVisible {
  3691. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3692. NSDecimalNumber *minValue = [NSDecimalNumber zero];
  3693. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3694. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3695. if (chartData.cci) {
  3696. if ([chartData.cci compare:minValue] != NSOrderedDescending) minValue = chartData.cci;
  3697. }
  3698. }
  3699. return minValue;
  3700. }
  3701. /**
  3702. * @brief 获取指定值的CCI线Y轴坐标
  3703. *
  3704. * @param value 目标价格
  3705. *
  3706. * @return 指定值的CCI线Y轴坐标
  3707. */
  3708. - (CGFloat)yCCIPointWithValue:(nullable NSDecimalNumber *)value {
  3709. CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorCCIMaxValue - _indicatorCCIMiniValue)) * ([value floatValue] - _indicatorCCIMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
  3710. return yPoitn;
  3711. }
  3712. #pragma mark - DMA数值计算相关
  3713. /**
  3714. * @brief 获取当前可视区DMA线最大值的方法
  3715. *
  3716. * @return 当前可视区DMA线最大值
  3717. */
  3718. - (nullable NSDecimalNumber *)maxDMAValueAtVisible {
  3719. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3720. NSDecimalNumber *maxValue = [NSDecimalNumber zero];
  3721. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3722. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3723. if (chartData.dma) {
  3724. if ([chartData.dma compare:maxValue] == NSOrderedDescending) maxValue = chartData.dma;
  3725. }
  3726. if (chartData.ama) {
  3727. if ([chartData.ama compare:maxValue] == NSOrderedDescending) maxValue = chartData.ama;
  3728. }
  3729. }
  3730. return maxValue;
  3731. }
  3732. /**
  3733. * @brief 获取当前可视区DMA线最小值的方法
  3734. *
  3735. * @return 当前可视区DMA线最小值
  3736. */
  3737. - (nullable NSDecimalNumber *)miniDMAValueAtVisible {
  3738. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3739. NSDecimalNumber *minValue = [NSDecimalNumber zero];
  3740. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3741. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3742. if (chartData.dma) {
  3743. if ([chartData.dma compare:minValue] != NSOrderedDescending) minValue = chartData.dma;
  3744. }
  3745. if (chartData.ama) {
  3746. if ([chartData.ama compare:minValue] != NSOrderedDescending) minValue = chartData.ama;
  3747. }
  3748. }
  3749. return minValue;
  3750. }
  3751. /**
  3752. * @brief 获取指定值的DMA线Y轴坐标
  3753. *
  3754. * @param value 目标价格
  3755. *
  3756. * @return 指定值的DMA线Y轴坐标
  3757. */
  3758. - (CGFloat)yDMAPointWithValue:(nullable NSDecimalNumber *)value {
  3759. CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorDMAMaxValue - _indicatorDMAMiniValue)) * ([value floatValue] - _indicatorDMAMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
  3760. return yPoitn;
  3761. }
  3762. #pragma mark - BIAS数值计算相关
  3763. /**
  3764. * @brief 获取当前可视区BIAS线最大值的方法
  3765. *
  3766. * @return 当前可视区BIAS线最大值
  3767. */
  3768. - (nullable NSDecimalNumber *)maxBIASValueAtVisible {
  3769. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3770. NSDecimalNumber *maxValue = [NSDecimalNumber zero];
  3771. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3772. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3773. if (chartData.bias1) {
  3774. if ([chartData.bias1 compare:maxValue] == NSOrderedDescending) maxValue = chartData.bias1;
  3775. }
  3776. if (chartData.bias2) {
  3777. if ([chartData.bias2 compare:maxValue] == NSOrderedDescending) maxValue = chartData.bias2;
  3778. }
  3779. if (chartData.bias3) {
  3780. if ([chartData.bias3 compare:maxValue] == NSOrderedDescending) maxValue = chartData.bias3;
  3781. }
  3782. }
  3783. return maxValue;
  3784. }
  3785. /**
  3786. * @brief 获取当前可视区BIAS线最小值的方法
  3787. *
  3788. * @return 当前可视区BIAS线最小值
  3789. */
  3790. - (nullable NSDecimalNumber *)miniBIASValueAtVisible {
  3791. if (_chartDataArray == nil || _chartDataArray.count == 0) { return [NSDecimalNumber zero]; }
  3792. NSDecimalNumber *minValue = [NSDecimalNumber zero];
  3793. for (NSInteger i=_kLineEndIndex ; i<=_kLineStartIndex ; i++) {
  3794. ChartData *chartData = [_chartDataArray objectAtIndex:i];
  3795. if (chartData.bias1) {
  3796. if ([chartData.bias1 compare:minValue] != NSOrderedDescending) minValue = chartData.bias1;
  3797. }
  3798. if (chartData.bias2) {
  3799. if ([chartData.bias2 compare:minValue] != NSOrderedDescending) minValue = chartData.bias2;
  3800. }
  3801. if (chartData.bias3) {
  3802. if ([chartData.bias3 compare:minValue] != NSOrderedDescending) minValue = chartData.bias3;
  3803. }
  3804. }
  3805. return minValue;
  3806. }
  3807. /**
  3808. * @brief 获取指定值的BIAS线Y轴坐标
  3809. *
  3810. * @param value 目标价格
  3811. *
  3812. * @return 指定值的BIAS线Y轴坐标
  3813. */
  3814. - (CGFloat)yBIASPointWithValue:(nullable NSDecimalNumber *)value {
  3815. CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorBIASMaxValue - _indicatorBIASMiniValue)) * ([value floatValue] - _indicatorBIASMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
  3816. return yPoitn;
  3817. }
  3818. #pragma mark - PSY数值计算相关
  3819. /**
  3820. * @brief 获取当前可视区PSY线最大值的方法
  3821. *
  3822. * @return 当前可视区PSY线最大值
  3823. */
  3824. - (NSDecimalNumber *)maxPSYValueAtVisible {
  3825. return [NSDecimalNumber decimalNumberWithString:@"100"];
  3826. }
  3827. /**
  3828. * @brief 获取当前可视区PSY线最小值的方法
  3829. *
  3830. * @return 当前可视区PSY线最小值
  3831. */
  3832. - (NSDecimalNumber *)miniPSYValueAtVisible {
  3833. return [NSDecimalNumber decimalNumberWithString:@"0"];
  3834. }
  3835. /**
  3836. * @brief 获取指定值的PSY线Y轴坐标
  3837. *
  3838. * @param value 目标价格
  3839. *
  3840. * @return 指定值的PSY线Y轴坐标
  3841. */
  3842. - (CGFloat)yPSYPointWithValue:(nullable NSDecimalNumber *)value {
  3843. CGFloat yPoitn = _indicatorHight - (_indicatorHight/(_indicatorPSYMaxValue - _indicatorPSYMiniValue)) * ([value floatValue] - _indicatorPSYMiniValue) + _kLineOrigin.y + _yAxisPaddingBottom;
  3844. return yPoitn;
  3845. }
  3846. #pragma mark - 分时图计算相关
  3847. /**
  3848. * @brief 获取两个时间之间的分钟数
  3849. *
  3850. * @param fromDate 开始时间
  3851. * @param toDate 结束时间
  3852. *
  3853. * @return 分钟数
  3854. */
  3855. - (NSInteger)diffMinuteWithFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
  3856. NSCalendar* chineseClendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
  3857. NSUInteger unitFlags = NSCalendarUnitMinute;
  3858. NSDateComponents *cps = [chineseClendar components:unitFlags fromDate:fromDate toDate:toDate options:0];
  3859. return [cps minute]/(_cycleInterval/60); /// 使用5分钟线需要除以5得到多余区间
  3860. }
  3861. #pragma mark - 手势交互
  3862. /**
  3863. * @brief 初始化和图标进行交互的相关手势
  3864. */
  3865. - (void)initGestureRecognizer {
  3866. /// 拖动手势
  3867. UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onPanGesture:)];
  3868. panGestureRecognizer.minimumNumberOfTouches = 1;
  3869. panGestureRecognizer.maximumNumberOfTouches = 1;
  3870. [self addGestureRecognizer:panGestureRecognizer];
  3871. /// 捏合手势
  3872. UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onPinchGesture:)];
  3873. [self addGestureRecognizer:pinchGestureRecognizer];
  3874. /// 长按手势
  3875. UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)];
  3876. longPressGestureRecognizer.delegate = self;
  3877. [self addGestureRecognizer:longPressGestureRecognizer];
  3878. }
  3879. /**
  3880. * @brief 移动手势进行移动时执行的方法
  3881. */
  3882. - (void)onPanGesture:(id)sender {
  3883. UIPanGestureRecognizer *panGestureRecognizer = (UIPanGestureRecognizer *)sender;
  3884. if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) {/// 拖动手势手势开始
  3885. CGPoint point = [panGestureRecognizer locationInView:self];
  3886. _startTouchPosition = point;
  3887. } else if (panGestureRecognizer.state == UIGestureRecognizerStateChanged){/// 拖动手势进行移动
  3888. if (!_isShowTipLine) {
  3889. /// 移动K线
  3890. /// 如果当前是分时图则什么都不做
  3891. if (_chartViewType == ChartViewTypeTSPlan && !self.isBBGoods) return;
  3892. /// Warnning:这里取translationInView可能有问题
  3893. CGPoint point = [panGestureRecognizer locationInView:self];
  3894. if (_startTouchPosition.x < point.x) {
  3895. /// 向右滑
  3896. if (_kLineStartIndex == _chartDataArray.count-1) return;
  3897. _startTouchPosition.x = point.x;
  3898. if (_kLineStartIndex+_panGestureIncrement <= _chartDataArray.count-1) {
  3899. _kLineStartIndex += _panGestureIncrement;
  3900. _kLineEndIndex += _panGestureIncrement;
  3901. } else {
  3902. /// 到达最前面
  3903. NSInteger t = _chartDataArray.count-1 - _kLineStartIndex;
  3904. _kLineStartIndex += t;
  3905. _kLineEndIndex += t;
  3906. /// 说明当前已经到达第一个图表数据
  3907. if (t <= 1) {
  3908. if (_chartDataArray.count != 0) {
  3909. /// 触发该方法 告诉上层当前已经拖动到第一个数据
  3910. if (self.delegate) [self.delegate onPanChartDataToTop];
  3911. }
  3912. }
  3913. }
  3914. [self setNeedsDisplay];
  3915. } else if (_startTouchPosition.x > point.x) {
  3916. /// 向左滑
  3917. if (_kLineEndIndex == 0) return;
  3918. _startTouchPosition.x = point.x;
  3919. if (_kLineEndIndex-_panGestureIncrement >= 0) {
  3920. _kLineStartIndex -= _panGestureIncrement;
  3921. _kLineEndIndex -= _panGestureIncrement;
  3922. } else {
  3923. /// 到达最后面
  3924. NSInteger t = _kLineEndIndex;
  3925. _kLineStartIndex -= t;
  3926. _kLineEndIndex -= t;
  3927. }
  3928. [self setNeedsDisplay];
  3929. }
  3930. } else {
  3931. /// 移动十字线
  3932. CGPoint point = [panGestureRecognizer locationInView:self];
  3933. /// 判断是否在图表区域内
  3934. if (CGRectContainsPoint(CGRectMake(_kLineOrigin.x, _yAxisPaddingTop, _xAxisWidth, _yAxisHeight), point)) {
  3935. //判断是否能获取点击位置上的K线
  3936. NSInteger tipIndex = NSNotFound;
  3937. if (_chartViewType != ChartViewTypeTSPlan) tipIndex = [self tipIndexWithXPoint:point.x];
  3938. else tipIndex = [self tipIndexTSPlanWithXPoint:point.x]; //分时图
  3939. if (tipIndex != NSNotFound) {
  3940. _tipLineIndex = tipIndex;
  3941. _tipLineYAxis = point.y;
  3942. [self setNeedsDisplay];
  3943. }
  3944. }
  3945. }
  3946. }
  3947. }
  3948. /**
  3949. * @brief 捏合手势进行捏合时执行的方法
  3950. */
  3951. - (void)onPinchGesture:(id)sender {
  3952. //如果当前是分时图则什么都不做
  3953. if (_chartViewType == ChartViewTypeTSPlan) return;
  3954. UIPinchGestureRecognizer *pinchGestureRecognizer = (UIPinchGestureRecognizer *)sender;
  3955. //捏合手势开始
  3956. if (pinchGestureRecognizer.state == UIGestureRecognizerStateBegan) {
  3957. _startScale = pinchGestureRecognizer.scale;
  3958. } else if (pinchGestureRecognizer.state == UIGestureRecognizerStateChanged) {//捏合手势进行捏合
  3959. if (pinchGestureRecognizer.scale - _startScale > 0.05f) {
  3960. _startScale = pinchGestureRecognizer.scale;
  3961. //放大到最大
  3962. if (_kLineWidth >= _kLineMaxWidth) return;
  3963. _kLineWidth++;
  3964. NSInteger lastKLineCount = _kLineCount;
  3965. // _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding)) - _ts_remove_count;
  3966. _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding));
  3967. if (_kLineCount < 0) _kLineCount = 0;
  3968. //判断当前最大显示数量是否已经小于原先最大显示数量(这一层好像是多余了,应该都是小于的)
  3969. if (_kLineCount < lastKLineCount) {
  3970. //判断原先已经显示的数量是否已经大于现在最大数量
  3971. if (_kLineStartIndex-_kLineEndIndex+1 > _kLineCount) {
  3972. //是的话就要减少显示数量了
  3973. if (_kLineStartIndex == _chartDataArray.count-1) {
  3974. //动后面
  3975. _kLineEndIndex += (_kLineStartIndex-_kLineEndIndex+1-_kLineCount);
  3976. } else {
  3977. //动前面
  3978. _kLineStartIndex -= (_kLineStartIndex-_kLineEndIndex+1-_kLineCount);
  3979. }
  3980. }
  3981. }
  3982. [self setNeedsDisplay];
  3983. } else if (_startScale - pinchGestureRecognizer.scale > 0.05f) {
  3984. _startScale = pinchGestureRecognizer.scale;
  3985. //缩小
  3986. if (_kLineWidth <= _kLineMinWidth) return;
  3987. _kLineWidth--;
  3988. NSInteger lastKLineCount = _kLineCount;
  3989. // _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding)) - _ts_remove_count;
  3990. _kLineCount = (_xAxisWidth / (_kLineWidth + _kLinePadding));
  3991. if (_kLineCount < 0) _kLineCount = 0;
  3992. //判断当前最大显示数据是否已经大于原先最大显示数量
  3993. if (_kLineCount > lastKLineCount) {
  3994. //判断原先已经显示的数量是否已经小于现在最大数量,同时还能增加显示数量
  3995. if ((_kLineStartIndex-_kLineEndIndex+1<_kLineCount) && (_kLineStartIndex-_kLineEndIndex+1<_chartDataArray.count)) {
  3996. //是的话就要增加显示数量了
  3997. if (_kLineStartIndex == _chartDataArray.count-1) {
  3998. //动后面
  3999. _kLineEndIndex -= (_kLineCount - (_kLineStartIndex-_kLineEndIndex+1));
  4000. if (_kLineEndIndex<0) _kLineEndIndex=0;
  4001. } else {
  4002. //动前面
  4003. _kLineStartIndex += (_kLineCount - (_kLineStartIndex-_kLineEndIndex+1));
  4004. if (_kLineStartIndex>_chartDataArray.count-1) _kLineStartIndex=_chartDataArray.count-1;
  4005. }
  4006. }
  4007. }
  4008. [self setNeedsDisplay];
  4009. }
  4010. }
  4011. }
  4012. /**
  4013. * @brief 长按手势进行长按时执行的方法
  4014. */
  4015. - (void)onLongPressGesture:(id)sender {
  4016. UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)sender;
  4017. if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan) {//手势开始进行
  4018. CGPoint point = [longPressGestureRecognizer locationInView:self];
  4019. //判断是否在K线区域内
  4020. if (CGRectContainsPoint(CGRectMake(_kLineOrigin.x, _yAxisPaddingTop, _xAxisWidth, _yAxisHeight), point)) {
  4021. //判断是否能获取点击位置上的K线
  4022. NSInteger tipIndex = NSNotFound;
  4023. if (_chartViewType != ChartViewTypeTSPlan) {
  4024. tipIndex = [self tipIndexWithXPoint:point.x];
  4025. } else {
  4026. //分时
  4027. tipIndex = [self tipIndexTSPlanWithXPoint:point.x];
  4028. }
  4029. if (tipIndex != NSNotFound) {
  4030. //开始长按
  4031. _isShowTipLine = YES;
  4032. _tipLineIndex = tipIndex;
  4033. _tipLineYAxis = point.y;
  4034. [self setNeedsDisplay];
  4035. }
  4036. }
  4037. } else if (longPressGestureRecognizer.state == UIGestureRecognizerStateEnded) {
  4038. //长按松开
  4039. CGPoint point = [longPressGestureRecognizer locationInView:self];
  4040. _startTouchPosition = point;
  4041. _isShowTipLine = NO;
  4042. [self setNeedsDisplay];
  4043. }
  4044. }
  4045. #pragma mark - UIGestureRecognizerDelegate
  4046. - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
  4047. if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) return YES;
  4048. return NO;
  4049. }
  4050. - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
  4051. if ([gestureRecognizer isMemberOfClass:[UIPanGestureRecognizer class]]) {
  4052. CGPoint translation = [(UIPanGestureRecognizer*)gestureRecognizer translationInView:self];
  4053. if (fabs(translation.y) > fabs(translation.x)) { //上下方向
  4054. return NO;
  4055. }
  4056. }
  4057. return YES;
  4058. }
  4059. @end