写写年度收益率年均收益率和年化收益率-4

没想到这个年化收益率写到第四篇,这一篇按之前年化收益率的叙述( https://ufqi.com/blog/income-rate-annuals-with-yale/ ),我们来分析股神、世界首富沃伦巴菲特(Warren E. Buffett)及其背后的公司Berkshire Hathaway Inc的历年投资收益情况, 同时拿来与耶鲁捐赠基金进行一些比较.

在动笔之前,我们搜索一下股神的相关股市的故事,材料很丰富,其成神之路也几乎不可复制,令人敬佩。在Berkshire的官网上可以轻松查询到股神巴菲特自1965年以来的历年的投资收益率,同时也包括有截至最后年份的年化收益率。截至2020年底,股神长达55年的投资历程(1965-2020),55年长期投资的年化收益率高达 20%, 当之无愧的神仙,财神。

Berkshire官网上的数据以2018年为分水岭,2018年之前的数据与之后的数据由于统计口径不同,导致是两个完全不同的版本,差异是会计计算方法,2018年之前没有适用GAAP(Generally Accepted Accounting Principles, 被广泛接受的会计准则,美国会计准则),2018年后则是适用了GAAP。具体到每一年年份上,两者差异挺大的,比如1965年的Non-GAAP的年度收益率是 23.8%, GAAP之后就变成了 49.5%, 1966年的Non-GAAP: 20.3%, GAAP: -3.4%, 具体可以参考Berkshire 2018年的年度报告。下文会再提到GAAP。

尽管每一年的调整前后都变化挺大的,有升有降,但拉长历史来看,多年后的年化收益率居然变化不大。
由于我们前一节在考察耶鲁捐赠基金的收益率数据时,只能拿到最早到1997年的数据,所以如下我们选取Berkshire的数据时,也从其1997年的数据开始对比考察。

也同样是由于耶鲁捐赠基金的对比基准选择了道琼斯工业指数,而不是SP标普500指数,所以这里我们也继续使用道琼斯工业指数。在Berkshire官网上,其基准对比的是SP标普500指数。同为美国股市指数,道琼斯工业指数与SP标普500指数虽有差异,但很相似。

8. 股神巴菲特24年来的年度、年化收益率分析

数据来源于Berkshire官网, https://www.berkshirehathaway.com/reports.html ,Berkshire的自我介绍:
“Berkshire Hathaway is re-engineering small business insurance.”
还是 Small business, 是依然很谦虚,还是没有更新官网?

Fig-1. Berkshire历年投资收益率, 对比耶鲁捐赠基金,道琼斯工业指数, 1997-2020

8.1. 过去24年未能跑赢耶鲁基金

过去24年里,巴菲特领导的Berkshire投资年化收益率为10.15%(10%),比老耶鲁基金的24年里年化收益率 11.94%(12%)略低,但仍是非常亮眼和令人骄傲的成绩。回顾最近20年来,世界经济2008金融危机,2018中美贸易战和2020新冠疫情,都对经济发展产生了广泛而深远的影响,股神巴菲特等人能持续保持财富按预期增长,实属不易!


Fig-2. Berkshire与耶鲁基金、道琼斯指数对比

巴菲特近24年来的收益跑输了耶鲁基金,可能主要归因于股神的主要资产在证券市场,而耶鲁基金正是依靠多元化资产配置,成功在股灾时避开了一部分亏损。可能所有的高手之间最后的比试,不是谁赚取得多,因为普通行情或者大涨行情,都赚取得很多,而是比试在亏损时,谁亏损的少。这一点恰如体育竞技比赛时,高手之间的竞技,更多的是依靠对手的失误。

根据网上盛传的资料,巴菲特是价值投资的倡导者,在选择具有价值的股票(很湿的雪和很长的坡道)的同时,也同时强调择时“别人贪婪时恐惧,别人恐惧时贪婪”。可能正是这种主动管理带有浓厚个人志趣和投资眼光,使得Berkshire的年收益率与道琼斯工业指数没有很强的相关性。

股神在Berkshire年度报告2019中写道他们选择股票与买入时机时,说了三个基本条件:1)在有形资产净值计算上有好的投资收益,2)有能力的且诚实的经理人和3)相对合适的价位。“In addition, we constantly seek to buy new businesses that meet three criteria. First, they must earn good
returns on the net tangible capital required in their operation. Second, they must be run by able and honest managers.
Finally, they must be available at a sensible price.”

8.2. 一直跑赢道琼斯工业指数,且与其不相关

进一步地计算,我们发现Berkshire的年收益率的变化与道琼斯工业指数和耶鲁捐赠基金均没有明显的相关性,呈现弱相关或者不相关,相应的系数分别为 0.52 和 0.34。

Fig-3. 道琼斯指数、巴菲特投资和耶鲁基金年度收益率对比, 2997-2020

股神巴菲特的24年年化收益率 10.15% 跑赢了道琼斯工业指数 6.7%,与之对应的相关系数为 0.52, 说明还是有一定的弱相关。大致可以推测,在大面积股灾的情况下,股神的股票配置也未能独善其身。比如在过去的24年中,2002,2008,2015等股神与大盘指数都同时录得了亏损记录。幸运的是,在股灾时,股神依然能够赢取大盘指数,跌的时候少跌些,而赢的时候则多多赚取了一把。这是股神的魅力所在之一吧。

8.3. Berkshire股神巴菲特视角下的GAAP

巴菲特作为Berkshire董事会主席在公司年报2018,2019中都明确表示反对采用GAAP方式编制年报数据,尤其是每年的年化收益率。

网上对于GAAP的评价,正面多于负面,原因在于市面上很多上市公司,需要统一的描述语言与标准来向公众报告年度业绩。如果没有统一的标准,很容易出现鸡同鸭讲,雪梨对蜜桃的情形,不利于公众解读和比较各个上市公司的业绩。

关于GAAP,股神在Berkshire公司年报2019中,在一节名为 The Power of Retained Earnings 中进行了详细说明。简而言之,股神巴菲特希望Berkshire的股东关注“到手的收益”(Operation Earnings)——这里主要是指股票的分红,而不要关注由股价上涨或下跌带来的“浮盈”或者“浮亏”——因为那是未交割未实现的部分(unrealized)。

2018年之前,Berkshire汇报给大家的收益,都是已经到手的分红等已经实现了的,不包括浮盈或者浮亏部分的。这部分大多数年份其收益率都是正数。
GAAP新规要求在年报中,需要包括浮盈和浮亏部分,这么一转换,Berkshire的部分年份的收益率就有正转负了,也有正的更高,或者负得更厉害的情况。终止,投资回报的振幅变大了许多。这可能也是近24年来,股神巴菲特的年化收益率(适用新GAAP)略低于耶鲁基金的年化收益率的原因之一。

一个实际的例子,比如Berkshire持有Apple Inc和Coca-Cola股份占比为5.7%, 9.3%, 2019年这两家公司的分红分别为 773M, 640M,而这两家公司股票市值当期的浮盈分别是2519M,194M。美国苹果公司股市浮盈很多,然而其分红却比可口可乐少,而可口可乐股市浮盈很少分红却与苹果公司差不多。

9. 年度、年化收益率分析小结-3

9.1. 股神巴菲特背后财大气粗的靠山

我们在此前的讨论小结中认为,在证券市场淘金,一般的守则是高抛低吸。股神巴菲特却有点另辟蹊径的意思,以自己感悟的三条选择标准,首先尝试100%买下,不能100%控股,再考虑部分持股,然后长期持有。在长期持有的情况下,享受连续不断的收益分红。

这的确有点像是滚雪球,有很厚很湿的雪和很长的坡道,发现这些,后面的就水道渠成。与在证券市场中频繁的审时度势地进行高低判断,进行高抛低吸不同,这种看似躺赢的背后,实际需要源源不断的的资金支持,尤其是分红较少或者没有分红的时期。

Berkshire具有某种不可复制的原因是其背后有Property/Causality Insurance业务,正是这些业务为其提供了源源不断的资金支撑,尤其是证券市场没有分红的时期。“Our property/casualty (“P/C”) insurance business has been the engine propelling Berkshire’s growth since 1967…, This collect-now, pay-later model leaves P/C companies holding large sums…”

因此,我们可以在高抛低吸地盈利模式下,额外增加一个在证券市场获利的途径,以股神巴菲特的选择标准,选定标的物,然后长期持有,享受分红,前提是有其他业务的现金流支撑。截至2019年,这些保险业务积累的浮动资金从1970年的39M,增加到2019年的129B(129,423M). 

