|
|
// ChartViewController.m// HC//// Created by huilinLi on 2025/11/27.//
#import "ChartViewController.h"#import "StockKLineModel.h"
@interface ChartViewController ()
// 上方卡片容器@property (nonatomic, strong) UIView *cardContainer;// k线选择项容器@property (nonatomic, strong) UIView *kSelectContainer;// K线图表容器@property (nonatomic, strong) UIView *kLineContainer;// K线图表滚动视图@property (nonatomic, strong) UIScrollView *kLineScrollView;
// K线数据@property (nonatomic, strong) NSArray *kLineData;// 价格刻度标签@property (nonatomic, strong) NSArray *priceLabels;// 日期刻度标签@property (nonatomic, strong) NSArray *dateLabels;
// 默认展示的K线数量@property (nonatomic, assign) NSInteger visibleKLineCount;
@end
@implementation ChartViewController
- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor blackColor]; self.visibleKLineCount = 40; [self generateMockData]; [self setupSubviews]; [self setupConstraints]; dispatch_async(dispatch_get_main_queue(), ^{ [self drawKLineChart]; if (self.kLineScrollView.contentSize.width > self.kLineScrollView.bounds.size.width) { CGPoint offset = CGPointMake(self.kLineScrollView.contentSize.width - self.kLineScrollView.bounds.size.width, 0); [self.kLineScrollView setContentOffset:offset animated:NO]; } });}
#pragma mark - UI Setup-(void) setupSubviews{ // 卡片容器 _cardContainer = [[UIView alloc] init]; _cardContainer.backgroundColor = [UIColor colorWithRed:26.0/255.0 green:26.0/255.0 blue:2.0/255.0 alpha:1.0]; _cardContainer.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:_cardContainer]; UILabel *cardLabel1 = [[UILabel alloc] init]; cardLabel1.text = @"1617.060"; cardLabel1.textColor = [UIColor redColor]; cardLabel1.font = [UIFont systemFontOfSize:15]; cardLabel1.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabel1]; UILabel *cardLabel2 = [[UILabel alloc] init]; cardLabel2.text = @"-7.470"; cardLabel2.textColor = [UIColor redColor]; cardLabel2.font = [UIFont systemFontOfSize:8]; cardLabel2.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabel2]; UILabel *cardLabel3 = [[UILabel alloc] init]; cardLabel3.text = @"-0.461%"; cardLabel3.textColor = [UIColor redColor]; cardLabel3.font = [UIFont systemFontOfSize:8]; cardLabel3.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabel3]; [NSLayoutConstraint activateConstraints:@[ [cardLabel1.topAnchor constraintEqualToAnchor:_cardContainer.topAnchor constant:25], [cardLabel1.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:10], [cardLabel2.topAnchor constraintEqualToAnchor:_cardContainer.topAnchor constant:50], [cardLabel2.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant: 8], [cardLabel3.topAnchor constraintEqualToAnchor:_cardContainer.topAnchor constant:50], [cardLabel3.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant: 45] ]]; UILabel *cardLabelHeight = [[UILabel alloc] init]; cardLabelHeight.text = @"高"; cardLabelHeight.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; cardLabelHeight.font = [UIFont systemFontOfSize:15]; cardLabelHeight.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabelHeight]; UILabel *cardLabelStart = [[UILabel alloc] init]; cardLabelStart.text = @"开"; cardLabelStart.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; cardLabelStart.font = [UIFont systemFontOfSize:15]; cardLabelStart.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabelStart]; UILabel *cardLabelVolume = [[UILabel alloc] init]; cardLabelVolume.text = @"量"; cardLabelVolume.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; cardLabelVolume.font = [UIFont systemFontOfSize:15]; cardLabelVolume.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabelVolume]; UILabel *cardLabelLow = [[UILabel alloc] init]; cardLabelLow.text = @"低"; cardLabelLow.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; cardLabelLow.font = [UIFont systemFontOfSize:15]; cardLabelLow.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabelLow]; UILabel *cardLabelChange = [[UILabel alloc] init]; cardLabelChange.text = @"换"; cardLabelChange.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; cardLabelChange.font = [UIFont systemFontOfSize:15]; cardLabelChange.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabelChange]; UILabel *cardLabelQuota = [[UILabel alloc] init]; cardLabelQuota.text = @"额"; cardLabelQuota.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; cardLabelQuota.font = [UIFont systemFontOfSize:15]; cardLabelQuota.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardLabelQuota]; UILabel *cardNumHeight = [[UILabel alloc] init]; cardNumHeight.text = @"1617.260"; cardNumHeight.textColor = [UIColor redColor]; cardNumHeight.font = [UIFont systemFontOfSize:12]; cardNumHeight.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardNumHeight]; UILabel *cardNumStart = [[UILabel alloc] init]; cardNumStart.text = @"1616.750"; cardNumStart.textColor = [UIColor redColor]; cardNumStart.font = [UIFont systemFontOfSize:12]; cardNumStart.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardNumStart]; UILabel *cardNumVolume = [[UILabel alloc] init]; cardNumVolume.text = @"1.511亿"; cardNumVolume.textColor = [UIColor whiteColor]; cardNumVolume.font = [UIFont systemFontOfSize:12]; cardNumVolume.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardNumVolume]; UILabel *cardNumLow = [[UILabel alloc] init]; cardNumLow.text = @"1608.850"; cardNumLow.textColor = [UIColor whiteColor]; cardNumLow.font = [UIFont systemFontOfSize:12]; cardNumLow.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardNumLow]; UILabel *cardNumChange = [[UILabel alloc] init]; cardNumChange.text = @"--"; cardNumChange.textColor = [UIColor whiteColor]; cardNumChange.font = [UIFont systemFontOfSize:12]; cardNumChange.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardNumChange]; UILabel *cardNumQuota = [[UILabel alloc] init]; cardNumQuota.text = @"--"; cardNumQuota.textColor = [UIColor whiteColor]; cardNumQuota.font = [UIFont systemFontOfSize:12]; cardNumQuota.translatesAutoresizingMaskIntoConstraints = NO; [_cardContainer addSubview:cardNumQuota]; [NSLayoutConstraint activateConstraints:@[ [cardLabelHeight.bottomAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-75], [cardLabelStart.bottomAnchor constraintEqualToAnchor:cardLabelHeight.bottomAnchor], [cardLabelVolume.bottomAnchor constraintEqualToAnchor:cardLabelHeight.bottomAnchor], [cardLabelLow.topAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-50], [cardLabelLow.leadingAnchor constraintEqualToAnchor:cardLabelHeight.leadingAnchor], [cardLabelChange.topAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-50], [cardLabelChange.leadingAnchor constraintEqualToAnchor:cardLabelStart.leadingAnchor], [cardLabelQuota.topAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-50], [cardLabelQuota.leadingAnchor constraintEqualToAnchor:cardLabelVolume.leadingAnchor], [cardNumHeight.bottomAnchor constraintEqualToAnchor:_cardContainer.topAnchor constant:45], [cardNumHeight.leadingAnchor constraintEqualToAnchor:cardLabelHeight.leadingAnchor], [cardNumStart.bottomAnchor constraintEqualToAnchor:cardNumHeight.bottomAnchor], [cardNumStart.leadingAnchor constraintEqualToAnchor:cardLabelStart.leadingAnchor], [cardNumVolume.bottomAnchor constraintEqualToAnchor:cardNumHeight.bottomAnchor], [cardNumVolume.leadingAnchor constraintEqualToAnchor:cardLabelVolume.leadingAnchor], [cardNumLow.bottomAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-10], [cardNumLow.leadingAnchor constraintEqualToAnchor:cardLabelLow.leadingAnchor], [cardNumChange.bottomAnchor constraintEqualToAnchor:cardNumLow.bottomAnchor], [cardNumChange.leadingAnchor constraintEqualToAnchor:cardLabelChange.leadingAnchor], [cardNumQuota.bottomAnchor constraintEqualToAnchor:cardNumLow.bottomAnchor], [cardNumQuota.leadingAnchor constraintEqualToAnchor:cardLabelVolume.leadingAnchor] ]]; [NSLayoutConstraint constraintWithItem:cardLabelHeight attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:_cardContainer attribute:NSLayoutAttributeTrailing multiplier:0.25 constant:0].active = YES; [NSLayoutConstraint constraintWithItem:cardLabelStart attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:_cardContainer attribute:NSLayoutAttributeTrailing multiplier:0.5 constant:0].active = YES; [NSLayoutConstraint constraintWithItem:cardLabelVolume attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:_cardContainer attribute:NSLayoutAttributeTrailing multiplier:0.75 constant:0].active = YES; // K线选择项容器 _kSelectContainer = [[UIView alloc] init]; _kSelectContainer.backgroundColor = [UIColor colorWithRed:26.0/255.0 green:26.0/255.0 blue:2.0/255.0 alpha:1.0]; _kSelectContainer.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:_kSelectContainer]; [self addKSelectOptions]; // K线图表容器 self.kLineContainer = [[UIView alloc] init]; self.kLineContainer.backgroundColor = [UIColor colorWithRed:26.0/255.0 green:26.0/255.0 blue:26.0/255.0 alpha:1.0]; self.kLineContainer.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:self.kLineContainer]; // K线图表滚动视图 self.kLineScrollView = [[UIScrollView alloc] init]; self.kLineScrollView.backgroundColor = [UIColor clearColor]; self.kLineScrollView.showsHorizontalScrollIndicator = NO; self.kLineScrollView.userInteractionEnabled = YES; self.kLineScrollView.translatesAutoresizingMaskIntoConstraints = NO; [self.kLineContainer addSubview:self.kLineScrollView]; CGFloat priceLabelAreaWidth = 50.0; // 滚动视图的约束 [NSLayoutConstraint activateConstraints:@[ [self.kLineScrollView.topAnchor constraintEqualToAnchor:self.kLineContainer.topAnchor], [self.kLineScrollView.bottomAnchor constraintEqualToAnchor:self.kLineContainer.bottomAnchor], [self.kLineScrollView.leadingAnchor constraintEqualToAnchor:self.kLineContainer.leadingAnchor constant:priceLabelAreaWidth], [self.kLineScrollView.trailingAnchor constraintEqualToAnchor:self.kLineContainer.trailingAnchor], [self.kLineScrollView.heightAnchor constraintEqualToAnchor:self.kLineContainer.heightAnchor] ]]; // 边框 UIView *borderView = [[UIView alloc] init]; borderView.backgroundColor = [UIColor clearColor]; borderView.layer.borderWidth = 1; borderView.layer.borderColor = [[UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1.0] CGColor]; borderView.translatesAutoresizingMaskIntoConstraints = NO; [self.kLineContainer addSubview:borderView]; [NSLayoutConstraint activateConstraints:@[ [borderView.leadingAnchor constraintEqualToAnchor:self.kLineContainer.leadingAnchor], [borderView.trailingAnchor constraintEqualToAnchor:self.kLineContainer.trailingAnchor], [borderView.topAnchor constraintEqualToAnchor:self.kLineContainer.topAnchor], [borderView.bottomAnchor constraintEqualToAnchor:self.kLineContainer.bottomAnchor] ]]; // 动态计算模型数据的价格区间 CGFloat maxPrice = 0; CGFloat minPrice = CGFLOAT_MAX; for (id item in self.kLineData) { if ([item isKindOfClass:[StockKLineModel class]]) { StockKLineModel *model = (StockKLineModel *)item; maxPrice = MAX(maxPrice, model.high); minPrice = MIN(minPrice, model.low); } else if ([item isKindOfClass:[NSDictionary class]]) { NSDictionary *dict = (NSDictionary *)item; maxPrice = MAX(maxPrice, [dict[@"high"] floatValue]); minPrice = MIN(minPrice, [dict[@"low"] floatValue]); } } maxPrice = maxPrice + (maxPrice - minPrice) * 0.1; minPrice = minPrice - (maxPrice - minPrice) * 0.1; // 价格刻度 NSMutableArray *priceLabelArr = [NSMutableArray array]; for (NSInteger i = 0; i < 5; i++) { CGFloat price = maxPrice - (maxPrice - minPrice) / 4 * i; UILabel *label = [[UILabel alloc] init]; label.text = [NSString stringWithFormat:@"%.1f", price]; label.textColor = [UIColor lightGrayColor]; label.font = [UIFont systemFontOfSize:10]; label.translatesAutoresizingMaskIntoConstraints = NO; [self.kLineContainer addSubview:label]; [NSLayoutConstraint activateConstraints:@[ [label.leadingAnchor constraintEqualToAnchor:self.kLineContainer.leadingAnchor constant:5], [label.centerYAnchor constraintEqualToAnchor:self.kLineContainer.centerYAnchor constant:-80 + 40 * i] ]]; [priceLabelArr addObject:label]; } self.priceLabels = priceLabelArr; self.dateLabels = @[];}
- (void)addKSelectOptions { NSArray *titles = @[@"日k", @"周k", @"月k", @"更多", @"设置"]; UIStackView *stackView = [[UIStackView alloc] init]; stackView.axis = UILayoutConstraintAxisHorizontal; stackView.distribution = UIStackViewDistributionFillEqually; stackView.alignment = UIStackViewAlignmentCenter; stackView.spacing = 5.0; stackView.translatesAutoresizingMaskIntoConstraints = NO; for (NSString *title in titles) { UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setTitle:title forState:UIControlStateNormal]; button.titleLabel.font = [UIFont systemFontOfSize:14]; [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; if ([title isEqualToString:@"日k"]) { [button setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal]; button.layer.borderColor = [[UIColor yellowColor] CGColor]; button.layer.borderWidth = 1.0; } else { [button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; button.layer.borderWidth = 0; } button.layer.cornerRadius = 3.0; button.clipsToBounds = YES; [stackView addArrangedSubview:button]; } [_kSelectContainer addSubview:stackView]; [NSLayoutConstraint activateConstraints:@[ [stackView.leadingAnchor constraintEqualToAnchor:_kSelectContainer.leadingAnchor constant:10], [stackView.trailingAnchor constraintEqualToAnchor:_kSelectContainer.trailingAnchor constant:-10], [stackView.topAnchor constraintEqualToAnchor:_kSelectContainer.topAnchor constant:5], [stackView.bottomAnchor constraintEqualToAnchor:_kSelectContainer.bottomAnchor constant:-5] ]];}
#pragma mark - Constraints- (void)setupConstraints{ [NSLayoutConstraint activateConstraints:@[ [_cardContainer.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor], [_cardContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [_cardContainer.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], [_cardContainer.heightAnchor constraintEqualToConstant:100], [_kSelectContainer.topAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:5], [_kSelectContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [_kSelectContainer.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], [_kSelectContainer.heightAnchor constraintEqualToConstant:40], [self.kLineContainer.topAnchor constraintEqualToAnchor:self.kSelectContainer.bottomAnchor constant:5], [self.kLineContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.kLineContainer.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], [self.kLineContainer.heightAnchor constraintEqualToConstant:200] ]];}
#pragma mark - KLine Drawing- (void)drawKLineChart { // 移除旧的 K 线 for (UIView *subview in self.kLineScrollView.subviews) { if (![subview isKindOfClass:[UILabel class]]) { [subview removeFromSuperview]; } } CGFloat chartHeight = self.kLineContainer.bounds.size.height; if (chartHeight == 0) { chartHeight = 200; } // K线宽度计算 CGFloat kLineUnitWidth = 5.0; CGFloat kLineRatio = 0.8; CGFloat kLineWidth = kLineUnitWidth * kLineRatio; CGFloat space = kLineUnitWidth * (1.0 - kLineRatio); CGFloat totalChartWidth = kLineUnitWidth * self.kLineData.count; // 设置contentSize self.kLineScrollView.contentSize = CGSizeMake(totalChartWidth, chartHeight); // 动态计算价格区间 CGFloat maxPrice = 0; CGFloat minPrice = CGFLOAT_MAX; for (id item in self.kLineData) { if ([item isKindOfClass:[StockKLineModel class]]) { StockKLineModel *model = (StockKLineModel *)item; maxPrice = MAX(maxPrice, model.high); minPrice = MIN(minPrice, model.low); } else if ([item isKindOfClass:[NSDictionary class]]) { NSDictionary *dict = (NSDictionary *)item; maxPrice = MAX(maxPrice, [dict[@"high"] floatValue]); minPrice = MIN(minPrice, [dict[@"low"] floatValue]); } } maxPrice = maxPrice + (maxPrice - minPrice) * 0.1; minPrice = minPrice - (maxPrice - minPrice) * 0.1; CGFloat priceRange = maxPrice - minPrice; // 绘制K线 for (NSInteger i = 0; i < self.kLineData.count; i++) { CGFloat open = 0, high = 0, low = 0, close = 0; if ([self.kLineData[i] isKindOfClass:[StockKLineModel class]]) { StockKLineModel *model = (StockKLineModel *)self.kLineData[i]; open = model.open; high = model.high; low = model.low; close = model.close; } else if ([self.kLineData[i] isKindOfClass:[NSDictionary class]]) { NSDictionary *dict = (NSDictionary *)self.kLineData[i]; open = [dict[@"open"] floatValue]; high = [dict[@"high"] floatValue]; low = [dict[@"low"] floatValue]; close = [dict[@"close"] floatValue]; } // 坐标转换 CGFloat yOpen = chartHeight * (maxPrice - open) / priceRange; CGFloat yHigh = chartHeight * (maxPrice - high) / priceRange; CGFloat yLow = chartHeight * (maxPrice - low) / priceRange; CGFloat yClose = chartHeight * (maxPrice - close) / priceRange; // 计算X坐标 CGFloat xPosition = space/2 + kLineUnitWidth * i; // 绘制K线实体 UIView *bodyView = [[UIView alloc] init]; bodyView.backgroundColor = (close >= open) ? [UIColor greenColor] : [UIColor redColor]; bodyView.frame = CGRectMake( xPosition, MIN(yOpen, yClose), kLineWidth, MAX(1.0, fabs(yClose - yOpen)) ); [self.kLineScrollView addSubview:bodyView]; // 绘制影线 UIView *shadowView = [[UIView alloc] init]; shadowView.backgroundColor = bodyView.backgroundColor; shadowView.frame = CGRectMake( bodyView.center.x - 0.5, yHigh, 1, yLow - yHigh ); [self.kLineScrollView addSubview:shadowView]; } // 日期刻度 for (UILabel *label in self.dateLabels) { [label removeFromSuperview]; } NSMutableArray *dateLabelArr = [NSMutableArray array]; NSInteger dateInterval = 10; for (NSInteger i = 0; i < self.kLineData.count; i += dateInterval) { NSString *dateStr = @""; if ([self.kLineData[i] isKindOfClass:[StockKLineModel class]]) { StockKLineModel *model = (StockKLineModel *)self.kLineData[i]; dateStr = model.date; } else if ([self.kLineData[i] isKindOfClass:[NSDictionary class]]) { NSDictionary *dict = (NSDictionary *)self.kLineData[i]; dateStr = dict[@"date"]; } UILabel *label = [[UILabel alloc] init]; label.text = dateStr; label.textColor = [UIColor lightGrayColor]; label.font = [UIFont systemFontOfSize:10]; label.translatesAutoresizingMaskIntoConstraints = YES; CGFloat xCenter = kLineUnitWidth * (i + 0.5); [label sizeToFit]; label.frame = CGRectMake( xCenter - label.bounds.size.width / 2, chartHeight - 15, label.bounds.size.width, label.bounds.size.height ); [self.kLineScrollView addSubview:label]; [dateLabelArr addObject:label]; } self.dateLabels = dateLabelArr; NSLog(@"ScrollView Bounds Width: %f", self.kLineScrollView.bounds.size.width); NSLog(@"Content Size Width: %f", self.kLineScrollView.contentSize.width); if (self.kLineScrollView.contentSize.width <= self.kLineScrollView.bounds.size.width) { NSLog(@"⚠️ 警告:ContentSize 不够大,无法滑动。"); }}
#pragma mark - Mock Data- (void) setupData{ self.kLineData = @[ @{@"date":@"2025/11/18", @"open":@1620.0, @"high":@1643.0, @"low":@1605.0, @"close":@1630.0, @"volume":@2.5}, @{@"date":@"2025/11/19", @"open":@1630.0, @"high":@1635.0, @"low":@1615.0, @"close":@1620.0, @"volume":@2.2}, @{@"date":@"2025/11/20", @"open":@1620.0, @"high":@1628.0, @"low":@1608.0, @"close":@1615.0, @"volume":@1.8}, @{@"date":@"2025/11/21", @"open":@1615.0, @"high":@1625.0, @"low":@1610.0, @"close":@1622.0, @"volume":@2.0}, @{@"date":@"2025/11/22", @"open":@1622.0, @"high":@1630.0, @"low":@1618.0, @"close":@1625.0, @"volume":@2.3}, @{@"date":@"2025/11/25", @"open":@1625.0, @"high":@1632.0, @"low":@1620.0, @"close":@1628.0, @"volume":@1.9}, @{@"date":@"2025/11/26", @"open":@1628.0, @"high":@1635.0, @"low":@1622.0, @"close":@1630.0, @"volume":@2.1}, @{@"date":@"2025/11/27", @"open":@1630.0, @"high":@1638.0, @"low":@1625.0, @"close":@1628.0, @"volume":@2.4}, @{@"date":@"2025/11/28", @"open":@1628.0, @"high":@1632.0, @"low":@1609.0, @"close":@1610.0, @"volume":@2.6}, @{@"date":@"2025/11/29", @"open":@1610.0, @"high":@1620.0, @"low":@1608.0, @"close":@1615.0, @"volume":@1.7} ];}
- (void)generateMockData { NSMutableArray *arr = [NSMutableArray array]; CGFloat lastClose = 100.0; NSLog(@"生成模拟数据中。。。"); // 生成200条数据(减少数量,避免contentSize过大) for (int i = 0; i < 200; i++) { StockKLineModel *model = [[StockKLineModel alloc] init]; NSDate *date = [NSDate dateWithTimeIntervalSinceNow:-(200 - i) * 24 * 3600]; NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; [fmt setDateFormat:@"MM-dd"]; model.date = [fmt stringFromDate:date]; // 价格生成逻辑 CGFloat volatility = lastClose * 0.02; CGFloat randomChange = ((arc4random() % 100) / 100.0 - 0.5) * 2 * volatility; model.open = lastClose + ((arc4random() % 100) / 100.0 - 0.5) * volatility * 0.5; model.close = model.open + randomChange; CGFloat maxOC = MAX(model.open, model.close); CGFloat minOC = MIN(model.open, model.close); model.high = maxOC + (arc4random() % 100) / 100.0 * 1.0; model.low = minOC - (arc4random() % 100) / 100.0 * 1.0; // 成交量生成逻辑 CGFloat baseVolume = 1000000.0; CGFloat randomVolFactor = (arc4random() % 200) / 100.0 + 0.5; if (fabs(model.close - model.open) / model.open > 0.03) { randomVolFactor *= 1.5; } model.volume = baseVolume * randomVolFactor; if (model.low < 0) model.low = 0.01; [arr addObject:model]; lastClose = model.close; } NSLog(@"生成模拟数据完毕,共%ld条", arr.count); self.kLineData = arr;}
@end
|