如果接触到股票、期货或者现货方面的项目的话,那么K线和指标是必须要有的,K线
表示商品价格的走势,指标则是反映价格运行趋势的重要标识。常见的K线图
有1分钟K线
,3分钟K线
,5分钟K线
,15分钟K线
,30分钟K线
,60分钟K线
,日K
,周K
,月K
,季K
,年K
。指标也有很多种,比如VOL
,MACD
,BOLL
,KDJ
,RSI
,三线出击
,庄家潜伏
,短线操盘
,中线操盘
,王牌狙击
等上百种指标。
由于项目的需要,笔者在今年6月份重构了K线库
,后面又做了一次性能优化,目前框架比较稳定,公司项目在用。
分时图
分时图.pngK线和指标
MA-VOL.png 短线-VOL.png MA-MACD.png MA-KDJ.png MA-三线出击.pngK线和指标绘制用到的类
CAShapeLayer + UIBezierPath
优点:
- 渲染速度快,
CAShapeLayer
使用了硬件加速,绘制图像比用Core Graphics
快。 - 高效使用内存。
- 效率高,滑动流畅,无明显卡顿,
FPS
在50
以上。
K线类的设计
#pragma mark - K线
/// K线数据源
@property (nonatomic, strong) NSArray<KLKlineData *> *klineDataArray;
/// 可视区域显示多少根k线
@property (nonatomic, assign) NSInteger displayCount;
/// k线图主体宽度
@property (nonatomic, assign, readonly) CGFloat klineWidth;
/// k线之间的空隙
@property (nonatomic, assign, readonly) CGFloat klineSpaceWidth;
/// 是否支持缩放
@property (nonatomic, assign, getter=isZoomEnable) BOOL zoomEnable;
/// 是否支持长按
@property (nonatomic, assign, getter=isLongPressEnable) BOOL longPressEnable;
#pragma mark - 指标
/// 主图指标
@property (nonatomic, strong) KLIndexTechnicalResult *mainTechnicalResult;
/// 附图指标
@property (nonatomic, strong) KLIndexTechnicalResult *subTechnicalResult;
#pragma mark -
/// 绘制k线
- (void)drawKlineView;
指标形状
为了对指标绘制进行封装,把所有的指标按照形状进行归类。以前需求中只有几种指标,可以对每种指标进行单独绘制,也就是每添加一种指标就需要重新创建一个类。但是后续需求添加了几十种指标,所以单独绘制的做法已经行不通了。目前比较好的做法就是根据形状进行绘制,从上百种指标来看,类型也就10多种
。
//指标形状
typedef NS_ENUM(NSInteger, KLKlineTechnicalShapeType)
{
KLKlineTechnicalShapeTypeCurveLine, /* 线 */
KLKlineTechnicalShapeTypeFillVol, /* 成交量(实心柱子) */
KLKlineTechnicalShapeTypeStrokeVol, /* 成交量(空心柱子) */
KLKlineTechnicalShapeTypeFillCandle, /* 实心柱状 */
KLKlineTechnicalShapeTypeStrokeCandle, /* 空心柱状 */
KLKlineTechnicalShapeTypeCircle, /* 圆形 */
KLKlineTechnicalShapeTypeImage, /*图片*/
KLKlineTechnicalShapeTypeTitle, /*文字*/
KLKlineTechnicalShapeTypeTitleImage /*图片文字组合*/
//......其它形状
};
指标类型
定义具体的指标类型,方便指标切换。
/***************** 指标 ********************/
typedef NS_ENUM(NSInteger, KLKlineIndexType)
{
KLKlineIndexVolume, /* 成交量 */
KLKlineIndexTypeMacd, /* MACD */
KLKlineIndexTypeKDJ, /* KDJ */
KLKlineIndexTypeRSI, /* RSI */
KLKlineIndexTypeThreeLineAttack, /* 三线出击 */
KLKlineIndexTypeBankerLurking, /* 庄家潜伏 */
KLKlineIndexTypeThreeLineAttack2, /* 三线出击2 */
KLKlineIndexTypeMA, /* MA */
KLKlineIndexTypeShortOperate, /* 短线操盘 */
KLKlineIndexTypeMidOperate, /* 中线操盘 */
KLKlineIndexTypeAceSniper /* 王牌阻击 */
//......其它指标
};
指标绘制
绘制交给一个单独的类来处理,根据不同的形状来绘制不同的指标。
/// 绘制指标
- (void)setupIndexShapeForTechnicalWithShapeLayer:(CAShapeLayer *)shapeLayer
drawStyleData:(KLIndexDrawStyleData *)drawStyleData
startIndex:(NSInteger)startIndex
xOffset:(CGFloat)xOffset
{
KLKlineTechnicalShapeType shapeType = drawStyleData.shapeType;
if (shapeType == KLKlineTechnicalShapeTypeCurveLine)
{
[self setupCurveLineShapeForTechnicalWithShapeLayer:shapeLayer drawStyleData:drawStyleData startIndex:startIndex xOffset:xOffset];
}
else if (shapeType == KLKlineTechnicalShapeTypeFillVol ||
shapeType == KLKlineTechnicalShapeTypeStrokeVol)
{
[self setupVolShapeForTechnicalWithShapeLayer:shapeLayer shapeType:shapeType drawStyleData:drawStyleData startIndex:startIndex xOffset:xOffset];
}
else if (shapeType == KLKlineTechnicalShapeTypeFillCandle ||
shapeType == KLKlineTechnicalShapeTypeStrokeCandle)
{
[self setupFillStrokeCandleShapeForTechnicalWithShapeLayer:shapeLayer shapeType:shapeType drawStyleData:drawStyleData startIndex:startIndex xOffset:xOffset];
}
else if (shapeType == KLKlineTechnicalShapeTypeImage ||
shapeType == KLKlineTechnicalShapeTypeTitle ||
shapeType == KLKlineTechnicalShapeTypeTitleImage)
{
[self setupTitleImageShapeForTechnicalWithShapeLayer:shapeLayer shapeType:shapeType drawStyleData:drawStyleData startIndex:startIndex xOffset:xOffset];
}
//其它形状
}
绘制注意点
- 为了提高性能,只需要绘制当前一屏即可。因为
K线
数据量非常大,全部绘制出来不太现实。 - 指标一定要根据形状来绘制。
其他
经测试,当前框架的FPS
在50
以上,滑动比较流畅。
网友评论