这种二千亿美元的资金规模,我们在 写写年度收益率年均收益率和年化收益率-2 ( https://ufqi.com/blog/income-rate-annuals-with-cic/ )论述过,作为中国国家主权财富基金中投公司注册资本是2000亿美元。

美国政府2019年收了243B的公司所得税(corporate income tax), Berkshire一家缴纳了 3.6B,占比1.5%。

9.2. 山外青山楼外楼

我们从分析中国社保基金近20年年化收益率(8.5%)开始,进而分析了中国中投公司的近12年来的境外投资年化收益率(6.13%),小结道,证券市场淘金不易,顶级团队所获得收益与其他行业横向比较也是平均水平线上下,看似高大上,在充分竞争市场,实则获得正常收益。所使用方法也是高抛低吸。

随后我们发现通过资源配置多元化的耶鲁捐赠基金,另外一个传奇,近24年的年化收益率高达 12%,在高抛低吸的基础上,进行多元化配置到房地产、自然资源和私募股权等。

在之后我们聚焦到证券市场分析了股神巴菲特的传奇,55年来,年化收益率高达20%,尽管最近24年来,使用新的GAAP计算,年化收益率低于耶鲁基金,但不影响他证券市场“封神”。其所创立的价值投资也新开一派。

传奇远不止这些,低调的Jim Simons所领导的大奖章基金(the Medallion Fund),据传依靠量化投资,收获了高于股神巴菲特的年化收益率(30%?)。量化投资,依靠数学模型,依靠计算技术,自动化高频交易,不断发现并放大微小的利差,重复利用这些利差进行套利,与价值投资可谓是大相径庭,他们完全不看“价值”。

山外青山楼外楼,令各国政要都头疼的George Soros所领导的量子基金(对冲基金, Hedge Fund),依靠做空或做多,一度兴风作浪到触发一个国家或地区的金融危机、经济危机。他本人出席美国国会质询时,却说,他的一切手段都是合法的。

—-

这是温习经济学著作的第七篇习作,之前的各篇附列如下。

  1. 写写年度收益率年均收益率和年化收益率-3, 
    https://ufqi.com/blog/income-rate-annuals-with-yale/
  2. 写写年度收益率年均收益率和年化收益率-2 , https://ufqi.com/blog/income-rate-annuals-with-cic/
  3. 写写年度收益率年均收益率和年化收益率, https://ufqi.com/blog/income-rate-annuals/
  4. 治大国若过小家——写写王朝兴衰更替背后的经济账, https://ufqi.com/blog/political-reform-country-vs-home/
  5.  写写🏦存款利率贷款利率和负利率, https://ufqi.com/blog/captial-rate-and-minus-rate/
  6. 写写1929年美国经济大萧条与2020年美国股市大跌, https://ufqi.com/blog/us-1929-economic-crisis-2020-stock-shock/

—-

-R/y2SN , http://ufqi.com/blog/income-rate-annuals-with-buffet/

《投资学》进阶阅读推荐必读之书.

推荐:股神巴菲特是怎样炼成的?长文深度起底股神的传奇人生 , https://ufqi.com/news/ulongpage.842.html

Posted in 社会生活 | Tagged , , , , | Leave a comment

写写年度收益率年均收益率和年化收益率-3

高瓴资本张磊在其新书《价值》一书中,描述了如下内容。

“…耶鲁捐赠基金(The Yale Endowments)的资产规模却不断扩大,从他(大卫-史文森, David Swensen)上任之初的13亿美元,增长到2019年6月的303亿美元,增长了22倍多,过去10年的年化收益率为11.1%,过去20年的年化收益率为11.4%,是世界上长期业绩最好的机构投资者之一,获得了基金管理界和华尔街的高度关注…”

这引发我们的兴趣,本来这个关于年化收益率的主题已经写了两篇,分别给出了年度收益率、年化收益率的定义及公式( https://ufqi.com/blog/income-rate-annuals/ ),考察和分析了全国社保基金投资收益率、中投公司境外投资收益率 ( https://ufqi.com/blog/income-rate-annuals-with-cic/ )。本篇我们打算深入分析一下美国耶鲁大学捐赠基金会(The Yale Endowments)的历年投资收益率。

6. 耶鲁捐赠基金24年来的年度、年化收益率分析

耶鲁捐赠基金的投资哲学(策略):”The Yale Investment Office seeks to provide high inflation-adjusted returns to support current and future needs of the University.  We work to establish an appropriate risk-adjusted asset allocation and seek out long-term partnerships across the globe with managers who provide deep analytical insights and improve the operations of public and private businesses.” 

Fig-1. 中国社保基金和美国耶鲁大学捐赠基金投资收益对比, 2001-2020, 最右侧为同时期美股道琼斯工业指数的相关数据

由上图对比数据可以看出,耶鲁捐赠基金的投资业绩相当亮眼。从官网查询可以获得最早1997年至今的年度收益率数据,据此可以进一步地计算出24年来的年化收益率,11.94%(12%)。这个数据高于20年来中国社保基金的年化收益率 8.5%. 大致1997-1999三年间取得了相当不错的成绩拉升了其整体年化收益率。耶鲁基金的计算方法略有偏差,他靠“财年”——当年7月1日至次年6月30日为一个财年,这个用财年计算周期与默认的用自然年(当年1月1日至12月31日)作为计算周期略有不同。

比如耶鲁基金唯一录得负数(亏损)的年份是2009年,实际当年股市大灾是发生在2008年下半年,这种偏移或偏差后面还会继续提到。

横向比较,2000、2001、2002三个年份,无论是中国社保基金、美国耶鲁基金,还是美股道琼斯工业指数,都表现不好,尤其是美股道琼斯工业指数,连续三年下跌。同时期的社保基金和耶鲁基金能够保持正收益,实在是难得。中国社保基金与美股可能关系不大,单独考察耶鲁基金与道琼斯工业指数或更有意义。在美股大跌的年份,耶鲁基金能够不跌甚至是小赚,可能与其引以为傲的资产配置有关。

6.1. 耶鲁基金资产配置多元化、持续不断调整配比

Fig-2. 耶鲁捐赠基金多元化资产配置, 1990-2020

通过Fig-2 可以看出耶鲁基金的配置与传统股票股权相关的比例一直很高,如Domestic Equity(国内股票)、Foreign Equity(国外证券)和Absolute Return(绝对收益,绝对正收益?), 国内外股票投资和经封装或委托的具有绝对正收益性质的证券投资。

变化较大较明显地地方在于国内股票和风险投资的此消彼长,直接投资美股的比例下降,而私募股和风险种子天使投资增多。
也许正是通过这种少投资或者不直接投资美国股票市场,所以可以避免股灾时,财富大幅下挫。
然而,尽管耶鲁基金极力避免亏损或者负数收益,在其过去的24年里,仍有一个年份的收益是负数,而且相当可怕的负数。2009年的 -24.9%, 当年道琼斯指数下跌了 -33.84% , 耶鲁基金的风险敞口几乎等同于美股。

6.2. 与美股道琼斯工业指数强正相关


Fig-3 耶鲁基金年度收益率与道琼斯工业指数

通过Fig-3的历史曲线图可以看出,耶鲁基金的收益率与道琼斯工业指数具有弱的正相关关系,相关系数为0.68。考虑到耶鲁基金按财年计算,而道琼斯工业指数按自然年计算,这个相关系数大致可以提升到 0.75~0.85, 几乎达到强相关的范围(>= 0.8)。毕竟国内外股权投资、绝对收益投资,最终都要流入证券市场。

尽管耶鲁基金极力避免股灾对投资收益的影响,也即追求稳健和绝对收益为第一位原则,2009年 -24.9% 年度收益率应该属于历史罕见的异常。这一亏损数据中,可能股灾并没有多大贡献,而耶鲁基金在资产配置中有大量的Real Estates(房地产),这些投资带来的巨亏,最终导致耶鲁基金历史上罕见的巨亏,从而使得耶鲁基金虽然隔离了股灾的风险,但没有预料到祸不单行地叠加了房地产巨亏!
从Fig-2中,我们也看到2009年后,资产配置中房地产的比例在逐渐降低。不过诡异的是,其后伴随多年的是年度收益率也在走低,可见随着风险敞口的缩小,收益似乎也逐渐降低。

通过更加多元化的资产配置,20年来,虽然历经证券市场的牛熊市,耶鲁基金当之无愧的基业长青,跑赢了道琼斯工业指数近一倍(11.94 vs. 6.7),也大幅跑赢了主要在证券市场淘金的中国社保基金和靠股灾大坑发财的中投公司的同期收益率。 

7. 年度、年化收益率分析小结-2

通过在 5.1、5.2节里,我们大致看到在证券市场赚钱是很难的,即便聪明绝顶且资金充沛,要想获得超出行业平均收益率,也不是容易的事。

通过证券市场获利的基本原则是高抛低吸,由于高低的相对性,实际操作起来要充分考虑各种因素进行判断,量化一下就是需要进行概率计算,在某种场景下,纳入各种考量因子,计算进行投资时的赢的概率。

经过对耶鲁基金投资的分析,我们在证券市场之外获悉多元化投资对整体收益率的影响,通过房地产、自然资源(矿产)等非金融市场的投资,可以放大投资收益。
正像硬币的两面,当房地产、自然资源遭遇行业危机时,也可能放大亏损。总体而言,多元化资产配置,收益率整体上要大于单一证券市场,可能是这个原因导致美国耶鲁基金24年来的年化收益率(11.95%)大于中国社保基金20年来的年化收益率(8.5%),大于中国中投公司12年来的年化收益率(6.54%)。

耶鲁基金是目前我们所考察长期投资年化收益率最高的对象。如有可能,我们希望再新开一篇继续这个分析,去看看股神巴菲特及其管理的投资公司的年化收益率情况。

—-

这是温习经济学著作的第六篇习作,之前的各篇附列如下。

  1. 写写年度收益率年均收益率和年化收益率-2 , https://ufqi.com/blog/income-rate-annuals-with-cic/
  2. 写写年度收益率年均收益率和年化收益率, https://ufqi.com/blog/income-rate-annuals/
  3. 治大国若过小家——写写王朝兴衰更替背后的经济账, https://ufqi.com/blog/political-reform-country-vs-home/
  4.  写写🏦存款利率贷款利率和负利率, https://ufqi.com/blog/captial-rate-and-minus-rate/
  5. 写写1929年美国经济大萧条与2020年美国股市大跌, https://ufqi.com/blog/us-1929-economic-crisis-2020-stock-shock/

—-

-R/j2SR , http://ufqi.com/blog/income-rate-annuals-with-yale/

《投资学》进阶阅读推荐必读之书.

Posted in 社会生活 | Tagged , , , , | 2 Comments

写写年度收益率年均收益率和年化收益率-2

前述写到全国社保基金投资年度、年化和年均收益率分析及其与同期中国央行M2的增长率对比( -R/H2SR,  https://ufqi.com/blog/income-rate-annuals/ )。大致小结为社保基金投资之所以牛到厉害,由于在2007和2015中国股灾时能够成功逃顶获得远超出平均水平的收益率;同时在2019、2020两个年份,分别抢到低点,然后又获得较高的收益率;以此赢得20年来年化收益率8.5%的美誉,跑赢同期中国央行M2的增长率年化6%。

行文到这里,我们想进一步地写写中国另外一个投资大亨:中国投资有限责任公司,中投公司,看看他的投资业绩。毕竟与全国社保基金200亿人民币起家不同,中投以2000亿美元起家。她的投资业绩的年化收益率也值得品读。

4. 中投公司境外投资12年来的年度、年化收益率分析

中投公司2007年设立,是国家主权财富基金,初始资金规模2000亿美元。其业务主要分三块:中国国际、中投海外和中央汇金。前两者主要在境外进行投资活动,中央汇金是各大国有大银行的大股东。

在中投公司的官网上有截至2019年的投资业绩数据( -R/G2SZ )。截至2019年,其累积年化收益率为 6.13% , 略低于全国社保基金的 8.5%。 不过中投公布的数据统计口径有两处差异: 1) 年度净收益率(刨去税金等其他?), 2)计算时间以公司成立日2007年9月29日起计算(不是自然年?)。

在新华网的一篇报道中提到“新华社北京(2020年)9月25日电(记者吴雨)中国投资有限责任公司25日发布年报显示,按美元计算,2019年中投公司境外投资净收益率为17.41%,投资收益额422亿美元。” ( -R/a2SQ )。
由于我们即将进行的是趋势分析,上述两点差异并不妨碍将要做的分析与讨论。

纵向来看,12年来,中投公司境外投资收益率颇为中规中矩,没有太突出超常的收益率,也没有明显跌份的亏损,波动区间小于社保基金的收益率。初步推测,可能跟海外欧美国家证券市场波动小于中国沪深证券市场有关。因为从公司要求和管理团队风格来说,都是谨慎操作——赚多少无所谓,一定不能亏太多。

循着这个思路,我们把中投公司境外投资年度收益率(净收益率)的变化与美国股市道琼斯工业指数做对比,或能窥见在这不错的投资业绩背后的一些逻辑或手法。

中投公司境外投资在2008-2020这12年里,2009-2010, 2017和2019,这四个年份表现不错,其年度收益率分别为 11.7%, 11.7%(两年一样的?), 17.59% 和 17.41%。如果打开道琼斯工业指数的历史曲线进行事后判断分析,大致可以看到:
1) 2009年的大涨是由于2008年金融危机挖下一个巨大的坑,道琼斯指数低至 6440点;
2) 2010年的高收益,是由于2010年中有坑,在10000点徘徊,而年末又成功拉起到11500点附近;

3) 2019年的高收益,是由于中美贸易战2018年挖下的坑, 2018年末低至 21800点左右,而2019年末到 29000点;
4) 2020年预计会是高收益年份,估算给到 10%, 因为新冠疫情,在2020年3月份砸出巨型天坑,道琼斯指数低至 18000点,而2020年年末成功拉起到 30000点。

5)故意将 2017年的大涨留在最后说,这一年没有坑,近乎直线拉升? 为何能实现躺赢?这12年里,2017年唯一实现躺赢的年份,也即买啥都赚。

可以小结: 中投公司过去12年里,有5个年头将是大赚,而这些年份里,靠股灾砸出坑的有4次——2008年金融危机一次,2018年中美贸易战一次,2020年的新冠疫情一次,2010年中的小坑,原因不详。难怪在新冠疫情导致股灾时,有证券业内人士称之为“黄金坑”。
对于这种体量无限大“弹药无限多”的机构投资者来说,不怕套的无限长,在面临每次股灾时,似乎都会在心底泛起某种“大发国难财”的想法。

相反地,在2011、2015、2008和2018年里,都是亏损,从道琼斯指数上看,当年都是有坑,而且在年末没有反弹起来。令人称奇的时,2008、2018等大盘指数几乎都是 20%以上的下跌,而中投公司却能及时止损或者成功逃掉?即便是 2011、2015的坑,事后看来,也很深,很吓人,中投公司境外投资是如何做到及时止损或者成功逃顶的?

未卜先知的研判?如果说像社保基金等机构投资者主要在国内证券市场进行操作的话,我们还可以阴谋论地臆想一下可能的操作空间。然而中投公司境外投资主要投向的是欧美发达国家成熟运作的证券市场,如道琼斯工业指数等,我们几乎无法再进行任何阴谋论的猜测。
也许真实情况,只有那些实际操盘人知道,那些被称之为精英的操盘手们知道如何在牛市获取超过大盘的收益,而在熊市避免太多亏损。往往后者避免亏损,比在牛市获取超常收益更重要。

如果再横向地对比社保基金的神奇操作,或者真相就是那看起来再朴素不过的道理:高抛低吸。
2007年道琼斯指数连涨3年到高点 14200点左右;2017年连涨2年到24600点左右,或许在大跌来临之前的几周、几日,精英高手们已经逃离了,此为高抛。2008和2018股灾时,或他们已经在股灾前空仓持币待购了。也许没有2008、2018的股灾,他们同样会抛售,然后等待下一个入场的机会。

2011年和2015年的坑,或有点意外,其前期并没有连续的大涨。而坑后当年也有反弹,所以略微亏损在情理之中。从上帝视角来看,如果当时精英操盘手们能够在坑底进行买入操作时,或许当年的收益率能够扭亏为正。


美国股票道琼斯工业指数2007-2020

5. 年度、年化收益率分析小结

