if ([stockDeal.dealWayisEqualToString:@\买入\]) {
if ([stockCurrentTemp floatValue] <= stockDeal.delegateDealPrice) { //成交
stockDeal.isCancel = NO;
BOOL success =[_databaseupdataStatusFromWeiTuoTableByStockDeal:stockDeal]; if (success) {
NSDateFormatter *formatter = [[NSDateFormatteralloc] init];
[formatter setDateFormat:@\];
stockDeal.dealTime = [formatter stringFromDate:[NSDatedate]]; stockDeal.yueAmount = stockDeal.delegateDealAmount; stockDeal.keyongAmount = stockDeal.yueAmount; stockDeal.dongjieAmount = 0;
stockDeal.cost = stockDeal.delegateDealPrice; nUseMoney -= stockDeal.cost * stockDeal.keyongAmount;
[_databaseupdataCanUseMoneyFromTradingAccountByUser:_user]; //添加到持仓表中
[_databaseinsertStockIntoChiCangTable:stockDeal]; //1.获取用户的股票余额
NSMutableArray *arr = [_databaseselectStockFromChiCangTableByAccountName:_user.userName]; float temp = 0;
for (int i = 0; i < arr.count; i ++) { ZMPStockDeal *s = arr[i];
temp += s.yueAmount * s.cost; } _user.stockMoney = temp; //2.得到交易发生时的资金总额
_user.totalMoney = _user.stockMoney + _user.canUseMoney; //3.将数据插入到交易记录表中
ZMPTradingRecord *tradingRecord = [[ZMPTradingRecordalloc] init]; tradingRecord.tradingTime = stockDeal.dealTime;
tradingRecord.tradingSummary = [NSStringstringWithFormat:@\买入%@\,stockDeal.stockName];
tradingRecord.tradingMoney = stockDeal.delegateDealMoney; tradingRecord.totalMoney = _user.totalMoney; tradingRecord.tradingAccount = _user.userName;
[_databaseinsertIntoTradingRecordTable:tradingRecord]; //推送通知
NSDate *fireDate = [[NSDatenew] dateByAddingTimeInterval:5];
NSMutableDictionary *dicUserInfo = [[NSMutableDictionaryalloc] init]; [dicUserInfo setValue:@\forKey:@\]; NSDictionary *userInfo = dicUserInfo;
NSString *message = [NSStringstringWithFormat:@\成交!买入%@(%@),成交金额%.2f元\,stockDeal.stockName,stockDeal.stockCode,stockDeal.delegateDealMoney];
[XGPushlocalNotification:fireDate alertBody:message badge:1alertAction:@\确定%userInfo:userInfo]; } } }
36
6.7.2 卖出
卖出交易过程大致与买入过程相同。在进入卖出界面,用户输入持仓股票中的股票代码后,系统
从数据库中获取该股交易的详细数据后显示,包括可买数量。同时,对该股当前的详细信息发送Get请求。在用户正常情况下进行卖出后,系统同样将该单挂入委托单中,只不过此时该单的状态为卖出。在后台新开辟线程进行实时刷新该股数据。在该应用中采用Thread方式进行多线程编程,与NSOperation和GCD相比,线程的管理、线程锁的设置与释放等都需要手动实现。多线程的实现关键代码如下:
#pragma mark - 开辟新线程 //创建新的线程
NSThread *thread = [[NSThreadalloc] initWithTarget:selfselector:@selector(newThread) object:nil]; [thread start]; - (void)newThread{ @autoreleasepool{
//在当前Run Loop中添加timer,模式是默认的NSDefaultRunLoopMode
[NSTimerscheduledTimerWithTimeInterval:3.0target:selfselector:@selector(usernameIsExist:) userInfo:nilrepeats:YES];
//开始执行新线程的Run Loop,如果不启动run loop,timer的事件是不会响应的 [[NSRunLoopcurrentRunLoop] run]; } }
6.7.3 撤单
撤单也是在真实股票交易过程中一个比不可少的操作,在该模拟软件中同样包含撤单操作。进入
撤单界面后,页面中出现的数据代表处于委托单中的数据。在“是否可撤”栏中,显示“是”表明可撤,显示“否”表明不可撤。出现“否”的原因是,该股已经达到交易条件,系统在后台便以成交,同时修改其状态为不可撤状态。关键代码如下:
#pragma mark - 撤单操作
- (void)cancelTrading:(NSNotification *)notification{
ZMPStockDeal *stockDeal = [_canCancelTradingArrayobjectAtIndex:[notification.objectintegerValue]]; stockDeal.isCancel = NO;
BOOL success = [_databaseupdataStatusFromWeiTuoTableByStockDeal:stockDeal]; NSString *message = nil;
if (success) {message = @\撤单成功\; }else{message = @\撤单失败\;} [selfdisplayAlertView:message]; }
37
6.8资产组合风险计算
iStock应用内嵌组合投资算法,用户通过输入组合投资的股票,计算相关参数指标来对该组合进
行评估,利用那个马科维茨模型寻找该组合中风险最小的组合。 6.8.1 相关参数
1、单只股票的预期收益和风险特征
根据不同的经济状况,对股票的未来收益都将出现不同的估计,由于市场经济的不确定性,将取
出股票在最近两年至三年的时间内的平均月收益率作为预期收益率:
1nE(x)=?xi (6-1)
ni=1其中xi为月收益率。将预期收益的方差作为衡量该股风险的标准,其计算公式为:
1n???(xi?x)2 (6-2)
ni?12方差的平方根为标准差,方差越大,意味着随机变量与数学期望的偏离越大,那么风险也就越大。 2、单只股票对系统风险的敏感系数
衡量了某种证券收益率的变化受市场收益率的变化的影响程度,市场的值用1个单位来表示。
[4]
当b>1时,表明该股票的波动幅度大于整个市场的波动浮动,即当市场的收益率变动一个单位时,该股票的收益率会向相同的方向变动大于一个单位,把具有这种性质的股票称为进攻型股票。相反
b<1,表明为防守型股票。
b=cov(ra,rm)s2m (6-3)
2其中,cov(ra,rm)表示该股收益率与市场收益率的协方差,sm表示市场方差。
3、资产组合的方差及预期收益率
资产组合中所有资产预期收益率的简单加权平均值构成资产组合的预期收益率,
E(rp)=?xiE(ri) (6-4)
i=1n其中xi为各股票在资产组合中所占的权重比。资产组合的简单方差计算公式为:
222?p??p?m???2 (6-5)
p其中,
????xi2??2 (6-6)
2pni?1i2 (6-7) se2=si2-bi2smi 38
式(6-7)中,计算得出的se为股票的残差。
i24、资产组合的实际马柯维茨方差
P=?xs+?2p2i2ii=1nni=1j=1,j1i?xxinjcov(xi,xj) (6-8)
其中cov(xi,xj)表示股票i和股票j之间收益率的协方差,也就是在计算马科维茨方差之前,需要计算出资产组合中股票收益的协方差矩阵。
马柯维茨的组合投资模型中,数学期望代表预期收益,方差或标准差代表风险,协方差代表资产
之间相互关系,进而资产组合的预期收益率是资产组合中所有资产预期收益的简单加权平均值,而资产组合的方差则为资产各自方差与他们之间协方差的加权平均。 6.8.2 实现算法
确定资产组合中马科维茨方差的最小值首先需要计算出构成该组合资产的每一单个资产的收益
[5]
率、风险及各股票资产之间的相互关系(协方差),然后计算该组合资产的预期收益率和风险。在该基础上,依据用户的投资偏好而所选择的股票构成的资产组合,计算出最小马柯维茨方差,以及此时的各资产的权重比。在iStock应用中,如图6-10和图6-11,分别是资产组合的用户输入界面和资产组合后结果处理界面。
图6-10 资产组合输入界面 图6-11 资产组合处理结果界面
寻找最小马柯维茨方差的权重数的具体算法如下:
1、通过各股票的收盘数据,选取2013-2014年中的24组数据来计算月平均收益率; 2、将月平均收益率假设为期望收益率,进一步计算各股票的方差和标准差;
39
3、按照同样的方法计算市场预期收益率和市场方差;
4、通过计算市场收益率和各股票收益率的协方差后,与市场方差的比值,得出个股票的贝塔系数值;
5、个股票的方差与贝塔系数的平方乘以市场方差的差值而得出每只股票的残差;
6、计算个股票之间的预期收益率的协方差矩阵,结合个股票的权重数,从而计算得出资产组合的实际马科维茨方差值;
7、最后通过不断改变权重比,利用选择排序的思想遍历找到出最小的马科维茨方差值以及相应的权重比。
在应用测试中,选择三只股票进行资产组合,江淮汽车(600418)、中国石化(600028)、华泰
证券(601688)。在选取股票进行资产组合时,选择收益呈负相关的股票进行组合,收益呈负相关的股票组合能够有效分散风险。选择以上样本股票在2013、2014两年的数据进行分析计算。
表6-9 各股和大盘的数据统计表
月平均收股票名称 江淮汽车 中国石化 华泰证券 上证指数
股票代码 600418 600028 601688 000001 益率 0.033088 0.001209 0.045757 0.013541 方差 0.021089 0.014443 0.025651 0.003965 标准差 0.145221 0.120180 0.160158 0.062967 贝塔 0.992217 1.288840 2.137524 1 最终通过(6-8)式计算得出资产组合的马科维茨方差,然后进行遍历,计算出马柯维茨方差最小
时所得到的权重数。计算结果如下表:
表6-10 资产组合计算结果
计算项目 最小马科维茨方差时的权重 组合资产的贝塔值 组合资产的预期收益率 组合资产的最小马科维茨方差
计算值 0.33、0.52、0.15 1.318257 1.8411% 0.010252 为了验证该算法的实际正确性,选取2015年1-3月之间个股票的数据来进行对比计算,如下表:
表6-11 2015年1-3月个股票实际收益率
股票名称 股票代码 江淮汽车 中国石化 华泰证券 600418 600028 601688 一月 0.040563 -0.070878 -0.138128 二月 三月 平均收益率 0.085393 0.000103 0.055767 0.164526 0.051090 0.056856 0.014331 0.128684 0.176746 经计算,按照最小马柯维茨方差得到的权重比来计算出的资产组合2015年1-3月之间的实际收益
率为0.012201,较组合资产的预期收益率低七个百分点。按照最小马柯维茨方差而得到的权重比进行
40