软件设计说明书例.doc
-软件详细设计说明书例完成日期:签收人:签收日期:修改情况记录:版本号修改批准人修改人安装日期签收人目录 1 引言11.1 编写目的11.2 围11.3 定义11.4 参考资料12 总体设计12.1 需求规定12.2 运行环境22.3 根本设计概念和处理流程22.4 构造22.5 功能需求与程序的关系22.6 人工处理过程22.7 尚未解决的问题33 接口设计33.1 用户接口33.2 外部接口33.3 部接口34 运行设计34.1 运行模块组合34.2 运行控制34.3 运行时间45 系统数据构造设计45.1 逻辑构造设计要点45.2 物理构造设计要点45.3 数据构造与程序的关系46 系统出错处理设计56.1 出错信息56.2 补救措施56.3 系统维护设计5. z.-1 引言1.1 编写目的随着证券交易电子化程度的不断提高,券商对于各种业务提出了新的要求,为了满足券商的开展需求,更好的为客户提供效劳,现结合原有各版本的证券交易软件的优点和特点,开发一套采用Client/Server构造的证券交易软件管理系统SQL版。本系统从底层予以优化,使整个系统的运行速度得到较大提高,通过重新优化数据库部构造,使系统的可扩大性得到极大提高。本说明书给出SQL版证券交易系统的设计说明,包括最终实现的软件必须满足的功能、性能、接口和用户界面、附属工具程序的功能以及设计约束等。目的在于:§ 为编码人员提供依据;§ 为修改、维护提供条件;§ 工程负责人将按方案书的要求布置和控制开发工作全过程;§ 工程质量保证组将按此方案书做阶段性和总结性的质量验证和确认。本说明书的预期读者包括:§ 工程开发人员,特别是编码人员;§ 软件维护人员;§ 技术管理人员;§ 执行软件质量保证方案的专门人员;§ 参与本工程开发进程各阶段验证、确认以及负责为最后工程验收、鉴定提供相应报告的有关人员。§ 合作各方有关部门的复杂人;工程负责人和全体参加人员。1.2 围说明:a 待开发的软件系统的名称:模拟股票交易系统b 列出本工程的任务提出者、开发者、用户以及将运行该项软件的单位。1.3 定义 列出本文件中用到的专门术语的定义和缩写词的原词组。 本报告用到的术语符合国家标准"软件工程术语GB/T11475-1995"。1.4 参考资料列出要用到的参考资料,如:a 本工程的经核准的方案任务书或合同、上级机关的批文;b 属于本工程的其他已发表的文件;c 本文件中各处引用的文件、资料,包括所要用到的软件开发标准。列出这些文件的标题、文件编号、发表日期和出版单位,说明能够得到这些文件资料的来源。2 总体设计2.1 需求规定说明对本系统的主要的输入输出工程、处理的功能性能要求,详细的说明可参见"需求分析说明书"。2.2 运行环境简要地说明对本系统的运行环境包括硬件环境和支持环境的规定,详细说明参见"需求分析说明书"。§ 数据库效劳器奔腾Pro存128MB以上硬盘9GB100M 网卡§ 应用效劳器奔腾Pro存64MB以上硬盘4GB100M 网卡§ 网络配置100M / 10M§ 工作站(柜台)P100以上存8MB以上硬盘1G以上100M/10M网卡 软件§ 操作系统WindowsNT 4.0以上§ 数据库管理系统SQL Server 2005§ 相关软件工具Windows NTWorkstation/Windows NT serverWindows 2000 Professional/ Server开发工具§ 平台:Windows95/98、Windows NT、Windows 2000§ 开发工具:visual stidio 2005 sp1,C#.Net 测试环境Windows31、Windows95/98、Windows NT、Windows 20002.3 根本设计概念和处理流程说明本系统的根本设计概念和处理流程,尽量使用图表的形式。营业部系统一共有四个对象,即客户、员工、市场和银行,市场的概念是交易所的细化,比方证券交易所的股和股就是两个市场,有了市场的概念我们就可以把交易所这个概念细化,并使同一个市场的共性更突出。银行则通过银证转账业务介入,并成为营业部系统不可或缺的组成局部。上述四个对象通过一些业务流程进展相互操作从而形成整个交易活动。因此整个系统模型可以表述为图2-1设计时需要将营业部系统所使用的各种信息分为描述四个对象的信息和描述业务流程的信息。由于四个对象相对而言是一种稳定型信息,而业务流程则较易变化,且营业部之间差异很大,因此应将四个对象尽量定型,而将各种业务流程尽可能做成组件,以便营业部可根据实际需求组装成适合自己的系统。根据以上思想,在设计对象模型时应充分考虑到可扩展性,尽量做到抽象化、参数化,从而使对象需求变化时不致影响系统构造。 图 2.12.4 构造用一览表及框图的形式说明本系统的系统元素各层模块、子程序、公用程序等的划分,扼要说明每个系统元素的标识符和功能,分层次地给出各元素之间的控制与被控制关系。本系统采用c/s模式的3层构造按照不同会话来划分的话可以分为3大系统模块局域网数据库柜台管理查询管理报表管理资金管理数据转换银证转账委托效劳日终管理系统管理系统监控接口处理子系统系统维护子系统图2-2 交易系统体系构造客户端登陆模块:最关键的交易系统模块构造图如下:股票信息发布经过修改我认为每次由客户端每5秒去查询一次效劳器更新信息不可取,因为这会加重效劳端和客户端的负担,特别是效劳器端的运算。修改后实现变更为:用户一开场登陆后获得一次效劳器的全部股票当前信息。而效劳器端每次发生交易后,给每一个在线用户发送当前交易需要更新的股票信息,这样就减轻了客户机和效劳端的信息2.5 功能需求与程序的关系该关系由需求分析报告编写者根据构造图说明本条用一如下的矩阵图说明各项功能需求的实现同各块程序的分配关系:获取并发送用户请求绘制分时图MD5加密解密发送用户交易请求承受并识别用户请求调用数据层查询撮合交易效劳器返回客户端信息用户登陆查看用户持仓实时指数交易委托取消交易2.6 人工处理过程说明在本软件系统的工作过程中不得不包含的人工处理过程如果有的话。没有完成股票管理的模块设计,所以股票必须从数据库后台添加如果有新股发行,还必须添加有关股票的交易队列2.7 尚未解决的问题说明在概要设计过程未解决而设计者认为在系统完成之前必须解决的各个问题。3接口设计3.1用户接口说明将向用户提供的命令和它们的语法构造,以及软件的答复信息。向用户提供简单易用的UI,以及帮助文档。客户端将提供以下功能首先弹出用户登陆框,供用户输入用户名和密码菜单项提供个股查询和分时图按钮菜单栏下是选项卡,提供股票实时信息和个股分时图栏 提供用户交易界面和交易按钮以及查看用户盈亏按键3.2 外部接口说明本系统同外界的所有接口的安排包括软件与硬件之间的接口、本系统与各支持软件之间的接口关系。采用基于正确公开标准的部件和技术以确保最大限度的协作能力以及与第三方系统与部件集成的简便性。这类标准包括但不限于以下几种:§ 网络协议与标准 (TCP/IP, HTTP, SSL, etc)§ 语言(SQL, C#.net, etc.)§ 数据库连接性(ADO。net)3.3 部接口说明本系统之的各个系统元素之间的接口的安排。逻辑层和数据访问层通过以经的stockDataModel接口,来限定访问stockData类型的数据客户端通过调用buyStockstockData和sellStockstockData来访问逻辑层,在这个函数中包含了访问逻辑层的接口dealTransaction(stockData) 通过AdoFactory访问不同的数据库客户端登陆协议D(二字节)+(客户名字长度)(4字节)+(客户名字)+(客户密码长度)(4字节)+(客户密码);客户买卖协议B(二字节)+(股票ID)(4字节)+(股票数量)(4字节)S(二字节)+(股票ID)(4字节)+(股票数量)(4字节)查询交易信息并返回给客户端C(二字节)具体有拆包解包的类using System;using System.Collections.Generic;using System.Te*t;namespace ProjectCenterTradingSyspublicclassProtocal privatebyte messagebuffer;privatebyte messagelength;publicbyte messagebag;/该函数是将字符串转换为字节数组publicbyte StringtoByte(string stringInfo) messagebuffer = System.Te*t.ASCIIEncoding.ASCII.GetBytes(stringInfo);return messagebuffer; /该函数将整型转换为个字节publicbyte InttoByte(int number) messagelength=BitConverter.GetBytes(number);return messagelength; /将浮点型转换为个字节publicbyte DoubletoByte(double price) byte pricebyte = BitConverter.GetBytes(price);return pricebyte; /合并一个字符串字节数组和他的长度作为一个包publicbyte binarray(byte messle, byte messinfo) messagebag=newbytemessle.Length+messinfo.Length;int inde*;for (inde* = 0; inde* < messle.Length; inde*+) messagebaginde* = messagelengthinde*;for (int inde*1 = 0; inde*1 < messinfo.Length; inde*1+) messagebaginde* + inde*1 = messagebufferinde*1;return messagebag; /解publicbyte BagHead(char head) byte headbyte = BitConverter.GetBytes(head);return headbyte; /读publicchar DeBagHead(byte buffer) char headinfo = BitConverter.ToChar(buffer, 0);return headinfo; /该函数为解包信息为字符串!publicstring deMessgeBag(byte Messagebag,int start,outint ne*t) ne*t = BitConverter.ToInt32(Messagebag, start);string message = System.Te*t.ASCIIEncoding.ASCII.GetString(Messagebag, start + 4, ne*t);return message; 4 运行设计4.1 运行模块组合说明对系统施加不同的外界运行控制时所引起的各种不同的运行模块组合,说明每种运行所历经的部模块和支持软件。4.2 运行控制说明每一种外界的运行控制的方式方法和操作步骤。4.3 运行时间说明每种运行模块组合将占用各种资源的时间。5 系统数据构造设计5.1 逻辑构造设计要点给出本系统所使用的每个数据构造的名称、标识符以及它们之中每个数据项、记录、文卷和系的标识、定义、长度及它们之间的层次的或表格的相互关系。客户端类图:windowForm:FormPrivate: userLogDialog userNamete*tBo* userPasswordte*tBo* userlogOKbotton userlogCanselbutton tabPage MenuBar stockRealtimeGraphitem stock Quote Dialog dataGridView userBuyStockID userBuyStockcount userBuyStockprice userBuyStockButton .sell userStocklistView userStockLookButton send Mesto Server(string Info) /该函数用来向主机发送请求 协议U:发送用户名,密码 B:buy股票id,count,price,user S: sell. Q:查询信息 Receive MesFromServer (接上MD5encryptstring/以下都要通过sendMestoServer/向主机发送信息logOK_press(event,handle);stockQuoteitem_press(e,h);buyStockButton_press(e,h);sellStockButton_press(e,h);stocklookButton_press(e,h);/该函数调用drawPicture画图stockRealtimeGraphitem_press(e,h)Class RealTime GraphPrivate stockID/动态数组存储股票价格 ArrayList stockPricePublic:/在windowform类中recievemess后更新当前价格,即在数组后添加一项最新价格updatePriceprice,sotckPrice) drawPicturestockID,stockPrice Class stockData 订单号 public int ListID; public int UsrID; public string StockInde*; public flout Price; public int Count; public bool Isbuy;该类即为向效劳端传送数据时的包效劳器端StockQueuePrivate stockData data stockData ne*tPublic DeleteQueueHead(); AddStockData();Class TradeService该类还要补充假设干个StockQueue类型的成员变量privatevoid StartListening() byte ipadre = newbyte 10, 82, 14, 47;IPAddress ip=newIPAddress(ipadre); m_Tcplisten = newTcpListener(ip,m_Port); m_Tcplisten.Start();while (true) try Socket s = m_Tcplisten.AcceptSocket(); clientSocket = s; m_serverThread = newThread(newThreadStart(serviceClient);/多线程deal各个连接用户的socket m_serverThread.Start(); catch (E*ception E) Console.WriteLine(E.ToString(); 如以上startlistening代码所示,监听创造一个连接客户端的套接字,再用多线程处理该连接,而效劳器端则继续监听新的套接字。这样主要的交易代码就可以放入ServiceClient这个函数中,当有新客户信息连入时,即可进展查询数据库,比照插入股票队列等工作Class ClientInfo/这个类记录了客户端的socket数据访问层类图Class ADOSQLserverPrivate dataSet /ds下可有4个dataTable userTable stockTable User_stockTable tempTablePublic:/验证用户信息 Bool CheckUserlogin(string usridstring password); Bool CheckUserMoney(string userID); Bool CheckUserStockCount(string userID);/交易成功修改用户和股票信息 Void updateUserTableClass stockData Void updateStockTableClass stockData Void updateUser_stockTable(Class stockData)/还未成功的交易放入临时表, Void updateTemTableClass stockData 注意,每次交易成功要删除临时表的信息 Void deleteInfoClass stockData) Class stockData 订单号 public int ListID; public int UsrID; public string StockInde*; public int Prince; public int Count; public bool Isbuy;该类即为向效劳端传送数据时的包关于交易算法的详细设计5.2 撮合算法在前文中,我们已经提到了,撮合算法是整个交易所乃至整个证券仿真系统的核心局部。此算法的成功与否,直接影响着仿真系统是否能实现以及实现效率的上下。按照真实的交易原则,撮合算法分为连续竞价和集中竞价两种方式。下面我们将分别对这两种方式进展实现。 连续竞价连续竞价是在绝大局部交易时间使用的撮合算法。连续竞价原则:1.) 价格优先原则:价格较高的买入申报优先于价格较低的买入申报,价格较低的卖出申报优先于价格较高的卖出申报。2.) 时间优先原则:同价位申报、依照申报时序决定优先顺序,即买卖方向、价格一样的,先申报者先于后申报者。先后顺序按证券交易所主机承受申报的时间确定。在正常情况下,买队列的第一笔报价最高的报价一定小于卖队列的第一笔最低报价的报价。此时不发生撮合。一旦买卖队列的价格发生了穿插,如图所示,发生穿插的那局部就会进展撮合。而事实上,由于每一笔新来的单子进入数列后都会触发一次比拟,所以每次触发撮合都是由新单子促成的。称为"来一笔撮合一次,也就是连续竞价。b 图连续竞价算法描述:首先设定QueueStruct构造为元素的买卖两个队列BuyQueue和SellQueue。为了尽可能的提高效率,减少资源占用,我们用静态数组构建这两个队列。其中BuyQueue是时间优先、买价降序排序,而SellQueue是时间优先、卖价升序排序,在连续竞价条件下,可以保证BuyQueue0的price小于SellQueue0的price。连续竞价算法如下:1.) 接收一个新单子newlist,判断newlist是买单还是卖单;如果是买单,则转2,如果是卖单,则转B; 2.) 取卖单队列头SellQueue0,if SellQueue0.price>newlist.price,利用插入排序将newlist插入到买队列BuyQueue中,转1; 3.) if SellQueue0.count>newlist.count,newlist完全撮合,SellQueue0.countSellQueue0.countnewlist.count,转2;4.) if SellQueue0.count<=newlist.count,SellQueue0撮合,并将SellQueue0从SellQueue队列中删除,newlist.count=newlist.count-SellQueue0.count,转2; 5.) 取买单队列头BuyQueue0,if BuyQueue0.price<newlist.price,利用插入排序将newlist插入到卖队列BuyQueue中,转1; 6.) if BuyQueue0.count>newlist.count,newlist完全撮合,BuyQueue0.countBuyQueue0.countnewlist.count,转1;7.) if BuyQueue0.count<=newlist.count,BuyQueue0撮合, 并将BuyQueue0从BuyQueue队列中删除, newlist.count=newlist.count-BuyQueue0.count,转5; 如下面流程图所示: 图 集合竞价集合竞价是指对所有有效委托进展集中处理,深、沪两市的集合竞价时间为交易日上午9:15至9:25。集合竞价原则:§ 但凡高于开盘价的买单一定成交;§ 但凡低于开盘价的卖单一定成交;§ 但凡高于开盘价的卖单一定不成交;§ 但凡低于开盘价的买单一定不成交;集合竞价分四步完成: 第一步:确定有效委托在有涨跌幅限制的情况下,有效委托是这样确定的: 根据该只证券上一交易日收盘价以及确定的涨跌幅度来计算当日的最高限价、 最低限价。有效价格围就是该只证券最高限价、最低限价之间的所有价位。 限价超出此围的委托为无效委托,系统作自动撤单处理。 第二步:系统根据竞价规则自动确定集合竞价的成交价,这个价格就是当日的开盘价, 所有高于开盘价的买盘和所有低开开盘价的卖盘均以此价格成交, 集合竞价的成交价确定原则是:以此价格成交,能够得到最大成交量。 第三步:集中撮合处理所有的买委托按照委托限价由高到低的顺序排列, 限价一样者按照进入系统的时间先后排列;所有卖委托按委托限价由低到高的顺序排列 , 限价一样者按照进入系统的时间先后排列。依序逐笔将排在前面的买委托与卖委托配对成交,即按照"价格优先,同等价格下时间优先"的成交顺序依次成交,直至成交条件不满足为止,即不存在限价高于等于成交价的叫买委托、或不存在限价低于等于成交价的叫卖委托。 所有成交都以同一成交价成交。 这同一成交价成交的买卖单一般量都是很大的,如图所示图所示第四步:行情提醒:1.) 如该只证券的成交量为零,则将成交价位提醒为开盘价、最近成交价、最高价、最低价,并提醒出成交量、成交金额。2.) 剩余有效委托中,实际的最高叫买价提醒为叫买提醒价,假设最高叫买价不存在,则叫买提醒价提醒为空;实际的最低叫卖价提醒为叫卖提醒价,假设最低叫卖价不存在,则叫卖提醒价提醒为空。 集合竞价中未能成交的委托,自动进入连续竞价。按照这样的原则和要求,我们设计了如下的集合竞价撮合算法。如图所示。 图集合竞价算法描述:和连续竞价一样,首先设定QueueStruct构造为元素的买卖两个队列BuyQueue和SellQueue。为了尽可能的提高效率,减少资源占用,我们用静态数组构建这两个队列。其中BuyQueue是时间优先、买价降序排序,而SellQueue是时间优先、卖价升序排序。在开市到开盘这段时间,买卖单已经分别进入了买卖队列排好了序。一旦宣布开盘,则触发集合撮合,如下:§ 判断两队列是否都不为空,如是,转2;如否,转21;§ 判断BuyQueue0.prince与SellQueue0.prince之差,如大于等于0,转3:如小于0,转21;§ 定义int i=j=0;M、N分别为买卖两队列非空元素的个数;BOOL k;QueueStruct Buy=BuyQueue0;Sell=SellQueue0;Buy1;Sell1;转4;§ 判断BuyQueuei.prince与SellQueuej.prince之差,如大于等于0,转5:如小于0,转14;§ 判断Buy.count与Sell.count之差,如大于0,转6;如小于等于0,转9;§ j+; k=true; Sell1.count=Sell.count;Sell.count=Sell.count+SellQueueiSellQueue.count;转7;§ 判断j是否小于N,如是,转4;如不是,转8;§ 开盘价为BuyQueuei.price;总成交量为Sell.count;统计成交数据及回报,并返回;§ i+;k=false; Buy1.count=Buy.count;Buy.count=Buy.count+BuyQueuei.count;转10;§ 判断i是否小于M,如是,转4;如不是,转11;§ 判断Buy.count与Sell.count之差,如小于0,转12;如等于0,转13;§ 开盘价为SellQueuej.price;总成交量为Buy.count;统计成交数据及回报,并返回;§ 开盘价为(SellQueuej.price+BuyQueuei-1.price)/2;总成交量为sell.count;统计成交数据及回报,并返回;§ 判断k值,如为true,转15;如为false,转18;§ 判断Buy1.count与Sell1.count之差,如大于0,转16;如小于0,转17;§ 开盘价为BuyQueuei.price;总成交量为Sell1.count;统计成交数据及回报,并返回;§ 开盘价为(SellQueuej-1.price+BuyQueuei-1.price)/2;总成交量为Sell1.count;统计成交数据及回报,并返回;§ 判断Buy1.count与Sell.count之差,如小于0,转19;如等于0,转20;§ 开盘价为SellQueuej.price;总成交量为Buy1.count;统计成交数据及回报,并返回;§ 开盘价为(SellQueuej.price+BuyQueuei-1.price)/2;总成交量为Buy1.count;统计成交数据及回报,并返回;§ 开盘价为昨日收盘价,成交量为0;保存所有数据至开盘进入连续竞价撮合;. z.- 买卖队列排序上面我们介绍了撮合算法的核心局部,但实际上在撮合前后都要对两个买卖队列进展一定的插入和排列处理,这在整个算法中也是很重要的局部。下面我们就来具体介绍一下。对所有的排列和插入我们考虑了效率问题之后,最后统一使用了二分插入排序法。在单子进入队列时,我们首先统计出当前队列中的非空数据个数,然后再通过新单子与当前队列中间值的价格比拟,确定新单子在队列的前半局部还是后半局部,然后再取该区域中间值与之比拟,直到确定新单子应在的位置。如以下代码所示:int low=0; int high=N-1; /N为队列中非空元素的个数while(low<=high)int m=(low+high)/2;if(newlist->price<SellQueuem.price)high=m-1;else low=m+1;for(int i=N-1; i>=high+1; -i)SellQueuei+1=SellQueuei; SellQueuehigh+1=*newlist;这是卖队列的排序,对于买队列的排序与之相似,只是价格排列是由高到底。在这里不再赘述。这种插入排序方法完全符合了撮合算法中价格优先、时间优先的要求,而且效率也是比拟高的。在集合竞价前和连续竞价后进展的插入排序都是这样进展的,而在集合竞价撮合之后,对两队列的重新排列,我们首先使用了memset函数将前面已全部成交的t个元素清空,然后将t到N(原总非空元素个数)前移t位。如以下代码所示:for (int p=0; *t < *N; p+,*t+)QueueStruct temp;temp=Queue*t;Queue*t=Queuep;Queuep=temp; 撮合算法的运行机制在交易所正常运行时,一天分为开市、开盘、休市、复开、收市等5个步骤。开市:每天上午9:15开市。这时候,股民可以通过券商向交易所递单。同一只股票的买卖单开场分别进入这只股票的买卖队列中,但并不进展撮合。该过程一直持续到9:25。开盘:每天上午9:30正式开盘。9:25-9:30为盘前处理,这段时间也就是集合竞价撮合算法运行的时间。9:25,买卖两队列开市不再接收新的单子。新的单子这时都放在缓冲区中,直到两队列运行完整个集合竞价算法后开市重新进单时,再依序将单子从缓存区取出读入买卖队列进展连续竞价的撮合。买卖队列于9:25开场集合竞价,运算完毕,得出开盘价等所有统计数据并发布行情以及发送完所有回报之后,重新接收单子进入该日正常交易中,使用连续竞价算法进展撮合。休市:每天上午11:00休市。此时,所有的券商不再承受买卖单子,也不再给交易所递单。交易所将此前已经收到的所有单子撮合之后处于休息阶段。并进展各种当日前市盘点。复开:每天下午13:30复开。此时,券商开市接收用户的递单,并将其送交交易所。交易所重新开市进入连续竞价撮合收市:每天下午15:00收市。此时交易所不再承受任何单子,准时进展最后一笔单子的撮合之后,关闭撮合线程。将最后得到的收盘价等数据统计发送完之后,当天的所有工作全部完毕。如图所示。 图. z.-5.3 数据库设计数据库效劳器为SQL SERVER 2005 E*PRESS 股票信息表记录了股票的当前信息用户信息表交易订单表其中userid和stockid是外键关系图如下5.4 物理构造设计要点给出本系统所使用的每个数据构造中的每个数据项的存储要求,访问方法、存取单位、存取的物理关系索引、设备、存储区域、设计考虑和条件。5.5 数据构造与程序的关系说明各个数据构造与访问这些数据构造的各个程序之间的对应关系,可采用如下的矩阵图的形式:程序1程序2程