5.1. 金融证券市场赚钱是很难的。
纵向的20年、12年跨度观察,横向的全国社保和中投公司笔投资业绩比较,都说明这一点,靠钱生钱,这种有点“不劳而获”的行当,很艰难。根据数据( -R/c2SP ,有福常在:  https://ufqi.com/news/ulongpage.446.html  ),1995年-2018年,中国25个行业的平均利润率不过8.35%,依旧低于GDP年均增速。同时期,货币M2年均增速为16.14%,GDP年均增速为8.87%。

无论是全国社保基金还是中投公司,他们的资金量、团队操盘能力,如果说他们是这个地球上是二流的,估计无人敢称为一流的。他们勤勉尽责,殚精竭虑地工作,每年也是有亏有赚,多年后看,所获得收益,也基本与25个行业平均收益差不多( 8.35% )。

最顶级的人才团队,最顶尖机构,所获得的成绩不过如此 ( 8.5% 左右 )。排后面的二流团队、二流机构又所获几何?三流团队和三流机构呢? 草台班子呢?资金和投研能力都排在末梢的个人散户又如何?

当我们分别品读了社保基金和中投公司近20年的收益情况分析后,再来听听时任中国人民银行党委书记、银监会主席郭树清先生的话( -R/l2SW , -Url4P ):
“在打击非法集资过程中,要努力通过多种方式让人民群众认识到,高收益意味着高风险,收益率超过6%的就要打问号,超过8%的就很危险,10%以上就要准备损失全部本金。”

是不是有新的体会和感悟,醍醐灌醒,振聋发聩?这真不是吓唬人的!我们最顶级的团队上不封顶的资金量,没日没夜累死累活地干,也才只有 8% 左右年化收益率,随便来个隔壁老王,就能承诺 8% 年化收益率?

一时一事上获得暴利或有偶然性,基业长青的数年之后,能有媲美全国社保基金和中投公司的年化收益率,差不多可以去跟他们PK了。那么多基金经理,10年以上年化 10% 以上的,仍是凤毛麟角,恰如最精英最顶级的全国社保基金团队或者中投公司的团队。

5.2. 年化收益率攀高的秘诀:高抛低吸
高和低都是相对而言,何处为高,何处为低?
相比前一阶段,上涨了 10% 算高吗? 下跌了 10% 算低吗?
10% 不算的话,那 15% 呢? 20% 呢?
哪个算是高,又为何是?

另外,相比前一阶段,是前一天,两天,三天,一周,两周,三周,一月,两月,三月,半年,一年,两年?

即便是知道了此处是高不是低,或者是低不是高,那经济学中股价随机游走不可预测的魔咒又在时时响起…

于是,终极地,我们回到概率论和博弈论等上了。举凡知其不可为而为之,莫不是概率论或博弈论等,区别可能是,有的人赌的大,1%的胜率,也押上 90%的筹码;有的人堵的小,90%的胜率,只押上1%的筹码。

我们猜测,全国社保基金团队和中投公司境外投资团队,可能会 60% 以下的胜率不考虑押注,在有 7~80% 胜率时,也只押上 2~30% 的筹码。

—-

这是温习经济学著作的第五篇习作,之前的各篇附列如下。

  1. 写写年度收益率年均收益率和年化收益率, https://ufqi.com/blog/income-rate-annuals/
  2. 治大国若过小家——写写王朝兴衰更替背后的经济账, https://ufqi.com/blog/political-reform-country-vs-home/
  3.  写写🏦存款利率贷款利率和负利率, https://ufqi.com/blog/captial-rate-and-minus-rate/
  4. 写写1929年美国经济大萧条与2020年美国股市大跌, https://ufqi.com/blog/us-1929-economic-crisis-2020-stock-shock/

—-

-R/b2SO , http://ufqi.com/blog/income-rate-annuals-with-cic/

《投资学》进阶阅读推荐必读之书.

Posted in 社会生活 | Tagged , , , , , , | 4 Comments

写写年度收益率年均收益率和年化收益率

银行存款利率一降再降,叠加一升再升的通货膨胀率( https://ufqi.com/news/ulonglist.5786.html ),实际上的存款利率已经早是负数,我们所持有的资金的购买力在不知不觉中降低再降低,贬值再贬值。只是由于官方存款利率还没有变成负数,直观上我们还感觉不到,或者刺激得不是那么强烈。

然而,“先知先觉”的同学们已经开始积极主动的进行投资理财了。在这项充满挑战和机遇,也伴随着刺激和风险的活动中,需要具备一些基础知识或者名词定义。其中较为高频和优先的词语叫做收益率,根据使用场景不同,又分为年度收益率,还有月度,月息,七日,每日收益率等等,还有年化收益率和年均收益率等。

这篇打算深究一下这几个收益率名词的定义和使用场景。这是温习经济学过程中的第四篇习作,之前三篇分别是《写写1929年美国经济大萧条与2020年美国股市大跌》( https://ufqi.com/blog/us-1929-economic-crisis-2020-stock-shock/ ),《写写🏦存款利率贷款利率和负利率》( https://ufqi.com/blog/captial-rate-and-minus-rate/ ) 和 《治大国若过小家——写写王朝兴衰更替背后的经济账》( https://ufqi.com/blog/political-reform-country-vs-home/  )。

前文在写写存款利率贷款利率和负利率的文章中已经谈到,当今,除了中国央行公布的官方存款利率是正数,美国美联储官方公布存款利率区间是0~0.25,其他一些国家和地区已经是存款负利率了。这只是名义存款利率,叠加通货膨胀率,则实际货币贬值得更加厉害,可能这也是国际社会上,不存钱,超前消费和信用消费诱因之一。

1. 年度、年化和年均的基本概念定义及计算公式

在讨论年度收益率,年化收益率和年均收益率之前,需要先定义和假设一下:
本金、期初/起初值,通常用 P 表示,Prime;
终值、末期/末值,通常用 F 表示, Final?
利率,用 R 表示, Rate;
期数、轮次,用 n 表示。
接下来要用到一些简单易懂的公式了,以便给那些“太长不看”的同学快速的答案。

年度收益率 R = ( ( F / P ) – 1 ) * 100% ;
年化收益率 R =  ( F / P ) ^( 1 / n ) – 1 ;
年均收益率 R = Sum ( R0 : Rn ) / n ;

其中: / 表示除法运算, * 表示乘法运算, ^ 表示幂运算, Sum 是求和函数, R0 是第一期收益率, Rn 是第n期收益率。这里的“期” 默认是指年。

年度收益率 含义是本年(自然年或者财政年),期末的数值除以期初的本金值,然后做百分化表示;
年均收益率 含义也相对好理解,就是每年平均,将多个年份的收益率加起来做算术平均数即可。年均还有另外一层意思是横向的,比如将同一年份内的多个不同数据对象的数值加起来做算术平均,如2019国民年均收入增长率。
年化收益率,相对较复杂一些,这里有复利计算的思想在里面,也即每年的收益率的计算总是以上一年的终值作为本金。另外,就是这里的轮次和期数 n , 当 n > 1 时,可以理解为多个年份后计算年化收益率;当 n < 1 时,表示短期收益率的延长理论值,这也是我们能够在小于一年期的理财产品中能够看到“七日年化利率”的由来。

行文至此,概念和理论希望已经说清楚了,接下来写写数据上的干货。我们希望使用上面的几个指标来考察一下全国社保基金(全国社会保障基金, ssf.gov.cn )权益投资收益的历年数据情况。

2. 全国社保基金投资年度、年化和年均收益率分析

拿全国社保基金投资收益率说事,是因为她干得漂亮。“(全国社保基金)理事会是境内最大机构投资者…,全国社保基金成立以来,取得了骄人的投资业绩,自20008月成立至2017年底,年均投资收益率8.44%累计投资收益额大于累计财政净拨入额。

Fig-1. 全国社保基金权益投资收益率2001-2020

上图表格中收录了全国社保20年来的每年年度收益率(绝对值),基于年度收益率,我们推导计算出了年化收益率和年均收益率。为了方便计算,我们假设了全国社保基金本金初期值为 10K,其实真实值应该是 200亿人民币左右。也为了凑数,我们根据2020年前11个月的数据,估算了2020年的年度增长率 15% 。

可以看出年度收益率波动较大,而年化收益率较平缓,年均收益率与年化收益率接近,且偏大。

可以看出,收益率最好和次高的年份是 2007和2006年,分别是 43% 和 29%。收益最差的年份是 2008和2018年,分别是 -6.8% 和 -2.3% 。令人惊奇是, 2009和2019都迎来了“报复性”的增长。
截至 2020年,20年来,全国社保基金年化收益率为 8.5% , 年均增长率为 9%, 这一业绩的确是“骄人”。之所以取得这样的成绩与好年份超高收益有关,如 2006-2007,2014-2015, 2019-2020. 其余年份也几乎乏善可陈。
这三个时间段里前两个刚好对应则中国股市是两次大的股灾,分别是2007年和2015年,牛气冲天之后一落千丈!全国社保基金的投资负责人是如何做到精准逃顶的?

2019-2020 这个时段的高收益却分别对应中国股市的两个低点,分别是2019年1月的2440点和2020年3月的2745点。中国股市分别在这两个低点之后迅雷不及掩耳之势快速拉升,2019年之后断崖下跌!2020年高位震荡至今。

小结她的傲人业绩,2006-2007, 2014-2015, 成功逃顶,赚取超高收益后在股灾来临之前一刻安全撤离;
2019-2020,成功埋伏,在市场最低点勇于加仓,在获得一定收益后,再度出逃, 如此操作,2019年一次,2020年一次,分别斩获 10+% 的收益率!
成功逃顶或有不可描述的缘由或故事,但成功埋伏确有某种投资人的慧眼识珠。
如果用美国投资大师沃伦巴菲特的话来配音,或就是那句“在别人贪婪时恐惧,在别人恐惧时贪婪。”

拉长历史来看,总是大道至简。20年来,全国社保基金的投资人可能换了几茬,也许回撤和亏损的理由各个不同,但赚取盈余的姿势和理由总是那么一致。只是我们凡夫俗子,不识庐山真面目,只缘身在此山中。做事后盘点说得头头是道,实盘操作当时已惘然。

3. 中国央行20年来的M2年度、年化和年均增速分析

Fig-1的表格中右侧是同时期中国央行M2的增长速度数据。广义货币供应量(M2,Broad Money)的定义大致约等于全社会的货币量。货币(M0)=流通中的现金,即流通于银行体系之外的现金。狭义货币(M1)=(M0)+单位活期存款;广义货币(M2)=M1+准货币(单位定期存款+居民储蓄存款+其他存款+证券公司客户保证金+住房公积金中心存款+非存款类金融机构在存款类金融机构的存款)。

为了方便计算,我们也假设了M2的本金、初期值为 10K。由于M2的增速里面一个重要因素是GDP的增长,所以我们还在后面增加了同时期的GDP增速。官方定义上,M2的增长,主要是由于GDP增加了。两者一致是理想状态,增加多少东西(货物或服务)印多少钱;如果GDP增速大于M2增速,则货币升值,如果GDP增速小于M2增速,则货币贬值。

通过上面的记录数据,我们发现全国社保基金投资年化收益率 8.5%, 确实傲人的业绩,而同时期的M2是多少呢? 通过公开数据收集、计算得出,2001-2020期间M2的年化增长率为 14.8% , 同时期GDP的年化增长率为  8.9%。于是我们有这样一组对比数据:

2001-2020年间主要年化收益率、增长率数据
全国社保基金投资年化收益率: 8.5% ;
中国央行M2年化增长率: 14.8% ;
中国GDP年化增长率: 8.9% ;
M2净增长率:M2增长率 – GDP增长率 = 6% ;

从这一角度看,全国社保基金投资收益跑赢了M2净增长率(扣减GDP增长率),净年化收益率为 8.5% – 6 = 2.5%。
进一步地,我们发现2001-2020这20年间,如果某项投资年化收益率低于 M2净增长率 6% 的话,其持有的货币(资产)的实际购买力是下降的,货币(资产)被贬值。

此外,根据M2的历史数据,我们会发现,2008年金融危机时候的“大放水”,“四万亿”的确推高M2,使其急速上升,致使2009年的M2年度增长率达到 27.7% 。而2017年以来,M2年度增长率开始大幅下降至 8% 左右,几乎与GDP年度增长率接近,似乎是完美的理想状态了。

小结全文,年度收益率年均收益率和年化收益率本不难理解和使用,希望上面的这些数据能够存档下来,便于后面接续使用,更长时期观察、对比和分析。

-R/D2SO

写写年度收益率年均收益率和年化收益率

《投资学》进阶阅读推荐必读之书。

Posted in 社会生活 | Tagged , , , , , , | 6 Comments

GWA2吉娃兔引入JsDelivr公用CDN的开发与配置

新冠肺炎疫情持续差不多一年了,疫苗已经在望,希望人类早日战胜这个病魔。

GWA2吉娃兔 持续更新升级,这次在升级更新优化的路上,走得更远,尝试引入公用CDN(Content Delivery Network,内容分发网络)。借此,使得基于GWA2的各种应用程序、网页能够如虎添翼一般,更快的响应用户请求。这次改进源于我们持之以恒地追求——更高、更快和更强。

根据此前梳理的提速优化思路(-gMIS 吉密斯 升级:增加缓存,按时间快捷检索和全局SessionId等,https://ufqi.com/blog/gmis-update-with-cache-searchbytime/),我们分别在缓存和减少页面持续两个方便进行了各种优化改进。其中在缓存优化方向,已经进行了客户端缓存和服务器端缓存,独缺少网络层缓存(CDN)这块。迟迟没有下手进行这个网络层缓存的升级操作,一是CDN相对而言与代码层开发关系不大,或者没有关系;二是网络层的CDN几乎等同于加服务器、加带宽的意思,迟迟没有合适的机会。

根据 V2EX上技术高手的介绍,我们在考察了JsDelivr公用CDN之后,发现是一个很好的开源CDN方案,可以实现免费免备案使用的静态资源分发。

  WITH    

 

1. 使用JsDelivr的准备工作
JsDelivr 允许托管和分发的网页文件类型是JavaScript(.js)、CSS(.css) 和部分小尺寸的图片(.jpg, .png等)。

JsDelivr 可以读取开源发布在 npm 、GitHub和WordPress 上的以上相关静态文件。出于便于管理和更新GWA2所使用的全部静态资源类文件,我们选择将上述文件放在 GitHub 的公开项目上(Repository)。

在GitHub上为某个项目或者网站、App建立一个对应的Repos, 将GWA2 的 view子目录下的所有非html文件上传到 GitHub 对应的 Repos下即可。这些文件包括 ,js, .css, .ico, .jpg, .png 等等。

由于JsDelivr的目标是分发静态资源文件,当加载.html文件时,其content-type 为 text/plain , 所以目前还无法使用JsDelivr 分发 .html. 从另外一个角度来说,.html 文件通常包括有业务逻辑或者模板语言,放在自家服务器上,反而更好。

经过以上几步准备工作,现在可以通过如下路径访问到已经放入 CDN网络的静态文件。地址例如,

https://cdn.jsdelivr.net/gh/UserName/ReposName/view/SiteName/abc.css

其中, gh 代表在 JsDelivr语境中的 GitHub,
UserName 为当前资源文件在GitHub 上的用户名称,
ReposName 为当前资源文件在 GitHub 上的项目名称,
view 为 GWA2 的子目录,负责视图,文件结构保持与本地服务器相一致。

 

2. 在GWA2中引入CDN

GWA2 从最早时期已经采用了 MVC 分层设计,因此针对视图文件的修改,相对集中。所有视图文件的加载,都通过一个叫做 $viewdir 的全局变量进行控制。 $viewdir 告诉服务器或者模板引擎,视图文件的具体位置。

如果要引入JsDelivr ,则只需要在项目中,适当修改 $viewdir 的指向即可。通常涉及到的文件在 comm/footer.inc 中。

GWA2PHP:
$cdnStaticPrefix=”//cdn.jsdelivr.net/gh/UserName/ReposName”;
$viewdir = $cdnStaticPrefix.”/”.$viewdir;

GWA2Java:
//- +cdn, 12:34 2020-12-04
String cdnStaticPrefix = “//cdn.jsdelivr.net/gh/UserName/ReposName”;
viewdir = cdnStaticPrefix + “/” + viewdir;

 

3. 速度提升明显用户反馈良好

经过上述修改后,程序同步及html或模板更新后,页面浏览加载会感觉提升明显。直觉上会有所谓的“秒开”。这对于在国内浏览海外服务器的相关网站时,对比尤其明显。

理论上分析,一个HTML文件中,实际 html 代码的尺寸占比很小,网上有一些这方面的数据,可能在10%左右,而更多的则是需要呈现页面的 .js, .css和各类页面元素等。如果将后者这些静态资源文件交给CDN网络,其提速效果自然有突飞猛进的感觉。

另外,这些原本需要本地服务器解析请求做出应答的内容,完全交给了CDN网络,无疑极大地降低了本地服务器的负载和减少了本地网络的带宽占用。相应地,这些富裕出来的资源可以更好、更快地响应HTML页面的输出。

此消彼长,基本是在国内的用户浏览海外服务器的网站,页面打开实现“秒开”也是很有可能的。
这里的“秒开”应该主要是指首次打开某个全新的页面,由于GWA2已经在客户端进行了大量的缓存,在第二次之后打开或者刷新页面,这些静态的.js .css和图片文件等,多数将都由浏览器调用本地缓存来实现响应,那将是页面加载的极致快速。

有时候幸福来得就是这么突然,海外服务器的页面可以实现了秒开,而且这个CDN由于不涉及到具体内容文件,因此可以不用中国地区的备案,而且她也是免费的——GitHub免费寄存静态资源文件,JsDelivr负责免费分发到距离用户最近的地方——据说全球有上数百个CDN节点,这几乎可以媲美一流的CDN服务。

 

4. CDN回滚与容错

作为可靠的庞大的CDN网络,JsDelivr是稳定的,但也需要预防万一的突发偶然情况,如果由于某种未知的原因 JsDelivr突然不能用了,如何可以快速平滑的切回到本地服务器?

也即CDN服务需要能够在必要的时候进行回滚或者降级,以实现容错。这个在 GWA2 里改动相对简单,参照上面增加CDN的时候操作,如果感知到 CDN不可用时,可以清空其赋值即可将资源文件的请求切换到本地服务器上来。也即通常情况下说的所有CDN本击穿了。

GWA2PHP:
$cdnStaticPrefix=””; # failover
$viewdir = $cdnStaticPrefix.”/”.$viewdir;

GWA2Java:
//- +cdn, 12:34 2020-12-04
String cdnStaticPrefix = “”; # failover
viewdir = cdnStaticPrefix + “/” + viewdir;

5. 多源CDN及应用层CDN队列

显然,GWA2 可以在代码层实现多源CDN的集群式配置,我们可以在程序中定义 $cdnStatixPrefix 作为当前CDN分发网络的标志,可以可以同样地定义 N个不同的CDN网络,如 $cdnStaticPrefix2, $cdnStaticPrefix3… $cdnStaticPrefixN.

当有这么一个群组队列的CDN可以用时,可以使用随机算法或者权重算法,将请求分发给这个CDN池,从而实现更加可靠的内容分发。

当然,也可以加上一定的心跳检测装置,自动对下线失效的CDN做移除处理。同样地,基于心跳检测,将恢复正常的CDN网络加入到队列中来,从而实现网络自动化、智能化运行。

如上,完成 GWA2吉娃兔引入JsDelivr公用CDN的开发与配置.

 


-GWA2 吉娃兔 是”通用网络应用架构( General Web Application Architeture, https://ufqi.com/dev/gwa2/ )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、在线医疗、在线教育、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, online medical services, online teaching, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.


 

JSDelivr: A free CDN for Open Source

fast, reliable, and automated

serving ~ 94 billion requests / month
 
serving ~ 2990 TiB / month
 
around since 2012
 
Posted in -GWA2, 服务器运维, 编程技术, 计算机技术 | Tagged , , , , | 1 Comment

治大国若过小家——写写王朝兴衰更替背后的经济账

最近在读网红历史长篇文章《晚清沧海事》( 上下卷在线连载: https://ufqi.com/news/ulongpage.1008.html  ),在其中接近尾声的部分,有一个章节叫做《 晚清沧海事:制度落后就要挨打-117:下卷六十六:光复伊犁:晚清灭亡的实情》。这个章节里剖析了晚清灭亡的真实情况,从作者的观点,晚清政府未能对外抵御强敌,对内镇压反叛势力是根本原因之一。作为两个政治想象的另外一个,意图改革儒家思想也加速了其衰落,最终走向不得不面临的大清帝国崩盘的局面。

细究起来,晚清政府之所以未能在对日本等国的作战中取得胜利,主要原因之一是晚清在勉力镇压了内部反叛势力(太平天国军、捻军等)之后,经济上受到重创,国库见底。在接下来的拮据日子里,又要面临一个子掰两半花的局面,那就是晚清著名的 海防还是疆防的大辩论。这里的海防是大清帝国的海上防务,主要是针对同时明治维新崛起的日本和欧洲列强。而并不多见于历史的疆防,则是指西北的陕甘宁和新疆、西藏等地区的内乱和外敌。内乱是穆斯林持续不断的反叛,外地是土耳其、印度(英属)和俄国等。

总结就是晚清政府由于常年征战导致经济上连年负债,越没钱越弱,越弱越遭人欺负,越没钱,死循环。一个大国的治理,竟如同一个小家过日子一样,穷死。

古圣贤者老子在名篇《道德经》里著文“治大国若烹小鲜”。由于所言极其简略,加上时日久远,解读众说纷纭。比较主流的解释有两种,一种是治国不要折腾,寓意烹小鲜不能来回翻转。还有一种解法是说,小鲜不若大鱼,不能掐头去尾删减内脏,那就几乎不剩下啥了,要原样蒸煮。这种解法寓意治国要兼收并蓄,不删减,不增殖,顺其自然。

这里本人倾向于第二种解释,顺其自然。不过结合对此前的理解,稍加改动为“治大国若过小家”。看着一个泱泱大国,治理道理的背后,竟然与寻常百姓的一家一户过日子一样,都是围绕挣取几块钱,吃上一口饭。这个观点也在斯塔夫里阿诺斯(Leften Stavros Stavrianos)的《全球通史》里被提到,王朝循环的根本原因是经济管理的循环,而造成经济循环的原因,则是帝国开支超过税收。

这是读习经济学的第三篇心得体会写作,之前两篇分别是《写写1929年美国经济大萧条与2020年美国股市大跌》( https://ufqi.com/blog/us-1929-economic-crisis-2020-stock-shock/ )和《写写🏦存款利率贷款利率和负利率》( https://ufqi.com/blog/captial-rate-and-minus-rate/ )。

简而言之,一个大国的治理,与一个小家庭过日子一样的道理,也是开门七件事,柴米油盐酱醋茶,关门七件事,吃喝拉撒睡洗刮。其核心就是一个字,钱!没有一个大国是在国库充盈的时候被击垮的,而所有王朝被覆灭的时候,都是国库亏空的。宛如家境殷实的家庭不容易离散出问题,而贫贱夫妻百事哀。

Fig 1. 王朝兴衰更替背后的经济账

一个政权(政府)初始创立,开始“今儿起我话事”,都听我的安排,给我上税(如上图)。
如果是一个允许讲道理(民主自由)的政权,基本内部就不存在起义、反叛等事件,因为允许公开有礼有节的抗辩,自然会遵循所谓市场规律,自由发展。勤快的懂得钻营的人就会获得超过平均数的收入和财富,于是有资本利得的助力,人群有贫富分化,踩着马太效应进而形成垄断,而垄断是经济危机的伏笔。

于是,政府要警惕垄断,预防经济危机,当经济危机发生时,国库可能会亏空。为避免这种情况,政府要避免经济危机发生,也就是避免垄断,也就是避免过分的贫富差距极大化。当经济危机不可避免的发生时,需要采取一切可能的手段来救助经济。如果成功了,皆大欢喜,如果不能,在野党就会翻盘上台,政府被和平更替。还有一种情况比较危险是,隔壁老王的邻国这时候趁火打劫来入侵处于经济危机时候的国家。

相反地,如果一个政权(政府)是不允许讲道理(独裁专制)的,内部起义、反叛就不可避免了。内部干架的区别主要是大的反抗和小的反抗,镇压了的反叛和镇压不了的反叛。从设立开始话事的时候起,反对派就一直在积蓄力量,政府主要收入来源的税基就像一个有蚁穴的大坝一样,潜移默化的逐渐减少。此消彼长,纳税的减少,而吃税(吃财政)的人却是反方向逐年月的增长,国库从一开始有盈余到平衡,到不可逆转的出现亏空。

反对派无法通过讲道理来实现诉求,只好战场上刀把子说话,不可避免的,持续动荡,帝国疲于应付,财政日趋紧张。周遭环伺的隔壁老王的邻国这时候也会插上一杠子,一般会正面敲竹杠,或者正面敲竹杠叠加或明或暗地支持反对派的叛军。兴盛一时的帝国无可奈何地走向了内忧外患的地步,无论是攘外必先安内,还是颠倒过来,一个锅里吃饭,就那么多米,区别不大。

晚清政府既要努力镇压西北陕甘新疆西藏穆斯林的反叛,还要对付海上来袭的日本和欧洲列强,不是不能打,实在是没钱了,生生打没钱的。据说晚清政府军队组织从中原地带运送粮草往大西北打仗,起运30担粮食,终到1担粮食,其余29担粮食在来回途中被吃掉了。从这个角度理解,国民政府时候,蒋介石面临似乎也有类似的局面。

在这个不讲道理的政府来看,无非是镇压了上一个反叛军,然后迎接下一个反叛军。在这个无休止的循环中,如果某一次反叛军胜利了,政府就彻底完蛋,另一个新政府就此设立。
如果他还是一个不讲道理的政府,就再次开启那个反抗-镇压模式的无休止地狱模式。
如果他良心发现,转为允许讲道理的政府,那就进入与经济危机做斗争的娱乐模式。

隔壁老王式的邻国是一个烦人的存在。由于国与国之间没有所谓正义,只有所谓利益,而且是无羞耻、无底线的地盘之争,所以,一旦一个政府被刺探到其国库亏空,就想一个普通百姓家庭一样,如果穷的揭不开锅,那受人欺负几乎是必然的。如果这时候有被大户财阀看得上的东西,无论是人还是财物,往往都会被使用各种手段被掠走。

家庭如此,政府国家亦然。百姓穷居闹市无人问,国家也是弱国无外交。
治大国若过小家,手中有粮,心中不慌。这背后都是经济活动,起支配作用的是经济规律。

Posted in 社会生活 | Tagged , , , | Leave a comment

GWA2吉娃兔🐇Java中的文件上傳表單處理若干問題

在 GWA2Java 中處理文件上傳的HTML表單被稱爲是“客貨混裝”的HTTP請求處理。

文件上傳處理是HTTP Web開發中較爲特殊的應用,對開發者有一定的要求。無論是流行的PHP,Aspx或者JSP都需要一定的處理技巧。由於實在想不起來10多年前是如何赤手純代碼來處理客貨混裝的HTML文件上傳表單,這次還是詳細地記錄一次,以備再過些時日忘卻了而備查。

還有一層考慮是,在處理HTML的文件上傳表單時,需要考慮與 GWA2Java的融合,涉及到GWA2 的文件處理的核心模塊,因此也需要或者也是檢視GWA2架構設計的一次極好的機會。
對此前的 GWA2 Java項目的巡視,我們發現已經有一些項目涉及到文件上傳,但基本上多數是使用Ajax異步上次等,回避了“客貨混裝”模式,某個HTML表單只負責文件上傳,而另外一個表單再收集其他數據。

所以,這次要在 GWA2Java 中更好的整合進文件上傳,并且是客貨混裝模式——處理一個表單,裏面同時包括兩個字段:張三的姓名文字和張三的頭像圖片。

1. 瀏覽器客戶端 HTML表單中enctype

如果需要在瀏覽器客戶端的HTML表單中進行文件上傳,需要明確顯式地指定 Form元素的 enctype 屬性為 multipart/form-data 。

2. 服務器端接收處理文件上傳的第三方組件

基於 Apache Tomcat的 Java Web Server,進行服務器端的文件上傳處理,推薦使用的組件是 Apache commons-fileupload-1.4.jar , 一并的也要引入 Apache commons-io-2.7.jar。

3. HTTP Request.getParameter 失效

儅客戶端使用文件上傳的表單遞交數據時,Java Web Server中常規的 Servlet 對象 HTTPRequest的主要方法 request.getParameter 就失效。這也是普通程序無法處理客貨混裝的原因之一。

取而代之的,儅 enctype=multipart/form-data , 需要通過第三方組件獲取到相應的表單參數。
在 GWA2 中,其中的路由模塊嚴重依賴HTTP Request的參數,這時候,需要將主要路由參數放入Form的Action屬性中。
可以改進的另外一個方法是,通過引入 Apache commons-fileupload 的相關對象,便利 FormItems 對象,從而獲得表單中的常規非文件字段,文本文件字段的名稱和值。

遍歷FormItems獲得HTTP Request請求參數之後,再通過 request.setAttribute寫回到當前Request對象,如此即可巧妙地彌補 request.getParameter 失效的問題。
由於在 GWA2Java 中,獲取外部參數通常由 Wht.get 的方法進行,這個方法除了調用 request.getParameter 之外,還會進一步地的訪問 request.getAttribute , 從而實現了對 request.setAttribute 的訪問。再進一步地的 Wht.get 還會對訪問數據做一些基本的安全檢查。

樣例代碼:

ServletFileUpload sfileupld = new ServletFileUpload((new DiskFileItemFactory()));
formItems = sfileupld.parseRequest(request); // can only be parsed once!
if (formItems != null && formItems.size() > 0){
String iname, ivalue; byte[] bytes;
for (FileItem item : formItems){
// processes only fields that are common form fields
if (item.isFormField()){
bytes = item.getFieldName().getBytes(“ISO-8859-1”); // why 8859?
iname = new String(bytes, “UTF-8”);
bytes = item.getString().getBytes(“ISO-8859-1”);
ivalue = new String(bytes, “UTF-8”);
request.setAttribute(iname, ivalue);
//debug(“ctrl/item: iname:”+iname+”, ivalue:”+ivalue);
}
}
}

 

4. HTML表單上傳request 能且僅能被parse一次

上文中提到的獲取 FormItems 需要從 HTTP Request中提取,

List<FormItem> formItems = uploadInstance.parseRequest(request);

這裏的Request,只能被 parseRequest 執行一次,如果在同一次請求處理程序中,再次對這個 request 執行 parseRequest 時,就會返回異常為空的錯誤。
因此,儅我們需要在程序頂部通過便利 FormItems 設置 request.setAttribute 時,還需要保留 FormItems 作爲全局對象,在後面這裏處理實際上傳文件時使用,避免再次調用 parseRequest 產生爲空的錯誤異常。

5. 揮之不去的字符轉碼: 從 ISO-8859-1 到 UTF-8

從心裏上,我們是抗拒在代碼中進行字符集轉碼的,所以從一開始,我們在 GWA2Java 中進行了前後端統一全流程一貫地使用UTF-8字符集,從而避免在系統程序内做無謂的轉碼工作。(參考:-GWA2 Java版本的i18n/中文编码/乱码问题,https://ufqi.com/blog/gwa2-java-i18n/

偏偏這裏儅使用客貨混裝模式進行文件上傳時,通過parseRequest出來的 FormItem 其中的非ASCII字符的編碼是 ISO-8859-1 ,對於像 GWA2Java 這樣默認的 UTF-8 環境,字符集轉碼成爲迫不得已的事情。

6. 文件上傳處理方法的歸置

在 GWA2 的架構設計中,文件上傳功能,歸屬于文件模塊,引入系統的接口文件是 inc/FileA , 針對不同的文件系統,有不同的文件類來實現 inc/FileDirver , 如 默認的文件處理是 Linux 的 inc/FileSystem .

在歸屬上,這些 inc 目錄下的類及其方法是“大家閨秀”,一般不參與到具體業務處理程序的,只能通過統一界面接口 inc/WebApp 來調用。因此理想的是調用文件上傳的邏輯流程大致為:

ctrl/a.jsp –> mod/ModA –> inc/WebApp –> inc/FileA –> inc/FileSystem .

由於文件上傳,屬於非常規的“操作”需求,另外一種非標準的捷徑是,在 mod/ModA 中直接實例化 inc/FileSystem , 從而便利地觸發對 upload 方法的運用。但這只針對具體的項目可行,且不需要可移植性。比如如果宿主系統不是 Linux, 那就不能實例化 inc/FileSystem , 相應地可能需要實例化 inc/WindowsFileSystem 來處理宿主環境是 Windows 的文件上傳。

7. 有進有出,文件刪除的操作

在此之前,核心接口類 inc/WebApp 中定義了 readObject/writeObject 用來讀寫非數據庫源的數據。其中 inc/FileA 中相應地定義了 read/write 方法,只是還沒有對應的刪除方法 rm 的實現。

接著這個機會,我們歸置並實現了 inc/FileA, inc/FileDriver 和 inc/FileSystem 三個類的 rm 方法,同時改造 inc/WebApp.rmBy 方法,將上述方法進行對接。

inc/WebApp.rmBy(“file:Path_To_File”) –> inc/FileA.rm –> inc/FileSystem.rm .

 GWA2Java, GWA2 就是這樣通過一個又一個項目實踐,不斷豐富完善,日益健壯强大,儅融合和沉澱足夠多的智慧和精華,一定能取得更大的成就。我們在 UfqiWork 有福工坊 ( https://ufqi.com/work/ )上首先實現了 GWA2Java 處理文件上傳的客貨混裝模式。


-GWA2 吉娃兔 是”通用网络应用架构( General Web Application Architeture, https://ufqi.com/dev/gwa2/ )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、在线医疗、在线教育、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, online medical services, online teaching, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.


ufqiwork-logo

有福工坊UfqiWork 是一个在线服务交易平台。( https://ufqi.com/work/ )
有福工坊提供在线分类服务信息,致力于在线撮合服务交易的买方和卖方,并为买方、卖方提供“行准”服务,居间担保服务交易。行准服务的提供方为居间交易的第三方。有福工坊的服务交易平台为整个服务交易流程的第四方。

-R/32ST

https://ufqi.com/blog/gwa2-java-file-upload-issues/

Posted in -GWA2, -Hanjst/-汉吉斯特, 服务器运维, 编程技术, 计算机技术 | Tagged , , , , | Leave a comment

A practical analysis on $hadow$ocks

Things are getting worse even for an ordinary computer programmer to bypass the Internet walls in some countries or districts. There are quite a lot of techniques involved in making a working solution to get through the walls safely to smoothly.

Knowledge on TCP/IP is an entry for this exam. Deep understanding of the walls is an essential point and other requirements are data communications, data security, network security and data encryption.

Besides those above, programmers are also being asked what application is being deployed over the wall. The most-deployed application is HTTP, and therefore they need to understand more than usual on its protocols. Multiple operating systems and programming languages could help programmers easily get things done.

What’s more, for both sides, the battles of blocking and anti-blocking are always continually being evolved  and they just look like spear vs. shield. One working technique may fail tomorrow if it has been acquired by another side. 

Here is a workflow based on what we have learnt from $hadow$ocks, one of the most-starred repositories on GitHub.

Work flow:

–> packets plain sent (1)
–> $hadow$ocks-windows-client(2) –> obfs-local(3)
–> packets wrapped over Internet
–> obfs-server(4) –> $hadow$ocks-libev-server(5)
–> packets REQUEST & RESPONSE (6)
–> $hadow$ocks-libev-server(7) –> obfs-server(8)
–> packets wrapped over Internet
–> obfs-local(9) –> $hadow$ocks-windows-client(10)
–> packets plain recv (11)


https://ufqi.com/blog/analysis-on-hadowocks-202008/

-R/A2SP

Posted in 服务器运维, 编程技术, 计算机技术 | Tagged , , | 1 Comment

GWA2吉娃兔🐇升級基於事件驅動的緩存處理模塊

時間過得飛快,距離上次升級改進GWA2吉娃兔🐇已經又三個月過去了。GWA2吉娃兔🐇升级模板引擎子系统( https://ufqi.com/blog/gwa2-updt-template-engine/ )。這期間,GWA2一直在進行細微改進升級,這次記錄的是改進較大的一個地方,對内置Built-in的緩存模塊進行了再次優化。其中的細節和思考值得分享,備忘於此。

GWA2吉娃兔🐇自相應體系創建以來,花了大量的時間和精力持續不斷地推進創建“更好的下一個版本”。關於緩存相關的改進,有記錄可以見于“GWA2-Java built-in cache with connection pool design/带连接池的缓存流程设计( https://ufqi.com/blog/gwa2-java-built-in-cache-with-pool-flowchat/ )”、“-GWA2 更新缓存调用built-in cache方法( https://ufqi.com/blog/gwa2-built-in-cache/ )”。



圖1. GWA2吉娃兔内置緩存機制

這些努力都是希望基於GWA2的應用系統跑得快些,再快些!待到進行到某種極緻的狀態時,往往面臨的是某種權衡和取捨。比如緩存功能,如果訪問速度更快,則預期的緩存時間越長,更新頻次越低。而對於某些改動,又需要立即更新,這就需要做出某種平衡和不同優先級的考慮。有些系統可以允許緩存一定時間再將改動提到到前端系統,有些系統則對實時性要求較高,不允許有片刻的緩存。

這樣總體考慮,大致是三種情況:1)全部用緩存,數據更新及時性次級考慮,2)全部不用緩存數據即時更新,系統效能次級考慮,3)部分查詢用緩存,平衡系統效能和數據及時性。
gMIS吉密斯 ( https://ufqi.com/dev/gmis/ ) 作爲 GWA2吉娃兔的一個應用實例,就是使用3)方式,部分查詢使用緩存,另外一部分完全不使用緩存,這樣在系統效能和數據及時性之間做tradeoff. 比如gMIS管理所訪問的當前數據表不使用緩存,數據及時性得到保證,而一些公共菜單、權限檢查等則使用了緩存,更新無法立即生效,需等待一個緩存失效的周期。

有沒有一種機制將這種實時性區分開來(第4種情況:全部使用緩存而又能保證數據的及時性, 既….又….?)?儅允許緩存時,使用默認的緩存機制,將數據緩存起來,以此來提升系統響應速度;儅需要實時性時,則立即進行相關數據的更新。經過一番探索,我們采用事件驅動機制,增加了對這些設想的工程實現。其大致思路時,儅用戶發起對系統的寫入、更新操作時,在更新系統對象狀態時,即刻觸發對緩存的更新,從而實現了按需更新想要緩存的目標,讓緩存數據與系統對象真實狀態保持高度一致性、同步性。這些改進包括如下兩個地方。

1. 改進頂級類 inc/WebApp,rmBy 方法的實現

改造之前,inc/WebApp.rmBy 的操作只支持針對數據庫接口的刪除操作。這次改進之後,inc/WebApp.rmBy 將支持形如 “cache:keyString” 的參數定義,儅接收到這樣的參數時,觸發對相應的緩存的刪除。

緩存刪除操作通過 inc/Cachea 接管后效用相應的緩存驅動,進而實現對緩存的刪除、更新操作。也即,通過改進 inc/WebApp.rmBy , 調用 inc/WebApp.writeObject , 通過寫入一個沒有緩存值的對象來發起對當前緩存的更新。這一流程中數據的流轉大致如下。

…. –> mod/ObjectInstance.setBy(execBy) –> inc/WebApp.rmBy
–> inc/WebApp.writeObject –> inc/Cachea.rm
–> inc/Memcached.rm –> …
圖2. GWA2 緩存刪除操作

相應地,不但可以在 inc/WebApp 中通過 rmBy(“cache:keyString”) 的形式調用針對緩存的清理,也可以在任何繼承或實現了 inc/WebApp 的類中調用該方法,實現對緩存的更精準的控制。比如通過圖2. 實現了對單條數據記錄字段級的更新時同步更新緩存的操作,如果針對一個具有多條數據集的操作,該如何同步進行緩存更新操作?

顯然地,需要在控制器中,顯示地調用 mod/ObjectInstance.rmBy(“cache:keyString”) 的方法來清空所涉及到的緩存對象。這是超出内置緩存的範疇,需要具體問題具體分析進行,尤其是每個cache的key不同時,如果有多條cache需求更新,還需要多次調用 rmBy(“cache:anotherKeyString”) .

2. 優化更新操作時觸發緩存操作

在此之前,按圖1.的標志,内置緩存只在數據對象讀取時發生作用,也即在 inc/WebApp.getBy/execBy 時生效,對於寫入、更新操作 inc/WebApp.setBy/execBy 時,無需調用相應的緩存功能模塊,因爲寫入數據無需進行緩存。

帶上開篇提到的問題,儅我們需要在寫入、更新操作時進行緩存更新時,采用事件驅動模式進行相應操作時,需要在寫入、更新操作 inc/WebApp.setBy/execBy 考慮一下緩存。只不過這時候考慮緩存,不是寫入緩存,而是也同步“更新緩存”。具體的改進包括如下兩項。

2.1. 改進 inc/WebApp.setBy

inc/WebApp.setBy 此前的方法中,支持第三個參數 HashMap args 形式,其主要功能是考慮需要寫入非數據庫時的需求。比如寫入緩存系統,寫入文件系統等,儅有這些發生時,需求被進一步地前傳給 inc/writeObject .

接著這個可擴展的機制,我們可以在寫入數據庫時,也通過 args 帶入需要更新的緩存keyString, 儅完成了相應的寫入數據庫的操作時,相應地發起對緩存的更新操作。其流程與圖2.描述相同。

2.2. 改進 inc/WebApp.execBy 

inc/WebApp.execBy 的情況稍微複雜一些。在目前的設計中,inc/WebApp.execBy 是為了滿足一些特定的SQL查詢語句,儅我們無法通過 getBy/setBy 實現目標SQL查詢時,execBy 就被排上用場。他甚至可以替代 getBy/setBy ( 在某些GWA2的新手,或者簡單應用中,開發者甚至只用這一種方法即可完成與數據庫的全部讀寫操作 ) ,因而需要考慮 execBy 的讀取和寫入兩種情況。

儅 execBy 執行讀取操作時,其第三個參數 HashMap args 本身就帶有 cache keyString 的參數,意在用於儅讀取成功時,通過這個cache keyString 將查詢結果緩存起來,下次再有類似查詢時,優先主動使用緩存數據。這也是 圖1. 我們的内置緩存的運行機制。

現在我們需要更多地考慮一層,儅 execBy 執行寫入、更新操作時,儅完成相應的操作后,需要進一步地考察 args 中的 cache keyString 參數,如果給定了相應的cache keyString,則我們認爲這是需要同步觸發更新緩存的操作,於是就進一步地呼叫 inc/WebApp.rm(“cache:keyString”) , 同步完成對緩存的更新。

只是,這裏如果是通過 execBy 發起對非數據庫的操作呢? 比如,通過 execBy 發起對 緩存系統,文件系統的操作呢? 目前還沒有這方面的需求,不過的確是需要再考慮的事情。@todo .


-GWA2 吉娃兔 是”通用网络应用架构( General Web Application Architeture, https://ufqi.com/dev/gwa2/ )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、在线医疗、在线教育、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, online medical services, online teaching, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.


GWA2吉娃兔 基於事件驅動的緩存處理機制已經在 有福工坊UfqiWork ( https://ufqi.com/work/ )上得到部署應用。

ufqiwork-logo
有福工坊UfqiWork 是一个在线服务交易平台。
有福工坊提供在线分类服务信息,致力于在线撮合服务交易的买方和卖方,并为买方、卖方提供“行准”服务,居间担保服务交易。行准服务的提供方为居间交易的第三方。有福工坊的服务交易平台为整个服务交易流程的第四方。

-R/B2SU
http://ufqi.com/blog/gwa2-updt-build-in-cache/

Posted in -GWA2, 服务器运维, 编程技术, 计算机技术 | Tagged , , , | Leave a comment

Graph圖的相似性計算的極值問題

數據集的相似性計算,其應用十分廣汎,在現有的各類人工智能的底層算法中,大多數都是基於概率(可能性)的近似計算,然後取最大可能性的近似值。參考 理解计算:从根号2到AlphaGo ——第1季 从根号谈起 ( https://ufqi.com/news/ulongpage.191.html )。 另外使用神經網絡可以模擬任意曲綫函數,A visual proof that neural nets can compute any function ( http://neuralnetworksanddeeplearning.com/chap4.html ) 。
甚至,在早期的搜索引擎的計算中,如果計算兩個段落或者兩篇文章的相似性,也有使用基於圖的算法,將每篇文章視爲一個 graph,然後使用下面的圖的相似性的算法來計算兩者之間的相似性。

從一堆圖片中找到貓的照片是類似算法,車牌識別是這種算法,人臉識別、語音識別等都是類似的應用,神經網絡、深度學習等,莫不如是。人工智能AI之外,我們看到各種基於興趣的商品推薦,在綫廣告的智能匹配等等,都有這些算法的身影。
我們曾經開展過在綫廣告點擊率預測模型,其中運用到KNN算法,其核心就用到了 Euclidean Distance的計算 ( https://www.researchgate.net/publication/330742123_A_practical_study_on_imbalanced_data_re-sampling_for_conversion_rate_of_online_advertising ) 。

Neo4j 關於圖(Graph)的相似性計算(Similarity algorithm)提供了若干算法。
https://neo4j.com/docs/graph-data-science/current/alpha-algorithms/

這些算法都有詳細的解釋説明,樣例代碼等,這裏還有對幾種不同算法的對比分析(參考:余弦距离、欧氏距离和杰卡德相似性度量的对比分析 , https://www.jianshu.com/p/c4bbad87f873 )。 其中應用較多的是 餘弦距離和歐氏距離。

cosine similarity

Cosine Similarity/餘弦距離計算公式

euclidean

Euclidean Distance/歐氏距離計算公式

在 Neo4j 的文檔中,對餘弦距離和歐氏距離的應用場景都有差不多的描述:

我们可以使用欧几里德距离算法来计算两个事物之间的相似性。然后我们可以使用计算出的相似度作为推荐查询的一部分。例如,根据用户的偏好来获得电影推荐,这些用户所給出的评分与您看过的其他电影的评分相似。
We can use the Cosine Similarity algorithm to work out the similarity between two things. We might then use the computed similarity as part of a recommendation query. For example, to get movie recommendations based on the preferences of users who have given similar ratings to other movies that you’ve seen.

Neo4j是一個開源的NoSQL的原生圖數據庫。Neo4j is an open-source, NoSQL, native graph database that provides an ACID-compliant transactional backend for your applications.
圖數據庫存儲的數據單位是節點(Node)和關係(Relations)。
通常,圖用一組數據表示,如 g1(a0, a1, a2, a3, ….), g2(b0, b1, b2, b3, ….),極值情況下,如 g1(a0), g2(b0) 如何比較和計算相似性?這是本文試圖探討的要點。我們還結合研發中的 ufqiwork-logo有福工坊UfqiWork ( https://ufqi.com/work ) 的實際應用案例對所提議的算法進行了驗證,取得了預期的效果。

將極值比如 g1(10) 和 g(100) 進行計算時,幾乎每個算法都會返回極其不相似的結果值: -1 .

如果我們想進一步地探討, g1(10) 和 g2(100) 的不相似值, 與 g2(100) 和 g3(1000) 的不相似值,有多少程度上的不同呢? 顯然上面的算法在都返回不相似的極值 -1 時,兩者的不相似是一樣的,而真實情況真的是一樣嗎?如果不一樣,怎麽來描述這種不相似的差異?

簡單而直接的做法是考察兩個數值之間的減法差值或除法商值,差值或商值的大小決定了兩個數據的差異性,正比例關係。
比如,10~100的差值是90,商值是10, 100~1000的差值是900,商值是10.

如果我們要定義或者套用一下相似性,10~100的相似性用數值表達是多少? 100~1000的相似性用數值表達是多少?如果比較差值的話,後者的差別大於前者,如果比較商值的話,前者與後者相等。從語義上來解讀,顯然使用商值較符合預期,業績兩者的差異是10倍。

使用絕對商值10來描述相似性顯然不太合適,爲了便於表述為相似性,我們還需要對其進行歸一化處理。為方便描述兩個數值的商值,我們對商值取log10對數,這樣大幅降低絕對值的範圍並提供更大的曲綫表述空間,其絕對值的細微變化能夠映射到相應的對數值上。


對數log10(x)的坐標曲綫

嘗試進行歸一化(Normalization)處理時,需要設定區間閾值。如果兩個數相等,其商值為1,取對數log10(1)時, 得到值為 0,可以認爲儅兩個數的如上這麽計算過程之後值為0時,這兩個數的相似性是 100%。

那麽,多大是不相似呢?如果做歸一化或者百分比,我們需要確定、劃定一個“不相似值”的標準,無論是取商值,還是再對商值取對數,需要一個明確而具體的數值來表示或界定完全不相似。這個數值可能最終需要靠經驗獲得,也與要考察的數據可能的取值範圍有關,比如考察人的身高時,相差一倍就有種十萬八千裏的感覺;而考察星系,十萬八千里也可能只是一倍的表述。因此,這個用以界定“不相似”的閾值 k 應該是根據經驗和應用場景而定。

於是,我們就可以寫出我們用於求值某兩個任意數的相似性值,設若k為完全不相似,則某兩個數的相似性表述區間為 [0, k] , 針對這個取值範圍,再進行歸一化處理則相對容易。最終,我們擬寫了下面這個求取兩個任意數值的相似性的函數表達式:

F(n1, n2, k) = normalize{ min[k,  log10[ max(n1, n2)/min(n1, n2)] ] };

其中n1, n2為待求取相似性的兩個數值, k為經驗常數極值(表示完全不相似值)。
其計算過程可以描述爲:
1) 比較n1, n2的大小;
2) 求取n1, n2較大值除以較小值的商;
3) 對商值取log10對數;
4) 比較對數值與常熟k的大小,如果商值的對數值大於k,取k值;
5) 對前一步數值做歸一化處理,得到預期值在 [0, 1] 之間.

由此,我們獲知,儅兩個數的商值一樣時,其相似性是一樣的。因此10~100 和 100~1000的相似性是一樣的。對商值做進一步的處理是爲了表述和運算方便。類似的算法我們在 ufqiwork-logo有福工坊UfqiWork ( https://ufqi.com/work ) 進行試用,取得了一定的預期效果。

圖的極值問題只是相似性問題中的特例,同時這些所謂的極值也是相對的,儅g1(a1), g2(a2), g3(a3)…. 等多個極值組合為一個大的圖G(a1, a2, a3….)時,其與另外一個大G(b1, b2, b3…)相比較計算相似性時,又回歸到到文檔看到提到的數據集相似性問題計算了。

 


ufqiwork-logo
UfqiWork 有福工坊 服務交易所

有福工坊UfqiWork 是一个在线服务交易平台。
有福工坊提供在线分类服务信息,致力于在线撮合服务交易的买方和卖方,并为买方、卖方提供“行准”服务,居间担保服务交易。行准服务的提供方为居间交易的第三方。有福工坊的服务交易平台为整个服务交易流程的第四方。

线上签约,线下交割。有福工坊整合服务交易的 信息流和 资金流,在线承载买卖双方的需求供给信息匹配、交易撮合,在线承担交易双方的资金拨付、担保。服务交易的 标的物在线下实施、交割。

有福工坊服务交易平台服务于提供居间交易的“行准”,通过行准服务于服务交易的买卖双方。交易标的物与其他电子商务交易不同的是其非标准性,如房屋、工作/职业、家政/维保、汽车、医疗、教育、金融、出行、时尚等等。相应地行准为房产中介,猎头中介,商品导购、推荐、带货等。
所不同于现有分类市场的地方在于:站在买方立场代表买方利益的居间服务;买方有定价权,居间服务报价。相应地,卖方也可以使用定价权雇佣代表卖方立场和利益的居间服务。

有福工坊UfqiWork 圖標中 “有” 的紅色高亮部分,既像是“房屋”(住房),也像是“凳子”(工作),寓意 有福工坊UfqiWork 致力於為用戶提供住房、工作、家政等各類信息匹配及撮合交易服務。

Posted in 计算机技术 | Tagged , , , , , | 2 Comments

GTAjax升級:一劍🗡磨十年改進JavaScript表單遞交瀏覽器異常等

2020年7月以來,持續對 UfqiLong 有福常在 進行升級改進。
改進過程中遇到之前不曾見的問題,在使用 GTAjax進行異步遞交 有福常在UfqiLog 的文章内容時,有隨機性地出現遞交失敗。進一步的跟蹤發現,儅點擊遞交后,GTAjax接管了表單遞交動作並觸發了進度顯示並進行讀秒操作。

但是,詭異的是,GTAjax在後臺並未真的將遞交發送給服務器端後臺。於是我們決定對 GTAjax開啓 debug 模式,進行深入分析,爲何之前不曾有這樣的問題,爲何問題會是隨機性出現,而又爲何,儅第一次遞交失敗后,第二次原樣操作,卻能成功?

帶著這些問題,我們準備深入分析一下。開啓 GTAjax的debug模式相對簡單,在 運行時參數裏:

var myGTAjax = new GTAjax();
myGTAjax.set(‘isdebug’, true);

這樣即可打開 GTAjax 的過程數據輸出,從而觀測到整個通訊過程。通過分析debug日志,問題很快鎖定到 postForm.submit() 這個節點上。
也即,在使用 ForceFrame 模式進行表單遞交時,依賴 JavaScript的 HTMLFormElement.submit() 這個方法進行最終的數據遞交。

這個是 W3C、HTML DOM和 JavaScript等標準組織封裝好的方法,無法進一步地往下拆解。問題就轉化為爲何 submit() 遞交失敗呢?通過進一步地分析,我們發現在 GTAjax 接管真正的 HTML Form表單時,通常會通過 _DFM_F 方法將 onsubmit 返回一個 false,從而阻止正常的遞交,然後GTAjax 再開展一系列的準備動作之後,再遞交 postForm.submit() 進行遞交。

詭異的地方在於,Google Chrome、MS Edge等瀏覽器,之前即便對HTML Form設置了 _DFM_F, 調用 postForm.submit() 時並不會受影響,而且儅 GTAjax 通過 _RGT 方法進行初始化設置之後再次調用 _DFM_F ,然後再次 postForm.submit() 時,卻是可以通行過去,如預期地進行與服務器端的通信。

我們推測,可能是近期的Google Chrome和MS Edge瀏覽器的升級,增加了對HTML Form遞交前的JavaScript等狀態檢查,所以如果發現某個Form的onsubmit 綁定了 return false的動作,就自動終止當前的操作;相反,則繼續如常。 

定位到問題,並經過粗略的原因分析之後,解決問題的辦法也就隨之而來。如果當前被執行的HTML Form被設置了 onsubmit 的檢查,則需要對已經設置的 onsubmit 進行重寫,使之能夠覆蓋之前的設置,尤其是之前 return false 的設置,以使得後續的Form遞交操作能夠順利進行。 改進主要集中在 _SUB 這個内部調用的子函數上。

在執行postForm.submit() 之前,對當前 postForm的onsubmit 進行檢查。

//postForm.submit(); // maybe fail due to this._DFM_F . 10:42 2020-07-04
if(postForm.onsubmit == null){
    postForm.submit();
    GTAj._DBG(GTAj.vA[‘ib’], ‘this._SUB’, ‘Sync form:        [‘+postForm.name+’] is being submitted.’);
}
else{
    GTAj.currentPostFormId = postForm.name!=” ?     postForm.name : postForm.id;
    postForm.onsubmit = (function(){
        var myTimerId = window.setTimeout(function(formId){
    document.getElementById(GTAj.currentPostFormId).submit();
GTAj._DBG(GTAj.vA[‘ib’], ‘this._SUB’, ‘Async form:[‘+GTAj.currentPostFormId+’] is being submitted.’);
}, 10); //- 0.01 sec
return true;
})();
}

如果當前被執行的 postForm的onsubmit 沒有被設置過,則繼續使用之前的邏輯,直接執行 postForm.submit();

如果當前被執行的 postForm的onsubmit已經被設置過,則需要重寫onsubmit的綁定與賦值操作。經過多次實驗,我采取了JavaScript anonymous function的方式,重新對當前postForm的onsubmit進行賦值操作。初始我們將一個匿名函數賦值給當前的 postForm, 形如:

postForm.onsubmit = function(){ return true; }

在我們的實測過程中,這一匿名函數,在不同應用場景和不同的瀏覽器中,仍有一定的隨機性出現匿名函數不被執行的情況。為保全起見,我們進一步地改進這個匿名函數,不但定義了匿名函數同時隨後執行這個你們函數,將返回值賦給 postForm.onsubmit .

在匿名函數體外,我們還通過全局變量 GTAj,將當前被執行的postForm的相關信息帶入匿名函數内;在匿名函數體内,我們設定了一個隨後立即執行的新的匿名函數,這第二個内嵌的匿名函數將完成這個表單的真實遞交動作。執行的時序變成: …. 1)定義一個匿名函數A—- 2)在匿名函數A内定義另一個異步的匿名函數B—- 3)執行這個匿名函數A —- 4)將匿名函數A的返回值true賦值給 postForm.onsubmit —- 5)時間觸發執行匿名函數B —– 6)實際執行postForm.submit() 操作 —– 7)監測服務器返回值進度….

改進后,分別在 Google Chrome,MS Edge 和 Mozilla Firefox 多個瀏覽器的不同應用場景下實測,均取得預期效果,不再發生或者隨機性發生,遞交Form未被執行的情況,故障問題得到順利解決。完整程序源代碼可以在 GTAjax 主頁( https://ufqi.com/dev/gtajax/ )和 GitHub上查詢(wadelau/GTAjax)。

這可能是軟件更新史上間隔最長的一次更新,GTAjax的官網主頁記錄記錄的上次更新時間為 2011-07, 距今已經九年過去了。著實令整個軟件作者也感到時光飛逝,一方面感慨時間過得太快,同時也對 GTAjax 歷時十多年,還能夠堅强、頑强地服務于業務系統的旺盛生命力感到一陣驚喜。

這不就是那種“Best as Air(好到無形)”極好的案例嗎? 幾乎每個工作日打開的基於 gMIS 吉密斯系統,其中都有 GTAjax 工作的身影,而他總是能夠不負囑托,完成每一次基於 GTAjax 的HTTP請求。

實際上,2011年以來,GTAjax 也做過小幅的升級改進和Bug修復,根據軟件源代碼中的更新標記,至少有如下幾次。

gtajax logo

* GTAjax.js
* @abstract: General-Targeted Ajax
* @author: wadelau@hotmail.com,wadelau@gmail.com
* @since: 2006-2-17 14:04
* @code: 5.7 // a.bc , funcs added b+, errs updated c+
* @NOTICE: DO NOT USE THIS COMMERICALLY WITHOUT AUTHOR’S PAPER AUTHORIZATION
* @update: Tue Feb 1 20:47:03 GMT 2011 

* Wed Jan 26 17:31:33 GMT 2011
* Wed Jul 20 08:08:09 BST 2011
* Fri Mar 16 16:36:52 CST 2012
* 12:15 Friday, February 20, 2015
* Sun Jan 24 12:56:43 CST 2016
* Fri May 25 08:51:23 CST 2018, code format refine and cA.sort bugfix
* Wed Oct 31 21:57:26 CST 2018, +form Name validate
* 11:06 Friday, August 16, 2019, imprvs with form validate
* 11:55 2020-07-04, bugfix for submit fail with forceFrame.

GTAjax 初創于 2006年2月,距今已經有 15年的歷史了。對於日新月異的軟件及互聯網行業來説,這差不多是古董級的軟件了。然而,基於開放標準和成熟技術棧,15年后,GTAjax依然穩定運行和應用在各種Web軟件中,這不能不説是相當成功的案例。

可以設想和對比的是,在應用層軟件,有有多少能使用15年之久?不要說15年,基於私有類庫和標準而開發的軟件,可能5年、10年之後已經難以覓得蹤跡,GTAjax 伴隨 gMIS 吉密斯 等軟件能夠一直運行到現在,並繼續運行到下一個5年,10年,是一件值得慶賀的事情。

軟件的生命力或者生存周期有多久?需要多久? 摩爾定律說硬件計算速度每18個月翻倍,軟件是否也只能用18個月要改版、升級換掉,甚至是完全推導重建?

實際上,GTAjax 生存的越久,越有可能遇到“趕不上趟”的情況,畢竟技術的發展與進步,日新月異,每隔3-5年幾乎就是天翻地覆的改變。GTAjax能夠堅持其可用、好用、能用達15年之久,應該說算是某種“成功”。

幾乎同時期的很多軟件都已經銷聲匿跡了。也可以設想,如果不是使用的開放的HTML、CSS和JavaScript等標準,而是使用某一家公司的某項私有技術,其情況可能就完全無法預料,更誑論與時俱進、歷久彌新了。縱向地時間跨度看,要保護和珍視一個軟件,盡可能延遲其生命周期,保持旺盛生命力,唯一可取的方式就是使用開放的技術與標準,構建面嚮未來的軟件。

從這一方面來説,基於WEB的應用軟件已經完勝了基於某個公司或者平臺的“本地應用”。10年前,差不多是WEB軟件真大行其道的時候,以美國Apple公司的Appstore反其道而用之,强推基於其自有的平臺軟件(App),構築强大的軟件壁壘,同時引導、脅迫無數軟件開發者不斷的爲其開發軟件(App),短則數月,長則數十月,App的快速更迭,也意味著大量的新寫成的代碼,像曇花一現一般消失了。

當然,也有及其少數的本地應用App頑强地頻繁地更新升級穿越了10年以上的歲月時空,如游戲魔獸世界WoW,即時通信軟件騰訊QQ等。這其中也包括,Web軟件賴以運行的網絡瀏覽器,如MS IE,Mozilla Firefox,Google Chrome,Apple Safari,Opera等。

在人民網工作期間,儅其實我們用的基於WEB的内部辦公系統(OA)相當有些年份(5-6年?),當時覺得,爲何不升級采用新技術? 甚至是再一個5-6年之後(10多年前),這個OA系統依然在運行中。現在想來,這是一筆極大的財富,因爲軟件的本身的技術棧是公開的標準,沒有很快地被業界全部抛棄,所以企事業單位的投資,得以延用至今繼續發揮作用。

當然,也不是說公開、開發的技術標準就止步不前,相反,公開、開放、開源的技術也在不斷的改進升級,只是由於影響巨大,各方需要多輪磋商,考慮各種因素,相對於一家公司的一項技術,其進度必然是緩慢的,當然也是理性而鑒定的。

比如 GTAjax 在開發計劃中,就規劃了 GTAjax-6.x 版本,主要考慮外部因素如下:

* 12:15 Friday, February 20, 2015
* 6.x Bears
HTML 5
ECMAScript 5, 6
HTTP/2 and Event-driven,
highly-cached,
code style of high-performance and readability
* in mind

尤其是其中的 HTML5,JavaScript 6 和 HTTP2 這些是在業界公開討論多年的技術標準,日益成熟,在新應用部署時會加快采用。相信在不久的將來,GTAjax-6.x 就緒時,能夠充分利用這些新技術特徵,在兼容之前的前提下,繼續為互聯網社區做出新的貢獻,下一個 15年,30年,50年。

與之相關 GTAjax更新Blog有:1)gMIS吉密斯更新Workflow工作流、FileMgr文件柜及GTAjax等模块( https://ufqi.com/blog/gmis-workflow-filemgr-gtajax/ ),2)-gMIS, -GWA2, -GTAjax 一并更新 ( https://ufqi.com/blog/gmis-gwa2-gtajax-update/ )。

世界仍不平靜,新冠肺炎疫情仍在傳播,愿軟件開發者多開發些生命周期更長的軟件,為世界和平貢獻智慧和力量,不要讓軟件成爲快消品, 而是要讓軟件成爲耐用品、藝術品。

-R/M2SR
https://ufqi.com/blog/gtajax-updt-form-submit-202007

Posted in -GTAjax, 编程技术, 计算机技术 | Tagged , , | 1 Comment

勞動的振興一家親

許久沒有寫家長里短的生活片段,說工作太忙,或者因爲新冠肺炎疫情都是不準確的。根本原因是在某種壓力之下,缺乏了對生活的感悟和思考,觀察和體會。真如同現在忽而要寫寫我們的生活剪影一樣,是有感而發,有所觸動,希望能言之有物,說説我們勤勞而辛勤工作的片段。

家住兩室兩廳,初裝修時,被改成三室一廳,兩個臥房,一個留作書房+鋼琴。四口人,如果岳父母來的話,是6口人,難免有些擁擠,通常每個房價要睡三口人。所以我們想把次臥的兩張板床換做一套上下床,不至於擁擠不堪。起初打算買新的,考慮到木料的,新的有味道,加上我們都一貫勤儉節約,就想著尋覓一個二手的上下鋪木床。妻子就在阿里鹹魚上尋找。這算是背景。

經過一陣子觀察,終於訂了一套附近小區的上下鋪木床,需要我們自己去拆卸了,搬運回來,再組裝起來。這個故事就是要記錄我們一家幾口在這個活動中的積極配合、辛勤勞作的過程。

2020年6月17日,是農曆閏四月的一個大熱天,大概有36度左右。我們在上午工作、學習之後,下午15:30按約定去賣方家裏拆卸床鋪。拆卸難度比預期的大,拆卸過程也比預期的長。Yoyo和我一道前往,個頭像個成年人一樣的大孩子,在與我配合的時候,一點不差。從擰卸螺絲、往外樓下搬運木板、床架,幹得很認真,很勤快,也很辛苦。大家都大汗淋淋的。只是暫時還沒有水喝,我們需要忙了大約一小時之後,待拆卸、搬運、裝車,然後運到家裏樓下、卸貨下車之後才能回去喝水。

這期間有個細節頗為意外。Yoyo搬運床板時,手指被床板的木刺兒刺破。在行動前,我預料會有這樣的事情發生,所以出門前我備了手套,並叮囑Yoyo也帶手套。顯然,YOyo沒儅個事,也沒戴手套就上手幹活了。木刺兒很鋒利,穿刺了Yoyo食指的表皮,從另一側穿出。我看著都覺得疼得厲害,她居然還開玩笑說,木刺兒刺穿了表皮、真皮和小部分組織細胞等等,然後將餘留在皮膚裏的木刺拔出。我趕緊制止了她的任務,讓她趕緊清洗,並將我的手套給她,囑咐她保護好手指,回去后再消毒、包紥處理等。

這些發生時,我忽然覺得Yoyo這孩子長大了,有能力處理一些突發情況,她對疼痛的耐受,超乎我的想象,即便受傷了,仍然繼續上上下下地幫我搬運完所有的木料,然後我隨著出發,她再自行騎電動車返回。

作爲父親,我既爲Yoyo的勇敢而欣慰,也有點擔憂,她這種超乎異常的鎮靜與堅强,會不會太狠了點?

貨到之後,Yoyo也前後脚回來,還好!我隨即囑咐她回去喝水、消毒包紥手指。另外讓她叫Hanu下來幫我搬運東西到樓上去。我連忙從車上卸貨,在單元門口堆放了一地。

不久,Hanu就樓裏冲出來,擼起袖子就開始搬運木料。我讓他擔心木刺兒,回去穿長袖衣服,撿自己能搬得動的木料往回搬。Hanu幹起活來,也很積極主動,一趟一趟,樓上樓下,和Yoyo,我,三人穿插著不停地往返,不一會,就搬木料從單元門口悉數運到了家裏來。僅僅多了Hanu一雙手,我忽然覺得比從賣方樓上運到樓下快了很多!

說易行難,待到我們將木料運到家裏之後,三日幾乎都累的不想動了,我們決定稍事休息,然後再進行組裝。

由於拆卸的時候進行的匆忙,沒有拍照留存樣子,我只好凴印象,一點一點地回想某個部件該在什麽部位,組裝的時候先組裝什麽再組裝什麽的先後順序等。而且在組裝之前,我們需要把原來室内的物件再歸置一下,在Hanu和Yoyo的幫助下,事情一一有序進行。

組裝最難的部分是將床鋪的骨架裏起來,在一個有限的空間裏,我們三個人覺得有點困難。主要是Hanu不能單獨扶住樹立一根床腿,太粗壯、太厚重了,如果兩根、三根甚至四根柱子不同時立起來的話,就沒法往一起使用橫梁連接、固定起來。辦法總比困難多,我們一起還是想了很多辦法,剋服了這些問題,最終樹立起骨架,後面就相對容易,逐漸上架更多的部件。

這期間,門口居然接連有兩次快遞送到門口,不得已我們沒法接,之後大聲地對門口喊,知道了把快遞放門口吧,而快遞員也有回應說,好的,只是運來的東西是冷鏈食品,需要馬上放冰箱裏…., 一片忙碌中.

Minina下班歸來,也加入我們的隊伍之中,協助清洗、消毒木料等,同時還為我們準備晚餐,對了,已經忙了一下午了,1拆卸—2搬運下樓—3裝車—4運送—5卸車—6搬運上樓—7組裝–8清洗消毒…., 這個漫長的流程,我們已經幾乎快完成了。

中間多次休息喝水,然後還有一次吃完飯,晚飯后繼續歸置,清理,大約忙到晚上21:30左右,終於結束當天的工作。從15:30出發啓動任務,差不多進行了連續6個小時的辛勞忙碌。

稍後休息。我回想之前有過 的一些搬家、運床的經歷。最早我從學校的宿舍搬出到平房居住,後來搬家到樓房,再後來搬家到我和Minina購置的新房,然後從這個小房搬家到現在住大房子。期間經歷可謂曲折、艱辛。這些搬家中,每一次幾乎都是親朋好友有力出力,有車出車,都來搭把手,雖然辛苦,卻也順利。

好像這是第一次,我帶兩個孩子,完成了將一個碩大的木製上下床從一個地方搬運到另外一個地方。孩子們大了? 我有幫手了?真相可能是孩子們真大了,而我還未老,也許現在就是創建功業的大好時機。 在不遠的將來,孩子們將重新走我和Minina年輕時走過的路,如果我們能將孩子們的起點墊起得更高些,或許他們能走得更遠些。

正如我們的父輩不辭辛苦地支持我們向更高、更好地生活邁進,我們也要沿著這樣的路綫,將孩子們遞送到更高、更好的生活方向和軌道上去,扶上馬,再送一程。這,或許就是人類生生不息、代際傳承的文化内涵和精神圭臬

一而再,再而三,家族之勢可成也。


姐姐Yoyo苦練一陣子的菊花字體“期末”,出現在學校班級的板報上,她言自己有兩科目以上都是榜眼,所以未能留言“狀元語錄”。我聞,亦爲之嘆息不已。


弟弟Hanu隔三岔五地會臨描一些圖畫書的插圖,如小鹿斑比(上圖),丁丁歷險記等,惟妙惟肖,煞是逼真。我意甚喜,而她母親則說,畫什麽像什麽並不是想象力的發揮。

時光就是這麽一晃就過去好幾年,上次寫 Yoyo的帖子是2015年,《化干戈为玉帛:平息争执的四个方法》:https://ufqi.com/blog/four-ways-to-get-out-of-disputes/ , 上次寫Hanu的帖子是2016年,《鸡蛋黄色的Orange和外教课english dict》:https://ufqi.com/blog/hanu-egg-yolk-orange-yoyo-eng-dict/ 。

—-

https://ufqi.com/blog/xenxin-family-hardwork-202006/

-R/S2SP

Posted in 社会生活 | Tagged , , , , , , | Leave a comment

🙋Hanjst汉吉斯特优化+JsonDataFromScript等

近日继续对 🙋Hanjst汉吉斯特优化改进。这次的改进思考是从服务器端返回的 HanjstJsonData的容器设计问题。目前的做法是服务器端的HanjstJsonData放入终端页面的一个Div元素中。这个Div的id默认被设置为Hanjstjsondata。

<div id=”Hanjstjsondata” style=”display:none;height:0px;width:0px;”>

HANJST_JSON_DATA
</div>

这么设计并实施有显而易见的好处,简单易行,而且部署实施复杂度和实际运行效率,都在可以接受的范围。然而在一些极端情况下,网速较慢时这个DIV会曝露给终端用户,而且需要在浏览器中读取到这个DIV的内容,并进行JSON.parse操作。有没有可能将服务器返回的HanjstJsonData 直接以JavaScript的JSON变量形式放入浏览器中,使得JavaScript和Hanjst可以直接调用?这样改进后,运行速度是否会更快?

同时,还要考虑的问题是,如果做这样的改动,比如可以接收来自JavaScript脚本的JSON数据,与此同时同时,还要前向兼容目前已经使用的方式方法,也即,需要继续支持能够使用DIV形式来传递JSON数据。

另外,还要考虑到,如果新的功能,来自JavaScript的JSON数据被引用,那么是否就丢弃来来自DIV的JSON数据?两者是否需有一个优先级?

从理论上分析,如果从服务端返回的JSON数据直接放入JavaScript的JSON对象中,会减少现有的JavaScript中读取DIV内容,并进行JSON.parse的过程,与之对应地,需要考察的过程就是JavaScript中处理较大的JSON对象的效率,这个过程是否高于从DIV中读取contents并对读取到对contents进行JSON.parse?

实践出真知。我们最终决定改造Hanjst的解析引擎,使之支持来自JavaScript的JSON数据对象,在Hanjst运行环境初始化完成后,开始对JSON数据对象的探测。Hanjst 使用window.hasOwnProperty(Hanjstjsondata) 的方法来探测是否在当前JavaScript运行时环境中已经定义了Hanjst Json data的数据对象。 如果探测到已经定义了有来自JavaScript的Hanjst JSON data数据对象被定义,则使用这个作为后续的数据源。

如果没有探测到相应的数据对象被定义,则程序进行之前的过程——根据HanjstJsonDataId寻求相应的DIV,然后读取DIV的contents,然后再对contents进行JSON.parse 的操作。

如此以来,将来自JavaScript的JSON数据对象置为第一优先级,如果有则终止对DIV对探寻,如果没有再继续之前的DIV中的JSON数据的读取。既实现了对之前对兼容,也扩展了对来自JavaScript的JSON数据的支持。

改进之后增加使用JavaScript声明变量来引入JSON数据对象的写法:

<script async>

//- first order, detect

//- HANJST_JSON_DATA

var Hanjstjsondata = {“pagetitle”: “-Hanjst, Hanjst汉吉斯特”};

</script>

 

Hanjst demo ( https://ufqi.com/dev/hanjst/Hanjst.demo.html) 的页面实测中,使用来自DIV的JSON数据和使用来自JavaScript的JSON数据对象,两者在运行时间上并没有明显的区别。Hanjst demo的解析运行时间 (普通PC桌面浏览器),在两种情况下均在 20~40ms之间,也即 0.02~0.04s之间完成页面的样式和内容的merging操作并更新整个页面的body。

可能是Hanjst demo页面尺寸和复杂度较低,JSON data数据对象也不大,所以在运行时间上无法明显区分开来。待有正式商用的较大尺寸的页面和较复杂的页面逻辑、较大尺寸的JSON data时,再做详细的对比。目前只能从理论上证明:使用来自JavaScript的JSON对象可能会快些。

这是最近接二连三地对 Hanjst汉吉斯特进行更新的第三篇,前两篇分别是:
https://ufqi.com/blog/hanjst-ensafeexpr-updt/ , 🙋Hanjst汉吉斯特改进+enSafeExpression安全表达式等; https://ufqi.com/blog/hanjst-showimage-dotpos/ , 🙋Hanjst汉吉斯特升级:+showImageAsync及性能改进等;

其他一些改进:

1)修改了一处 正则表达式中的 matchStr 被引用时,将双引号“进行转义操作。
2)改进了一处 关于注释代码清理的正则匹配问题,在检查 // 注释之前,先行去除 /* */

/\/\*([^]+?)\*\//gm

3)增加了一處顯示功能, {=$i+2} , 先對 $i 進行賦值操作,然後再在當前位置顯示出來
此前要顯示一個變量需要經過兩步驟:

a. 賦值操作: {$i=$i+2} , 空語句,只執行語句,不做顯示;
b. 顯示操作: {$i} ;

目前a, b兩步驟可以合并為一步: {=$i+2} , 先賦值操作,后顯示操作。
相當於截至目前,有兩種顯示操作方式:
3.1) {$i} : 在當前位置顯示 $i 的值;
3.2) {=$i+2} : 先進行賦值計算操作,然後再在當前位置顯示出 $i 的值. 

{$i} 等價於 {=$i+0} .

 

….


Hanjst

🙋Hanjst汉吉斯特 是一种基于JavaScript的模板语言及模版解析引擎,她运行在客户端或服务器端。

🙋Hanjst汉吉斯特 能够表述逻辑控制,能够实现与服务器端模版语言相同的强大功能。

  • Hanjst当完全在客户端解析时,节省服务器端计算资源;

  • Hanjst模板语言独立,不与服务器端资源做任何绑定;

  • 纯粹的MVC,层间数据用JSON格式传递;

  • 常见模板语言功能全支持,附带复杂而强大的JavaScript编程能力;

  • 无学习成本,直接使用JavaScript书写模板语言;

  • ….

Hanjst is a JavaScript-based templating language and parsing engine that runs on both the client-side and/or server-side.

Hanjst can express logical controls and achieve the same functionalities as the server-side templating languages.

  • Hanjst’s Run-time in client-side, reduce computing render in server-side;

  • Hanjst is Language-independent, not-bound with back-end scripts or languages;

  • Totally-isolated between MVC, data transfer with JSON;

  • Full-support template tags with built-in logic and customized JavaScript functions;

  • No more tags languages to be learned, just JavaScript;

  • ….

 

 https://ufqi.com/blog/hanjst-updt-jsondata-from-script/
-R/N2SL

Posted in -Hanjst/-汉吉斯特, 编程技术, 计算机技术 | Tagged , , , , | Leave a comment

🙋Hanjst汉吉斯特改进+enSafeExpression安全表达式等

Hanjst汉吉斯特模版语言及模版引擎,近期持续改进升级。
这次改进主要是增加了对安全输出表达式兼容,由于涉及到对软件开发过程中的效率和软件运行效率的平衡和取舍,所以多写了几句,以描述这个权衡利弊对思考过程。距离上次更新:🙋Hanjst汉吉斯特升级:+showImageAsync及性能改进等 ( https://ufqi.com/blog/hanjst-showimage-dotpos/ ),时间过得并不算长,希望Hanjst早日成熟而稳定下来。

1. 问题及背景

Hanjst 模版语言解析引擎在编写时,启用了JavaScript的 strict mode ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode ),对程序语句执行严格对语法检查,因此如果书写不严格会偶尔抛出异常错误警告来。之所以这么要求,使用JavaScript对strict mode,是希望Hanjst汉吉斯特能够用在一些关键领域和苛刻岗位,将异常错误消灭在程序编写阶段。

让异常在“编译时”发生,进而得到解决,属于编程语言方面的准编译型。这本是好事,因为Hanjst 除了用在普通的资讯网站,也会用在电商、金融等领域,对其进行苛刻的语法检查,是必需的步骤。

然而,这也有弊端,就是开发时比较耗费时间,需要考虑各种情况,反复测试各种情景下的软件行为,无意会加大开发成本。比如常见的 strict mode下的报错:未定义变量和访问对象为undefined。报错信息在 Hanjst里有较人性化的显示输出,参考:汉吉斯特Hanjst+更新升级:error reporting, innerLoop和loadingLayer ,https://ufqi.com/blog/hanjst-error-reporting-innerloop-and-loadinglayer/  。

如果因为对接的系统处于非关键领域和苛刻岗位,对于往复出现的这种变量未定义或者访问undefined对象,能不能进行一些主动兼容?这次就是考察这个问题。

2. 解决思路及方法

对这个问题的考察,大致两种方法:
1)在模版编译时,去掉 JavaScript对strict mode,使之不再做严格对检查,从而避免类似未定义变量和访问undefined对象;
2)第二种思路是在保持 strict mode对前提下,做一些局部的微调,使之能够兼容这些低级错误,也保留对其他语法对严格检查。

在大的方向上去掉Strict mode显然是不行的,这会从本质上动摇Hanjst用在关键领域和苛刻岗位的定位。这一点不应拿来讨论。启用strict mode,进行编译时语法检查,对严肃软件是必需的。

在JavaScript中,探测一个变量是否被定义,是一件容易的事,使用类似 typeof 对指令,可以判断某个变量是否被定义。如果对每一个变量在输出前都做这样的检查,显然陷入了“一个人有病,全国人吃药💊”的非理智状态,这也是之前的尝试被阻止的原因之一。
因此如果要启用针对变量的探测,需要有某种机制来感知已经被定义了的变量。

另外,如果不使用 JavaScript eval等危险性较高对函数,如何去感知某个字符串所代表对变量是否被定义了?使用内置对象 Function构建匿名函数吗?如果匿名函数的话,其单独的变量作用域与变量实际运行环境又有显著的不同,该如何操作?

第三,在模版语言中,我们允许对象的属性访问,这类对象,可能是运行时环境的全局变量,也可能是局部变量;这类对象既可能是一维的Hash数据list,还可能还多位的Hash嵌套,可能存在第一维的数据对象是已经被定义的,而第二维、第三维是未定义的,而此时如果是未定义的,就有可能抛出异常来。

待问题进一步地发散为:
1)继续启用Strict mode,
2)在1)的情况下,实现对未定义变量和未定义对象对访问兼容;
3)尽量不要使用高危函数,如 eval;
4)保证2)都情况下,不能不分情况的对所有变量进行兼容操作;
5)需要区分是全局变量,还是局部变量,各种情况最好都能兼容;
6)需要区分一维对象和多维对象,各种情况最好都能兼容。

