时间:2015-06-11 来源:

程序员的量化交易之路(32)--Cointrade之Portfolio组合(19) 【编程语言】

转载须注明出处:http://blog.csdn.net/minimicall?viewmode=contents,http://cloudtrade.top/

Portfolio:组合,网页外包接活代表的是多个证券组合在一起为了完成某一策略 .组合中每个证券都有自己的仓位(Position).我们的策略就是要控制组合的Position进而涉及到买卖,网页切图价格 Remainder.ROUND_EVEN)).plus(pos.getOpenVolume().times( // pos.getStopPrice(), // Remainder.ROUND_EVEN); // // longVolume = longVolume.plus(pos.getOpenVolume()); // } else if (pos.isShort()) { // shortAvgPrice = ((shortAvgPrice.times(shortVolume, // Remainder.ROUND_EVEN))).dividedBy(shortVolume.plus(pos.getOpenVolume()), Remainder.ROUND_EVEN)).plus(pos.getOpenVolume().times( // pos.getStopPrice(), // Remainder.ROUND_EVEN); // // shortVolume = shortVolume.plus(pos.getOpenVolume()); // } // } } // need to change this to just return one position that is the total, listing); // Fill pos = new Fill(); // pos.setPortfolio(this); // pos.setMarket(market); // // pos.setPriceCount(longAvgPrice.toBasis(market.getPriceBasis(), Remainder.ROUND_EVEN).getCount()); // Position position = new Position(pos); // allPositions.add(position); // } } } } } return allPositions; } public @Transient Position getPosition(Asset asset, portoflio should not be null // Position position = new Position(null, market, DecimalAmount.ZERO, Remainder.ROUND_EVEN)).plus(pos.getOpenVolume().times(pos.getPrice(), Remainder.ROUND_EVEN); // if (pos.getStopPrice() != null) // longAvgStopPrice = ((longAvgStopPrice.times(longVolume, // Remainder.ROUND_EVEN))).dividedBy(longVolume.plus(pos.getOpenVolume()), Remainder.ROUND_EVEN)).plus(pos.getOpenVolume().times(pos.getPrice(), Remainder.ROUND_EVEN); // if (pos.getStopPrice() != null) // shortAvgStopPrice = ((shortAvgStopPrice.times(longVolume, // Remainder.ROUND_EVEN))).dividedBy(longVolume.plus(pos.getOpenVolume()), not one long and one short. // // if (!shortVolume.isZero() || !longVolume.isZero()) { // Fill pos = new Fill(); // pos.setPortfolio(this); // pos.setMarket(market); // // pos.setPriceCount(longAvgPrice.toBasis(market.getPriceBasis(), Remainder.ROUND_EVEN).getCount()); // position = new Position(pos); // //allPositions.add(position); // } return new Position(fills); // return position; } public @Transient Collection<Position> getPositions(Asset asset, Amount> getRealisedPnLs() { ConcurrentHashMap<Asset, Amount>(); synchronized (lock) { for (Iterator<Asset> it = realisedProfits.keySet().iterator(); it.hasNext();) { Asset asset = it.next(); for (Iterator<Exchange> ite = realisedProfits.get(asset).keySet().iterator(); ite.hasNext();) { Exchange exchange = ite.next(); for (Iterator<Listing> itl = realisedProfits.get(asset).get(exchange).keySet().iterator(); itl.hasNext();) { Listing listing = itl.next(); Amount realisedPnL = realisedProfits.get(asset).get(exchange).get(listing); if (allPnLs.get(asset) == null) { allPnLs.put(asset, allPnLs.get(asset).plus(realisedPnL)); } } } } } return allPnLs; } public @Transient Amount getRealisedPnL(Asset asset) { Amount realisedPnL = DecimalAmount.ZERO; for (Iterator<Exchange> ite = realisedProfits.get(asset).keySet().iterator(); ite.hasNext();) { Exchange exchange = ite.next(); for (Iterator<Listing> itl = realisedProfits.get(asset).get(exchange).keySet().iterator(); itl.hasNext();) { Listing listing = itl.next(); realisedPnL = realisedPnL.plus(realisedProfits.get(asset).get(exchange).get(listing)); } } return realisedPnL; } public @Transient ConcurrentHashMap<Asset, ConcurrentHashMap<Listing, Exchange exchange) { long longVolumeCount = 0; synchronized (lock) { if (positions.get(asset) != null && positions.get(asset).get(exchange) != null) { for (Iterator<Listing> itl = positions.get(asset).get(exchange).keySet().iterator(); itl.hasNext();) { Listing listing = itl.next(); for (Position itpos : positions.get(asset).get(exchange).get(listing).get(TransactionType.BUY)) { for (Iterator<Fill> itp = itpos.getFills().iterator(); itp.hasNext();) { Fill pos = itp.next(); longVolumeCount += pos.getOpenVolumeCount(); } } } } } return new DiscreteAmount(longVolumeCount, Exchange exchange) { long netVolumeCount = 0; Fill pos = null; synchronized (lock) { if (positions.get(asset) != null && positions.get(asset).get(exchange) != null) { for (Iterator<Listing> itl = positions.get(asset).get(exchange).keySet().iterator(); itl.hasNext();) { Listing listing = itl.next(); for (Iterator<TransactionType> itt = positions.get(asset).get(exchange).get(listing).keySet().iterator(); itt.hasNext();) { TransactionType transactionType = itt.next(); for (Position itpos : positions.get(asset).get(exchange).get(listing).get(transactionType)) { for (Iterator<Fill> itp = itpos.getFills().iterator(); itp.hasNext();) { pos = itp.next(); netVolumeCount += pos.getOpenVolumeCount(); } } } } } } return new DiscreteAmount(netVolumeCount, Exchange exchange) { long shortVolumeCount = 0; synchronized (lock) { if (positions.get(asset) != null && positions.get(asset).get(exchange) != null) { for (Iterator<Listing> itl = positions.get(asset).get(exchange).keySet().iterator(); itl.hasNext();) { Listing listing = itl.next(); for (Position itpos : positions.get(asset).get(exchange).get(listing).get(TransactionType.SELL)) { for (Iterator<Fill> itp = itpos.getFills().iterator(); itp.hasNext();) { Fill pos = itp.next(); shortVolumeCount += pos.getOpenVolumeCount(); } } } } } return new DiscreteAmount(shortVolumeCount, List<Wallet>> getBalances() { return balances; } /** * Returns all Positions in the Portfolio which are not reserved as payment for an open Order */ @Transient public Collection<Position> getTradeableBalance(Exchange exchange) { throw new NotImplementedException(); } @Transient public Collection<Transaction> getTransactions() { ConcurrentLinkedQueue<Transaction> allTransactions = new ConcurrentLinkedQueue<Transaction>(); for (Iterator<Asset> it = transactions.keySet().iterator(); it.hasNext();) { Asset asset = it.next(); for (Iterator<Exchange> ite = transactions.get(asset).keySet().iterator(); ite.hasNext();) { Exchange exchange = ite.next(); for (Iterator<TransactionType> itt = transactions.get(asset).get(exchange).keySet().iterator(); itt.hasNext();) { TransactionType type = itt.next(); for (Iterator<Transaction> ittr = transactions.get(asset).get(exchange).get(type).iterator(); ittr.hasNext();) { Transaction tran = ittr.next(); allTransactions.add(tran); } } } } return allTransactions; } @Transient public void removeTransaction(Transaction reservation) { if (transactions.get(reservation.getCurrency()) == null) return; if (transactions.get(reservation.getCurrency()).get(reservation.getExchange()) == null) return; if (transactions.get(reservation.getCurrency()).get(reservation.getExchange()).get(reservation.getType()) == null) return; synchronized (lock) { transactions.get(reservation.getCurrency()).get(reservation.getExchange()).get(reservation.getType()).remove(reservation); // Iterator<Transaction> it = transactions.get(reservation.getCurrency()).get(reservation.getExchange()).get(reservation.getType()).iterator(); // while (it.hasNext()) { // Transaction transaction = it.next(); // if (transaction != null && reservation != null && transaction.equals(reservation)) // it.remove(); // } } } /** * This is the main way for a Strategy to determine what assets it has available for trading */ @Transient public Collection<Position> getReservedBalances(Exchange exchange) { throw new NotImplementedException(); } /** * This is the main way for a Strategy to determine how much of a given asset it has available for trading * @param f * @return */ @Transient public Collection<Position> getTradeableBalanceOf(Exchange exchange, then breaks it into the amount p requires * plus an unreserved amount. The resevered Position is then associated with the given order, call release(order) * * @param order the order which will be placed * @param p the cost of the order. could be a different fungible than the order's quote fungible * @throws IllegalArgumentException */ @Transient public void reserve(SpecificOrder order, ConcurrentHashMap<TransactionType, ConcurrentHashMap<TransactionType, ConcurrentLinkedQueue<Transaction>> transactionGroup = new ConcurrentHashMap<TransactionType, transactionList); assetTransactions.put(transaction.getExchange(), assetTransactions); return true; } else { //asset is present, ConcurrentLinkedQueue<Transaction>> exchangeTransactions = assetTransactions.get(transaction.getExchange()); if (exchangeTransactions == null) { ConcurrentLinkedQueue<Transaction> transactionList = new ConcurrentLinkedQueue<Transaction>(); transactionList.add(transaction); ConcurrentHashMap<TransactionType, ConcurrentLinkedQueue<Transaction>>(); transactionGroup.put(transaction.getType(), transactionGroup); return true; } else { ConcurrentLinkedQueue<Transaction> transactionList = exchangeTransactions.get(transaction.getType()); if (transactionList == null) { transactionList = new ConcurrentLinkedQueue<Transaction>(); transactionList.add(transaction); exchangeTransactions.put(transaction.getType(), transactionList); return true; } } } } /** * finds other Positions in this portfolio which have the same Exchange and Asset and merges this position's * amount into the found position's amount, PositionType lastType, market, mergedType)); } @Transient public void insert(Position position) { TransactionType transactionType = (position.isLong()) ? TransactionType.BUY : TransactionType.SELL; ConcurrentLinkedQueue<Position> detailPosition = new ConcurrentLinkedQueue<Position>(); //Position detPosition = new Position(fill); //detPosition.Persit(); detailPosition.add(position); ConcurrentHashMap<TransactionType, ConcurrentLinkedQueue<Position>>(); positionType.put(transactionType, ConcurrentHashMap<TransactionType, ConcurrentHashMap<TransactionType, positionType); ConcurrentHashMap<Exchange, ConcurrentHashMap<TransactionType, ConcurrentHashMap<Listing, ConcurrentLinkedQueue<Position>>>>(); assetPositions.put(position.getMarket().getExchange(), assetPositions); } @Transient private boolean merge(Fill fill) { //synchronized (lock) { // We need to have a queue of buys and a queue of sells ( two array lists), // when we get a new trade coem in we add it to the buy or sell queue // 1) caluate price difference // 2) times price diff by min(trade quantity or the position) and add to relasied PnL // 3) update the quaitity of the postion and remove from queue if zero // 4) move onto next postion until the qty =0 // https://github.com/webpat/jquant-core/blob/173d5ca79b318385a3754c8e1357de79ece47be4/src/main/java/org/jquant/portfolio/Portfolio.java TransactionType transactionType = (fill.isLong()) ? TransactionType.BUY : TransactionType.SELL; TransactionType openingTransactionType = (transactionType.equals(TransactionType.BUY)) ? TransactionType.SELL : TransactionType.BUY; ConcurrentHashMap<Exchange, ConcurrentHashMap<TransactionType, ConcurrentHashMap<TransactionType, ConcurrentHashMap<TransactionType, ArrayList<Position>> listingPosition = new ConcurrentHashMap<Listing, Amount> marketRealisedProfits; ConcurrentHashMap<Exchange, Amount>> assetRealisedProfits = realisedProfits.get(fill.getMarket().getTradedCurrency()); if (assetRealisedProfits != null) { marketRealisedProfits = assetRealisedProfits.get(fill.getMarket().getListing()); } if (assetPositions == null) { ConcurrentLinkedQueue<Position> detailPosition = new ConcurrentLinkedQueue<Position>(); Position detPosition = new Position(fill); detPosition.Persit(); detailPosition.add(detPosition); ConcurrentHashMap<TransactionType, ConcurrentLinkedQueue<Position>>(); positionType.put(transactionType, positionType); assetPositions = new ConcurrentHashMap<Exchange, ConcurrentHashMap<TransactionType, listingPosition); positions.put(fill.getMarket().getBase(), ConcurrentHashMap<Listing, Amount>(); marketRealisedProfits.put(fill.getMarket().getListing(), marketRealisedProfits); realisedProfits.put(fill.getMarket().getTradedCurrency(), fill.getMarket()), fill.getMarket()); return true; } else { //asset is present, ConcurrentHashMap<TransactionType, ConcurrentLinkedQueue<Position>> positionType = new ConcurrentHashMap<TransactionType, detailPosition); listingPosition.put(fill.getMarket().getListing(), listingPosition); Amount profits = DecimalAmount.ZERO; if (realisedProfits.get(fill.getMarket().getTradedCurrency()).get(fill.getMarket().getExchange()).get(fill.getMarket().getListing()) == null) { marketRealisedProfits = new ConcurrentHashMap<Listing, profits); realisedProfits.get(fill.getMarket().getTradedCurrency()).put(fill.getMarket().getExchange(), fill.getMarket()), fill.getMarket()); return true; } else { //ConcurrentHashMap<TransactionType, so check the market // need yo vhnage this to have tne cocnurrent hashmap on here //ConcurrentHashMap<TransactionType, listingsDetailPosition); listingPositions = exchangePositions.get(fill.getMarket().getListing()).get(transactionType); Amount listingProfits = DecimalAmount.ZERO; if (realisedProfits.get(fill.getMarket().getTradedCurrency()) == null || realisedProfits.get(fill.getMarket().getTradedCurrency()).get(fill.getMarket().getExchange()) == null || realisedProfits.get(fill.getMarket().getTradedCurrency()).get(fill.getMarket().getExchange()).get(fill.getMarket().getListing()) == null) { marketRealisedProfits = new ConcurrentHashMap<Listing, listingProfits); realisedProfits.get(fill.getMarket().getTradedCurrency()).put(fill.getMarket().getExchange(), closed out 421 lots, total of 444 lots, so if I am long, net =-5 -> neet ot take 5 max(), net =-10 net to take 10 (max), net =-20 net to take (Min)10 // short postion =-10, Max) postions = -10, postion =-10,-5 () my volume is 5 // 5,5 my volume is -5 // -5,-10 my voulme is 10 //Math.abs(a) closingVolumeCount = (openingTransactionType.equals(TransactionType.SELL)) ? (Math.min( Math.abs(openPosition.getOpenVolumeCount()), Math.abs(p.getOpenVolumeCount()))); // need to think hwere as one if negative and one is postive, p.getMarket().getListing().getVolumeBasis()); realisedPnL = realisedPnL.plus(((entryPrice.minus(exitPrice)).times(volDiscrete, Remainder.ROUND_EVEN)); // need to confonvert to deiscreete amount //LongRealisedPnL = ((exitPrice.minus(entryPrice)).times(volDiscrete, Remainder.ROUND_EVEN); // ShortRealisedPnL = (position.getShortAvgPrice().minus(p.getLongAvgPrice())).times(position.getShortVolume().negate(), // Remainder.ROUND_EVEN); } } Amount RealisedPnL = realisedPnL.toBasis(p.getMarket().getTradedCurrency().getBasis(), TotalRealisedPnL); Transaction trans = new Transaction(this, p.getMarket().getTradedCurrency(), RealisedPnL, p.getMarket().getTradedCurrency().getBasis())); context.route(trans); PersistUtil.insert(trans); // manager.getPortfolioService().CreateTransaction(position.getExchange(), // TransactionType.REALISED_PROFIT_LOSS, DecimalAmount.ZERO); } // if (!totalQuantity.isZero()) { // //generate PnL // //Update postion Quanitty // //Recculate Avaerge Price // Amount avgPrice = ((p.getAvgPrice().times(p.getVolume(), Remainder.ROUND_EVEN))).dividedBy(p.getVolume().plus(position.getLongVolume()), Remainder.ROUND_EVEN)).plus(position.getLongVolume().times( // position.getLongAvgPrice(), Remainder.ROUND_EVEN); // p.setLongAvgPrice(longExitPrice); // } // } // if (!position.getShortVolume().isZero()) { // // i.e short position // //this does not work when we net out the postion as we have a divid by zero error // Amount vol = (p.getShortAvgPrice().isZero()) ? position.getShortVolume() : p.getShortVolume().plus(position.getShortVolume()); // if (vol.isZero()) { // shortExitPrice = ((p.getShortAvgPrice().times(p.getShortVolume(), Remainder.ROUND_EVEN))).dividedBy(vol, Remainder.ROUND_EVEN).asDouble(); //avgPrice = new DiscreteAmount(avgPriceCount, Remainder.ROUND_EVEN) // .asDouble(), might want to have a comparator to merge using LIFO, fill.getMarket()) == null) { Position detPosition = new Position(fill); detPosition.Persit(); publishPositionUpdate(detPosition, fill.getMarket()); } else { PositionType lastType = (openingTransactionType == TransactionType.BUY) ? PositionType.LONG : PositionType.SHORT; publishPositionUpdate(getPosition(fill.getMarket().getBase(), lastType, PortfolioManager manager) { this.name = name; this.manager = manager; } private String name; public String getName() { return name; } @OneToMany public Collection<Stake> getStakes() { return stakes; } @ManyToOne public Asset getBaseAsset() { return baseAsset; } @Transient public PortfolioManager getManager() { return manager; } /** * Adds the given position to this Portfolio. Must be authorized. * @param position * @param authorization */ @Transient protected void modifyPosition(Fill fill, ConcurrentHashMap<Exchange, ConcurrentHashMap<TransactionType, ConcurrentHashMap<Exchange, Amount>>>(); this.balances = new ConcurrentLinkedQueue<>(); this.transactions = new ConcurrentHashMap<Asset, ConcurrentHashMap<TransactionType, ConcurrentHashMap<Exchange, ConcurrentHashMap<TransactionType, ConcurrentHashMap<Exchange, ConcurrentLinkedQueue<Transaction>>>> transactions) { this.transactions = transactions; } public void setName(String name) { this.name = name; } protected void setStakes(Collection<Stake> stakes) { this.stakes = stakes; } public static Portfolio findOrCreate(String portfolioName) { final String queryStr = "select p from Portfolio p where name=?1"; try { return PersistUtil.queryOne(Portfolio.class, portfolioName); } catch (NoResultException e) { // context.getInjector().getInstance(Portfolio.class); // PersistUtil.insert(portfolio); return null; } } protected void setManager(PortfolioManager manager) { this.manager = manager; } public static final class Factory { /** * Constructs a new instance of {@link Tick}. * @return new TickImpl() */ public static Portfolio newInstance() { return new Portfolio(); } public static Portfolio newInstance(String name, manager); return entity; } // HibernateEntity.vsl merge-point } private PortfolioManager manager; @Inject private Logger log; @Inject protected Context context; @Inject protected PortfolioService portfolioService; private Asset baseAsset; private ConcurrentHashMap<Asset, ConcurrentHashMap<Listing, ConcurrentLinkedQueue<Position>>>>> positions; private ConcurrentHashMap<Asset, ConcurrentHashMap<Listing, ConcurrentHashMap<Exchange, ConcurrentLinkedQueue<Transaction>>>> transactions; private Collection<Stake> stakes = Collections.emptyList(); private final Collection<Balance> trades = Collections.emptyList(); }

Portfolio代码:

点击次数:60476
作者:
web前端行业资讯
Web new NewsList
英特尔宣布与法拉利跨界合作欲将AI技术用于赛车运动 ,,2018年01月11日甲骨文服务器出漏洞:攻击者用漏洞挖矿获取加密货币 ,,2018年01月11日用深度学习设计图像视频压缩算法:更简洁、更强大 ,,2018年01月11日Ubuntu内核和NVIDIA更新:修复Meltdown和Spectre两处漏洞 ,,2018年01月11日AntDesign3.1.1发布,阿里企业级UI设计语言 ,,2018年01月11日微信「跳一跳」带火小游戏,开发者如何快速上手? ,,2018年01月11日谷歌公布最新安卓系统份额:你用上奥利奥了么? ,,2018年01月11日腾讯开发出“3D音效”算法:普通耳机实现3D实时语音效果 ,,2018年01月11日谷歌工程师点赞中国程序员实现Node.js启动超4倍提速 ,,2018年01月11日三星电子总裁兼CE部门负责人金炫奭:万物互联时代到来 ,,2018年01月11日NVIDIA和大众合作建立智能驾驶助手 ,,2018年01月11日GIMPS项目报告发现已知最大素数 ,,2018年01月11日微软与生物技术公司开展AI驱动的血液检测同时诊断数十种疾病 ,,2018年01月11日微软跨平台移动开发工具套件HockeyApp宣布免费 ,,2018年01月11日《硅谷》里神乎其神的压缩技术,AI正在一点点做出来 ,,2018年01月11日LinuxMint19代号敲定为“Tara”预计2018年5月至6月期间发布 ,,2018年01月11日Facebook发布wav2letter工具包,用于端到端自动语音识别 ,,2018年01月11日开源数据库ArangoDB正进行约1156万美元股权融资 ,,2018年01月11日IntelCPU漏洞闹大:腾讯云紧急升级 ,,2018年01月11日2018年1月全球数据库排名:Redis夺回第八 ,,2018年01月11日Lyft将联手无人驾驶公司于CES上展示无人驾驶汽车 ,,2018年01月11日京东X无人超市首家社会门店开业:刷脸进、微信自动结算 ,,2018年01月11日担心被AI取代是杞人忧天?高晓松跨年演讲说的有几分对 ,,2018年01月11日免费授权技术许可Intel宣布在未来CPU中集成雷电3 ,,2018年01月11日算法决定你在社交媒体上看到的信息 ,,2018年01月11日谷歌安全博客披露“英特尔内核漏洞”更多细节 ,,2018年01月04日Postgres10开发者新特性 ,,2017年12月28日阿里巴巴、狗尾草、苏大联合论文:基于对抗学习的众包标注用于中文命名实体识别 ,,2017年12月28日柯洁的2017:20岁,与AI斗与人类斗,其乐无穷 ,,2017年12月28日如果机器人拥有痛觉,这个世界会有哪些不一样? ,,2017年12月28日在js文件中如何获取basePath处理js路径问题2014年01月29日Centos6.5下iscsi存储搭建 【编程语言】2015年04月24日Hadoop1.x的Task,ReduceTask,MapTask随想【编程语言】2015年05月15日Maven存储管理软件Artifactory2.4发布 ,,2016年06月23日ExtJS简介让你知道extjs是什么2014年01月29日liunxphp的GD库添加jpeg文件的支持 【移动开发】2014年12月01日使用Socket抓取网页源代码 【编程语言】2014年11月10日算法----bonusdumplings 【编程语言】2014年12月29日下载安装setuptool和piplinux安装pip2014年01月29日leetcode||89、GrayCode 【编程语言】2015年04月17日ECharts系列-柱状图(条形图)实例一【编程语言】2015年01月19日UIWebView隐藏右侧和底部滚动条,去掉滚动边界的黑色背景,禁止左右滑动【数据库】2015年04月24日百度搜索关键词上线大家快点踊跃使用吧【编程语言】2015年07月07日uva12296(切割凸多边形)【Web前端】2015年08月03日让回调函数showResponse也带上参数的代码2014年01月29日JavaWeb-10(会话技术之session&JSP) 【编程语言】2015年04月02日ListView中删掉某个item时出现整个ListView都看不见,但是数据源有改变 【Web前端】2014年12月23日【翻译】finalize方法到底要干嘛 【移动开发】2015年03月20日文本框禁止粘贴【移动开发】2014年12月02日HDU3810Magina(搜索+用优先队列模拟01背包)经典【编程语言】2015年01月19日openSUSE国内镜像汇总 【移动开发】2015年04月07日android手电筒原理 【移动开发】2014年11月04日水平tab和垂直tab表单设计2014年01月28日Javascript实例教程(19)使用HoTMetal(7)2014年01月29日Linux常用命令(三十一)-grep【移动开发】2014年12月01日【笔试】27、斐波那契数列 【编程语言】2015年08月27日TCP网络编程中connect()、listen()和accept()三者之间的关系 【综合】2015年05月11日医疗时鲜资讯:自由执业能否给电子病历、影像中心“云端化”带来机遇? 【编程语言】2014年12月16日ORACLE问题集【综合】2015年06月02日单纯形法求解线性规划问题(C++实现代码) 【编程语言】2015年07月21日
我们保证
We guarantee
> psd效果文件手工切图,保证图片效果最好体积最小利于传输
> 100%手写的HTML(DIV+CSS)编码,绝对符合W3C标准
> 代码精简、css沉余量小、搜索引擎扫描迅速,网页打开快捷
> 应用Css Sprite能够减少HTTP请求数,提高网页性能
> 跨浏览器兼容(IE6、7、8、9,Firefox火狐,Chrome谷歌)