经过一番艰难地探索,在尝试寻求鱼和熊掌兼得的情况下,采取如下措施:
1)使用 typeof 生成待执行的变量是否被定义的JavaScript语句;
2)新增环境变量赋值语句的list,用以检测某个变量是否显式地被定义;
3)使用 window.hasOwnProperty 探测某个全局变量是否被定义;
4)使用递归方式拆解多维数据对象,如, $aList[$ak1][$ak2][$ak3] .

基于以上分析在 Hanjst.js 中新增 _enSafeExpression 函数用于对待输出对变量及对象进行安全性检查。

3. 样例演示

{$a=1}  –> 类似的语句被登记为该变量已经被显式地声明;

{$a}  –>  ((typeof $a == ‘undefined’) ? ” : $a) , 输出 $a 对语句如果探测到没有被定义,将被改写为三目运算符的表达式;

$aList[$ak1][$ak2][$ak3] –> $aList[$ak1], $aList[$ak1][$ak2] , 将待输出对三维数据分别逐级拆解,形成待探测的两个变量/对象,再分别予以构建使用三目运算符的表达式,形成由顶部到底部的逐层检测,大致为:
((typeof $aList[$ak1] == ‘undefined’) ? ” : ((typeof $aList[$ak1][$ak2] == ‘undefined’) ? ” :$aList[$ak1][$ak2][$ak3]))

更多维的数据对象,也依此类推。 

4. 其他

版本号升至 v1.7, +其他一些细微的优化调整,

一个简单地问题细究起来,居然一点都不简单,纸上得来终觉浅,绝知此事要躬行。一个小任务,变量输出前进行主动安全性检查,居然唠唠叨叨地写了差不多2000字。

毕竟,Hanjst汉吉斯特在追求平衡的艺术,追求极致而完美。

….


🙋Hanjst汉吉斯特 是一种基于JavaScript的模板语言及模版解析引擎,她运行在客户端或服务器端。

🙋Hanjst汉吉斯特 能够表述逻辑控制,能够实现与服务器端模版语言相同的强大功能。

  • Hanjst当完全在客户端解析时,节省服务器端计算资源;

  • Hanjst模板语言独立,不与服务器端资源做任何绑定;

  • 纯粹的MVC,层间数据用JSON格式传递;

  • 常见模板语言功能全支持,附带复杂而强大的JavaScript编程能力;

  • 无学习成本,直接使用JavaScript书写模板语言;

  • ….

Hanjst is a JavaScript-based templating language and parsing engine that runs on both the client-side and/or server-side.

Hanjst can express logical controls and achieve the same functionalities as the server-side templating languages.

  • Hanjst’s Run-time in client-side, reduce computing render in server-side;

  • Hanjst is Language-independent, not-bound with back-end scripts or languages;

  • Totally-isolated between MVC, data transfer with JSON;

  • Full-support template tags with built-in logic and customized JavaScript functions;

  • No more tags languages to be learned, just JavaScript;

  • ….

    两天来,连续创作两篇,在写blog的历史上,也是少有的行为。同期写就的另一篇: 写写🏦存款利率贷款利率和负利率 , https://ufqi.com/blog/captial-rate-and-minus-rate/  。

http://ufqi.com/blog/hanjst-ensafeexpr-updt/
-R/x12SX
https://ufqi.com/news/list.932.html

Posted in -Hanjst/-汉吉斯特, 编程技术, 计算机技术 | Tagged , , , | 2 Comments

写写🏦存款利率贷款利率和负利率

2020年以来,经济发展受新冠肺炎疫情影响,进行大幅深度回调,宏观层面金融政策和财政政策接踵而至,为了保经济、保不下挫、保下挫的不太厉害操碎了心。利率调整是宏观经济干预工具箱中较为亮眼的那种,有点像像是瑞士军刀Swiss Knife或者互联网络中netcat命令. 这篇打算写写利率及负利率,算是经济学学习笔记第二篇。(这里是第一篇:写写1929年美国经济大萧条与2020年美国股市大跌https://ufqi.com/blog/us-1929-economic-crisis-2020-stock-shock/ )欢迎批评指正。

几个月前,网上有篇美团副总裁谈“为什么中国To B企业都活得这么惨?-4( https://ufqi.com/news/ulongpage.250.html )”的文章也提到负利率,说法是负利率就是你去向小A借钱做生意不但不用支付利息,等期末小A再多给付你一笔钱;或者说,你向小A借了100元,等期末你只需向小A还款90元就行。
这是一种错误的说法,天上掉馅饼的事不会发生(发生了也不会砸你头上),负利率不是这么解释和应用的。本文首先要澄清这一点。

1. 利率的一些定义及名词

利率,教科书上的定义是资金的价格,使用资金的成本。经济学上,正常情况下,价格是不能小于零(等于零是白送),当某种商品或服务的价格为负时,一定是异常的、极端的情况。
可能这也是美联储2020年这次一撸到底将美元的利率降低到 0–0.25% 附近,而没有一下子极端地将美元利率弄成负的。
还要注意的是,这个利率,潜台词或者默认是指“存款利率”,不是贷款利率。


(1900-2013 美国存款利率)

需要进一步地厘清可能的名词:
1) 存款利率,小A将钱存入银行时,银行按“存款利率”给付利息,这是最大众,最普遍,也是默认的“利率”的指代;
2)贷款利率,小A申请一笔住房贷款,银行发放一笔贷款给小A,小A按期按“贷款利率”支付利息给银行,当然本金也要按计划慢慢还;
3)名义利率,就是名义上的利率,官方(中央银行)公布的利率,与实际利率相对于,与通货膨胀率相关;
4)实际利率,就是名义利率扣减掉通货膨胀率之后的真实所得的利率,这部分在投资上也成为无风险收益,是计算和比较其他投资收益的基准,也称为“躺赢”的钱;
5)通货膨胀率,大致可以理解单位资金/货币的实际购买力的变化率,通俗地说是货币的贬值速度,贬值率。为何货币会贬值?( 从硬货币到代币到信用货币: https://ufqi.com/news/ulongpage.658.html

通过一番对名词的解读,我们发现,实际上,能够实现赚取躺赢的钱,很少很少,以美元利率为例,假如存款利率为 0.2%(名义利率),实际利率会是多少呢? 美联储的使命之一就是极力地维持美元的通货膨胀率在年2%以下,设若这一目标达成(很多时候只高不低),美元的实际利率是 -1.8%。 又成为负的了!
也就是目前的美元存款,没法实现躺赢,要想拿到美元躺赢的钱,只能在名义利率大于通货膨胀率时,才可能发生,也即名义利率在 2% 以上时。从美元存款利率1900-2013间100多年的历史来看,多数年份的利率都远高于 2%, 均值是 8%,这个是相当高的无风险收益了。
其他货币依此类推。

2.有存款负利率,没有贷款负利率

回头说 贷款利率,这个利率的普及远不如存款利率,因为相比存款的人,贷款的人仍然显得很少。所以也很少讨论。实际上,贷款利率与存款利率是挂钩的,这个挂钩的依据是银行的开销。


(央行一年期存款利率1.5%,贷款4.35%)

银行这种经济基础设施是需要花钱的,有各种开销。这些开销来源,一块大头就是利率差,也即贷款利率减去存款利率的差值。由于银行还有其他方面的收益,以及作为贷款方有资格在多个银行间询价,贷款利率往往不是整齐划一的,反而参差不齐,甚至相去甚远。

然而,有一点明确的是,贷款利率不会为负。即便是在存款利率为负的情况下,贷款利率还仍然高挺着不动。当存款利率为负时,你存钱到银行,需要每月给银行费用(管理费等),而还不曾发生,你从银行贷款了,银行每月还发钱给你,这就有点不符合常识,也是违背经济学基本规律的。总之,贷款利率不会为负的,负利率是一个混淆视听的说法。正确地说是,存款负利率。

等一下,储户存款负利率时,从银行的视角来看,就是银行借小A的钱用,然后每月小A还得付款给银行,对银行来说,就是妥妥地贷款负利率啊!为何会发生这种情况,为何不是逆转过来的样子?
发生了什么事? 为何资产、资金一夜之间从正资产(产生现金流)变成负资产(损耗现金流)?投资行为一夜之间变成消费活动?
为何只有银行能够享受这种贷款负利率的优惠?

3. 能坦然面对存款负利率吗?

在文章“新冠肺炎疫情之后,中国何去何从? ( https://ufqi.com/news/ulongpage.631.html )” 中,作者在谈论GDP和经济时这样感慨如下。

这很好地验证了我读博时导师对我的训诫:
你在问最好的商业模式?
很好。要么你去打天下然后收税,要么去拿一张银行牌照。

我们能够很容易地的推导出来,当存款利率为正的时候,银行是吃贷款用户的钱;当存款利率为负的时候,银行是两头吃,继续吃着贷款客户的利息,也同时吃着存款用户的钱。

问世间真有这么好的商业模式吗?这么梦幻的事情正在发生,在那些存款负利率的国家。庆幸美联储、中国央行等还没官宣存款负利率,虽然通货膨胀率已经完全抹去存款名义利率的收益,好在这还起着遮羞布的作用。

如果掀开了存款正利率这块遮羞布,将存款利率弄成负的,银行狰狞的面貌就露出来了,站在它背后的大Boss也若隐若现了。
也许有经济学家或者银行辩驳说,吃储户的钱,就可以降低贷款户的利率了,然后支持经济发展,bulabulaaaa…… 

存款负利率是对公民财产赤裸裸地剥夺,是明火执掌地征收“货币税”。持有某种货币,所以要纳税(收费),只是这个税未经法定,收取机关也不是税务局,而是银行。
将富裕阶层分化升格为大富豪或降格到中产,将中产阶层直接降格为无产,无产阶层免受其害,因为不持有“货币”。

这将加速社会两级分化,财富进一步地向少数人集中,中产无可避免地下坠到无产,到后来,绝大多数人除了可以出卖的劳动力,其他一无所有。

4. 危言耸听的风险错配

存款负利率的实施会加速摧毁中产阶层,使之降格到无产阶层,而不是升格到富裕阶层。可以想象的是,面对为数不多的一笔存在银行里的钱,每个月要还“利息”,怎么想都觉得不爽,要么花掉这笔钱,吃喝玩乐算了。

理性的人,会将钱取出,去买理财等进行有风险投资活动。注意我们上面提到存款利率是无风险收益。现在没有无风险收益,而且还要倒贴钱拿着这笔钱,又不能吃光花净,只好冒险去进行有风险的投资活动。

在一个危机四伏的投资环境里,对于不懂、不擅长进行风险管理的投资者来说,亏完这些血汗钱,可能只是时间问题。
这本来是专业风险管理、专业投资进行的活动,因为存款负利率完全转移到毫无理论知识和实践经验的平民百姓头上,作为不同专业、不同职业的人,可能完全没有投资理财的技能,也不会学习投资理财的知识。

中产就这么慢慢地被消解为无产,而一些富裕阶层,由于需要更多地面对有风险的投资活动,在一次次有风险的投资活动中,或输或赢,保持富裕阶层,或消解为新中产,进一步地大概率地滑落到无产。

当我们还在讨伐“食利阶层”时,一不小心地,我们都成了,日光族、月光族和年光族,从此再无需为存款负利率担忧,稍有风吹草动,生活也可能万劫不复,因为没有可以代替肉身抵挡风险的“资产、资金”。

或许只是危言耸听,普通民众只是多了一项“货币税”而已,我们从摇篮到坟墓,我们所交的税多得多了。只是相比较而言,这个“税”有些特殊,令人锥心。

如果有那么一天,存款负利率时,我们也能同时申领到贷款负利率的贷款,或许会好些。

https://ufqi.com/blog/captial-rate-and-minus-rate/

-R/c2SO

https://ufqi.com/news/ulonglist.405.html

https://ufqi.com/news/list.2397.html

Posted in 社会生活 | Tagged , , , | 8 Comments