前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。
目录如下:
Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。
Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。
Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。
Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。
Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。
Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。
Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。
Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。
Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。
基础工具方法 Hessian 序列化之后的数据,都是字节数组,为了方便查看字节数组的二进制形式和十六进制形式,在正式开始之前,先介绍一下期间用到的辅助工具方法。闲言少叙,直接上代码:
/** * 创建 Hessian2Output 对象,以便用于序列化 * * @author D瓜哥 · https://www.diguage.com/ */ private Hessian2Output getHessian2Output(OutputStream stream) { SerializerFactory serializerFactory = new SerializerFactory(); serializerFactory.setAllowNonSerializable(true); Hessian2Output result = new Hessian2Output(stream); result.setSerializerFactory(serializerFactory); return result; } /** * 打印字节数组 * * @author D瓜哥 · https://www.diguage.com/ */ private void printBytes(byte[] result) { for (byte b : result) { String bitx = Integer.toBinaryString(Byte.toUnsignedInt(b)); String zbits = String.format("%8s", bitx).replace(' ', '0'); if (0 <= b) { System.out.printf("%4d 0x%02X %8s %c %n", b, b, zbits, b); } else { System.out.printf("%4d 0x%02X %8s %n", b, b, zbits); } } } /** * 将 long 转化成二进制字符串(前面补0) * * @author D瓜哥 · https://www.diguage.com/ */ private String getBinaryString(long value) { String bits = Long.toBinaryString(value); char[] chars = String.format("%64s", bits) .replace(' ', '0').toCharArray(); StringBuilder result = new StringBuilder(64 + 7); for (int i = 0; i < chars.length; i++) { result.append(chars[i]); if (i % 8 == 7 && i != chars.length - 1) { result.append(","); } } return result.toString(); } /** * 将 int 转化成二进制字符串(前面补0) * * @author D瓜哥 · https://www.diguage.com/ */ private String getBinaryString(int value) { String bits = Integer.toBinaryString(value); char[] chars = String.format("%32s", bits) .replace(' ', '0').toCharArray(); StringBuilder result = new StringBuilder(64 + 7); for (int i = 0; i < chars.length; i++) { result.append(chars[i]); if (i % 8 == 7 && i != chars.length - 1) { result.append(","); } } return result.toString(); }
公司在微服务系统中,序列化协议大多数使用 MessagePack。但是,由于 MessagePack 设计限制,导致微服务接口在增减参数时,只能在最后操作。但是,由于个人操作,难免失误,结果造成因为增减字段导致的事故层出不穷。最近,一些条件成熟,准备推动部门将序列化协议切换到 Hessian。
原以为,切换到 Hessian 就可以万事大吉。但是,在和同事的沟通中发现,同事反馈,Hessian 本身也有一些限制。为了对 Hessian 有一个更深入的了解,干脆就把 Hessian 序列化协议读一遍。看协议,文字不多,干脆就把协议完整翻译一遍。闲言少叙,正文开始。
Hessian 2.0 序列化协议 协议解释 针对该协议有很多言语不详,甚至模糊不清之处,专门做了一些解释和实践,叙述系列文章,用于辅助消化理解。目录如下:
Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。
Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。
Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。
Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。
Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。
Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。
Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。
Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。
Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。
使用 Spring Boot 时,需要使用 Jackson 处理一些 Java Time API 类型的 JSON 序列化问题,在处理一些类的字段时,可以通过直接在属性上加注解的方式来指定其格式化样式。但是,昨天同事遇到一个格式化 Map 数据的问题,这样就不能通过加注解来解决格式化样式的问题了。
在网上各种搜索,各种尝试后,终于解决了这个问题,记录一下,以备不时之需。
闲言少叙,直接上代码:
package com.diguage.demo.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.util.StdDateFormat; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import static com.fasterxml.jackson.databind.SerializationFeature.*; import static java.time.format.DateTimeFormatter.ofPattern; /** * 配置类 * * @author D瓜哥 · https://www.diguage.com */ @Configuration public class Config { /** * 创建 ObjectMapper 对象,配置日期格式化 * * @author D瓜哥 · https://www.diguage.com */ @Bean @Primary public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); String dateTimepattern = "yyyy-MM-dd HH:mm:ss"; String datePattern = "yyyy-MM-dd"; DateFormat dateFormat = new SimpleDateFormat(dateTimepattern); mapper.setDateFormat(dateFormat); mapper.configure(WRITE_DATES_AS_TIMESTAMPS, false); mapper.setDateFormat(new StdDateFormat().withColonInTimeZone(true)); JavaTimeModule javaTimeModule = new JavaTimeModule(); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(ofPattern(datePattern))); javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(ofPattern(datePattern))); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(ofPattern(dateTimepattern))); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(ofPattern(dateTimepattern))); mapper.registerModule(javaTimeModule); return mapper; } } 后续问题 不知道通过这种方式指定日期格式化样式后,在处理一些打格式化样式注解的字段时,会有什么样的表现?有机会测试一下。
参考资料 Jackson Date
json - Java 8 LocalDate Jackson format
最近公司项目要对一些内部依赖做集中升级。为此,D瓜哥发布了一个 BOM(BOM stands for Bill Of Materials),用于规范项目依赖及版本。
但是升级后,效果不理想,检查发现还是有不少依赖的版本依然不符合要求。经同事提醒,可以使用 Apache Maven Enforcer 来做规范检查,测试一下效果确实不错。
将 Apache Maven Enforcer 和 Extra Enforcer Rules 的文档大致巴拉了一遍之后,根据项目的实际情况,挑选出来可用规则如下:
比较有用的几个规则 bannedDependencies – 排除不需要的依赖,引入需要的依赖。
banDuplicatePomDependencyVersions – 防止依赖重复声明。
dependencyConvergence – 确保所有依赖收敛到相同的版本。也可以考虑加入。
reactorModuleConvergence – 多模块开发时,确保父子模块的版本是一致的。
requireJavaVersion – 检查 JDK 的版本
requireMavenVersion – 检查 Maven 的版本
requireReleaseVersion – 这个可以通过激活生产环境的 profile 来启用该规则,保证发布的不是快照版。
requireUpperBoundDeps – 确保直接引用的依赖不比间接解析出来的依赖版本低。感觉这个也挺有用,但是使用方式还没搞清楚。实例有些模糊。
banDuplicateClasses – 检查重复类定义。可以避免一些特殊情况。
requirePropertyDiverges – 确保项目定义的属性与依赖中包含的属性不重复。
enforceBytecodeVersion – 确保使用的字节码版本不高于指定版本。
banCircularDependencies – 确保没有循环依赖。
requireEncoding – 指定项目字符集。
实践总结 D瓜哥把上面的规则几乎全部试用了一遍,把发现的一些需要特别注意的地方标注记录一下吧:
banDuplicateClasses — 这个插件还是很棒的。使用的时候,成功检查出废弃不用的依赖(废弃依赖被收入到另外一个依赖中了。)。不过,也发现一些问题,项目中使用了 netty-all 及 Netty 的其他模块依赖。但是,并没有检查出来,感觉是项目代码有直接依赖的重复类才会被检测出来。
requireUpperBoundDeps — 开启这个检查时,发现间接引用了 commons-lang:commons-lang:2.6,但是项目直接声明的依赖是 commons-lang:commons-lang:2.5,就直接报错了。私以为这个检查规则还是很赞的。但是,因为我们的项目中有有依赖 Gson 1.X,也有 Gson 2.X 的,而且这两个版本在处理父子类有相同字段时的存在抛异常的差异,所以无法启用,实在可惜。
reactorModuleConvergence –- 多模块开发时,确保父子模块的版本是一致的。这个规则还是很赞的。但是,因为我测试的模块不存在这个问题,所以,没有触发报警。
requirePropertyDiverges — 本想启用这个规则,看了一下配置,着实麻烦,而且不是全局检查,似乎是检查指定配置项,感觉不是很满意。没有启用。
enforceBytecodeVersion — 检查字节码版本。这个是不超过上限,我是想检查下限,所以没有启用。反思:在写这个文章时,又思考了一下,检查下限是有问题的,一些陈旧的依赖就不能使用了。但是这些依赖是没有问题的。
banCircularDependencies — 这个规则似乎 Maven 已经内置了,以前遇到过这样的场景,Maven 直接报错了。所以,就没有启用这个规则。
requireEncoding — 这个规则非常棒。在试用过程中发现,它会把存 ASCII 字符的 UTF-8 文件判定为 US-ASCII 编码。没有找到好的办法来解决这个问题。所以,可惜没有启用。
最近一位同事离职,在践行宴会上,大家聊到投资理财,D瓜哥推荐了 《投资中最简单的事》。去年已经把这本书读完了,下班后把这本书的摘要笔记整理一下,按照章节,分四篇来分享:
《投资中最简单的事》之读书笔记(一):投资理念
《投资中最简单的事》之读书笔记(二):投资方法
《投资中最简单的事》之读书笔记(三):投资风险
《投资中最简单的事》之读书笔记(四):投资心理学
第四部分 投资心理学 11 人性的弱点:投资者常见的心理误区 一个股票便宜与否,看估值比看近期涨跌更可靠:基本面大幅超预期时会越涨越便宜,反之会越跌越贵。
美国消费股多,适合价值投资;加拿大资源股多,适合趋势投资。互联网赢家通吃,买龙头;休闲服装百花齐放,买成长。差异化产品,买品牌;同质化产品,买成本低的。
俾斯麦说,每个笨蛋都会从自己的教训中吸取经验,聪明人则会从别人的经验中获益。
同样是错过航班,错过 3分钟的比错过 30分钟的更沮丧;同样是彩票没中,号码与头奖号码只差一点的是最痛苦的。
与成功擦肩而过比从未接近成功更令人难以接受,更令人想再试一次,所以,许多赌博形式正是包含大量“差点就赢”的设计,才吸引了这么多赌徒不惜倾家荡产屡败屡战。
12 后视镜 应该跑向球将要去的地方,而不是球现在所在的地方。
13 傻瓜定价说 对市场敬畏但不屈服,逆市场而动但懂得自我保护。
14 这次不同了 人们从历史中学到的唯一教训就是人们从来不吸取任何教训。
每一次危机或泡沫都感觉像是史无前例,其实不过是历史长河中的一朵浪花。
当人们在为“黄金十年”找论据时,市场离见顶就不远了;当人们在为长期的悲观寻找理由时,市场已经在底部区域了。投资者的悲哀,永远是轻易地放弃和错误地坚持。
15 树动风动心动 短期来说,股价波动是人心与人心博弈的结果,是心在动,难以预测。中期来说,股价更多是由政策面决定:吹的是政策宽松的暖风,股价就上涨;刮的是政策紧缩的寒风,股价就下跌。所以说,中期是风在动。
长期来说,股价是由基本面决定的。那些根基不稳的病树,难以避免在风中被连根拔起的命运;而那些有稳固根基的好树,不管人心冷暖,风向东西,终将成长为参天大树。所以说,长期是树在动。
“心在动”常对“风在动”推波助澜,把五级风放大为十级,此时人们已不关心“树动”与否,反正玩的是击鼓传花的游戏。
附录 投资访谈:顺应规律投资,才能事半功倍 过去 10年,人家问我看好什么行业,我在任何时候都是讲三大类行业:金融地产、品牌消费、先进制造。
有“霸王条款”的行业都不会太差。
便宜是硬道理,股票的回报并不取决于它未来的增长快还是慢,而是取决于未来增长比当前股价反映的增长预期更快还是更慢。
我们找白酒的顺序是先找高端,再找次高端,再到平价酒,因为中国经济的复苏通常是先重点扶持基建,商务应酬增加,对高端酒的需求会增加,之后经济恢复,老百姓有钱了,中端酒开始起来,然后再到低端酒。
市场是一个拍卖系统,最后的顶点总是最疯狂的人在定价,就像在拍卖会上面,最后的买主肯定是那个最狂热的、愿意出最高价的人。
一个投资人说过,当一家公司的创始人和管理者,主要是做好两点:一个是算命,即想清楚一些大的战略性的问题;第二是相面,就是选人。
后记 大佬为什么对科技股长期持谨慎的态度?为什么热衷科技股的基金经理鲜有长时间业绩突出者?
第一,科技进步内在的突变性决定了科技股投资人业绩内在的不可延续性。
第二,科学技术是不断变化的。
第三,虽然新技术的前景广阔,初期的行业格局却非常散乱,绝大多数投资人很难在事前判断出谁是最终赢家。
临渊羡鱼不如退而结网,投资必须把握你能把握的东西。
知道自己的能力边界,发挥自己的优势,买便宜的好公司,注意安全边际,注重定价权,人弃我取,在胜负已分的行业里找赢家,这些貌似投资中最简单的事,其实也是投资中最本质的东西。
最近一位同事离职,在践行宴会上,大家聊到投资理财,D瓜哥推荐了 《投资中最简单的事》。去年已经把这本书读完了,下班后把这本书的摘要笔记整理一下,按照章节,分四篇来分享:
《投资中最简单的事》之读书笔记(一):投资理念
《投资中最简单的事》之读书笔记(二):投资方法
《投资中最简单的事》之读书笔记(三):投资风险
《投资中最简单的事》之读书笔记(四):投资心理学
第三部分 投资风险 07 价值陷阱与成长陷阱 价值陷阱 第一类是被技术进步淘汰的。
第二类是赢家通吃行业里的小公司。
集中度越来越高说明行业里的龙头企业比其他企业增长更快,不然就是越来越分散。
第三类是分散的、重资产的夕阳行业。
第四类是景气顶点的周期股。
对周期股价值的评估可以借助两个概念,一个是常态化的盈利( Normalized Earnings),计算剔除了经济周期波动后的企业盈利;另一个是盈利能力( Earnings Power),而不是某一时间的盈利数额,评估企业内在的可持续的盈利水平。
怎么操作?
第五类是有会计欺诈的公司。
最后一类是人不行、捧着“金饭碗”讨饭的公司。“
金玉之堂,莫之能守
成长陷阱 成长陷阱比价值陷阱更常见。
估值过高
技术路径踏空
无利润增长
成长性破产
盲目多元化
树大招风
追随者挑战巨头的时候要小心,不要太早显露目的,以免遭到巨头的封杀和围剿。
新产品风险
寄生式增长
强弩之末
会计造假
各类价值陷阱的共性是利润的不可持续性,各类成长陷阱的共性是成长的不可持续性。
成长本身并不是陷阱,但人性的弱点中对未来成长习惯性地过高预期和过高估值却是不折不扣的陷阱。
管子说:“不为不可成,不求不可得,不处不可久,不行不可复。”
“黄金坑”还是“融化中的冰棒” 这有点像一根正在融化的冰棒,你拿在手中它就不断地融化。
价值陷阱大部分的问题主要出现在内在逻辑被破坏,这样整个公司的护城河、核心竞争力逐步丧失,整个公司要么被时代淘汰,要么被对手打败,这种大多数是价值陷阱。
我们需要理解什么是永久性的下跌,什么是暂时性的调整。
如果找到了每一个公司便宜的原因,就能判断相应的股票是价值陷阱还是“黄金坑”。
趋势投资是可以不断止损的,每一次错误最大的损失是有限的。所以,从这个意义上看,价值投资的风险比趋势投资更大。
08 真假风险与安全边际 股市如围城,城内的人在往外逃,城外的人在往里冲。
在互联网时代,品牌的优势比渠道的优势更重要。
股票暴涨后,真实的风险上升,感受到的风险却在下降,在 6 000点股市最危险的时候大家感受到的都是歌舞升平;股票暴跌后,真实的风险下降,感受到的风险上升,在 2 000点股市相对低谷时人们感受到的却都是凄风苦雨。
黑色星期一之后暴露的风险很大,但是隐藏的风险不大;感受到的风险很大,但是真实的风险不大。能区分并利用这两种风险的不同,是成功投资的必要条件。
对于逆向投资者来说,最痛的时候,往往是最不该放手的时候。正如索罗斯所说,如果你承受不了失败的痛苦,就不要入市,因为没有人能够百战百胜。
安全边际 东方不亮西方亮,给点阳光就灿烂
估值低到足以反映大多数可能的坏情况
有“冗余设计”,有“备用系统”来限制下跌空间
价值易估,不具反身性,可越跌越买
索罗斯所说的反身性是指股价下跌本身对公司基本面有负面作用,易形成自我强化的恶性循环。
贝尔斯登和可口可乐对比!多思考!!!
鼻莫如大,目莫如小
止损 对于趋势投资者而言,止损不止赢是短线交易的第一法则,自不必多说。
忘掉你的成本,是成功投资的第一步。
不止损是有很严格的前提条件的:必须避开各种价值陷阱;所买的股票有足够安全边际;所承担的只是价格波动的风险而非本金永久性丧失的风险。
最近一位同事离职,在践行宴会上,大家聊到投资理财,D瓜哥推荐了 《投资中最简单的事》。去年已经把这本书读完了,下班后把这本书的摘要笔记整理一下,按照章节,分四篇来分享:
《投资中最简单的事》之读书笔记(一):投资理念
《投资中最简单的事》之读书笔记(二):投资方法
《投资中最简单的事》之读书笔记(三):投资风险
《投资中最简单的事》之读书笔记(四):投资心理学
第二部分 投资方法 04 投资的三个基本问题 如果把我过去十几年的投资分析方法做一个简单的概括,最根本的就是要回答三个问题:为什么认为一家公司便宜,为什么认为一家公司好,以及为什么要现在买。这三个问题中,第一个是估值的问题,第二个是公司品质的问题,第三个是买卖时机的问题。
问题1:估值 世界上不存在每年都有效的投资方法。
在好行业中挑选好公司,然后等待好价格出现时买入。
三板斧:
波特五力分析。不要孤立地看待一只股票,而要把一个公司放到行业的上下游产业链和行业竞争格局的大背景中分析,重点搞清三个问题:公司对上下游的议价权、与竞争对手的比较优势、行业对潜在进入者的门槛。
杜邦分析。弄清公司过去 5年究竟是靠什么模式赚钱的(高利润、高周转还是高杠杆),然后看公司战略规划、团队背景和管理执行力等是否与其商业模式一致。例如,高利润模式的看其广告投入、研发投入、产品定位、差异化营销是否合理有效,高周转模式的看其运营管理能力、渠道管控能力、成本控制能力等是否具备,高杠杆模式的看其风险控制能力、融资成本高低等。
估值分析。通过同业横比和历史纵比,加上市值与未来成长空间比,在显著低估时买入。
这“三板斧”分别解决的是好行业、好公司和好价格的问题,挑出来的“三好学生”就是值得长期持有的好股票了。
不要被上市公司讲的“美好未来”忽悠了,一定要看现在看得见摸得着的利润、现金流和资产。
问题2:品质 便宜不便宜大多数人都能够判断,因此关键的区别在于搞清楚公司的品质。
三个要素中,投资者真正需要下大力气搞清楚的就是品质。
马和骑师,选马比选骑师重要。
我认为选一个好行业是成功投资的基本条件。
公司的品质好坏,关键是看能不能具有定价权。
你对你的竞争对手怎么看?最近竞争对手有没有什么做法让你特别难受?你最近有没有什么做法让你的竞争对手感到难受?
我为什么不太喜欢政府支持的新兴行业?因为政府的支持其实是增加了供应,增加了行业的竞争对手。
如何判断公司的品质?
是不是一个好行业?首先是看行业的格局,不要有太多人做,做的人多了,竞争自然就激烈了。
扶持其实是鼓励更多的人进入行业而加剧了竞争,打压却限制了新增供给,反而改善了竞争格局并且让行业龙头做大。
第二个要注意的是差异化竞争和同质化竞争的区别。
差异化的第一个标志是品牌。差异化、定价权的一个来源是品牌,而且最好是请客送礼的品牌。
差异化的第二个标志是有回头客,即用户黏度高。
差异化的第三个标志是单价不要太高。
差异化的第四个标志是转换成本。
差异化的关键在于能不能提价,提价之后是不是影响销售。
差异化的第五个标志是服务网络。
差异化的第六个标志是先发优势。
对行业格局的分析和对公司核心竞争力的理解是“道”,财务分析只是“术”,但是后者对前者起着验证和把关的作用。
判断一个公司所在的行业好不好,首先是看行业竞争格局是不是清晰,领先者有没有品牌的美誉度,领先者产品的售价是不是显著高于其他竞争者,领先者有没有网络服务的优势,有没有规模效应,产品的销售半径是不是相对比较小(不用参与全球竞争),是不是有回头客,是不是低单价(下游对价格不敏感),是不是转换成本高,领先者是不是有先发优势,技术变化是不是没有那么快。对品质的评判有很多指标,核心是“这是不是一门好生意,有没有定价权,是不是一门容易赚钱的生意”。
我一直强调胜而后求战,愿意买已经把竞争对手打趴下的公司,而不是战而后求胜,在百舸争流中猜赢家。
我认为行业研究员能够给基金经理提供的附加值在于讲出这个行业的特点。
我分析公司、分析行业,更看重的是行业的内在特质和公司的长期经济特征这一类静态的信息,这些是规律性的东西,只有对行业真正理解了才能够说得出来。
一个成功的投资者应该能够把行业到底竞争的是什么说清楚,把这个行业是得什么东西得天下弄明白。
在不同的细分子行业中竞争的东西也是不一样的,投资之前必须把每个细分子行业中决定胜负的因素研究清楚。
即使是同一个行业,投资者也得明白在不同阶段,到底什么因素是决定胜负的关键。
要认识一个行业,不妨做一道填空题:得___者得天下,用一个词来概括这个行业竞争的是什么。例如,基金业是得人才者得天下,高端消费品是得品牌者得天下,低端消费品是得渠道者得天下,无差异中间品是得成本者得天下,制造业是得规模者得天下,大宗品是得资源者得天下。
问题3:时机 投资的第三个大问题是时机。
投资是科学加艺术,在投资的三个基本问题中,估值是最接近科学的,有一整套的方法和规律可以学习;而选时是最接近艺术的,只可悟、不可学,只可意会、不可言传。
对于多数人而言,对待选时的正确态度应该是避免把大量的时间花在试图“抄底”或者“逃顶”上。
彼得·林奇说的“如果你每年花 10分钟在宏观分析上,你就浪费了 10分钟”
如何在合适的时候加仓?
第一种办法是看估值。
第二种办法,是根据各种指标之间的领先和滞后关系进行分析(具体请参读 本书第 10章:四种周期、三种杠杆,行业轮动时机的把握)。
第三种办法,是根据对市场情绪的把握和逆向思考进行分析。
“表弟指标”
对于多数人而言,只要把估值掌握好,把基本面分析好,淡化选时,长期来看投资回报就不会差。
历史上的股市见底信号 1.市场估值在历史低位; 2. M1见底回升; 3.降存准或降息; 4.成交量极度萎缩; 5.社保汇金入市; 6.大股东和高管增持; 7.机构大幅超配非周期类股票; 8.强周期股在跌时抗跌,涨时领涨; 9.机构仓位在历史低点; 10.新股停发或降印花税。
最近一位同事离职,在践行宴会上,大家聊到投资理财,D瓜哥推荐了 《投资中最简单的事》。去年已经把这本书读完了,下班后把这本书的摘要笔记整理一下,按照章节,分四篇来分享:
《投资中最简单的事》之读书笔记(一):投资理念
《投资中最简单的事》之读书笔记(二):投资方法
《投资中最简单的事》之读书笔记(三):投资风险
《投资中最简单的事》之读书笔记(四):投资心理学
推荐序 天下武林,林林总总。名门正宗如少林武当,诚然名扬天下,而武林之大,但凡修得暗镖神剑者,亦可独步江湖。
即使最成功的投资人,也要心胸坦荡,认识到自我局限,不可以名门正宗自居,须认识到获得真理是一个学无止境、永远追求的过程。
在多数人都醉心于“即时满足”( instant gratification)的世界里,懂得用“延迟满足”( delayed gratification)去做交易的人,已先胜一筹了。
健康的环境和心情是长期修行的结果。
初版序 成长投资的价值支撑主要来自企业未来收入和利润的高增长,更强调公司未来的价值 Vn 要远大于公司现在的价值 V0,但这种投资需要预测未来的远见,只有极少数的人能够做到。
我努力奉行一些简单的原则,例如:
第一,便宜是硬道理。即使是普通公司,只要足够便宜,也会有丰厚的回报。
第二,定价权是核心竞争力。有核心竞争力的公司有两个标准:一是做的是自己可以不断复制的事情,比如麦当劳和星巴克可以不断地跨区域开新店,在全世界成功复制;二是做的是别人不可能复制的事情,具备独占资源、品牌美誉度、专利、技术、寡头垄断地位、牌照准入限制等特征,最终体现为企业的定价权。
第三,胜而后求战,不要战而后求胜。百舸争流的行业,增长再快也很难找投资标的,不妨等待行业“内战”结束、赢家产生后再做投资。
第四,人弃我取,逆向投资。无论是巴菲特、索罗斯,还是邓普顿、卡尔·伊坎,投资领域的集大成者大多数都具有超强的逆向思维能力。
这些规律性的东西虽然看起来是投资中最简单的事,却也是投资中最本质的东西,并不会因为时空的不同而产生大的差异。
第一部分 投资理念 01 以实业的眼光做投资 下跌后,悲痛欲绝;上涨后,欢欣雀跃。两者均无必要。
以买企业的心态做投资,不因急跌而失措,也不因急涨而忘形。
在一个先发优势不断被颠覆、没有永远的赢家的行业里,只有勇于自我否定、因时而变才能生存。
成长是未来的,难预测;门槛是既成的,易把握。
第一,把客户的钱当作自己的钱来珍惜;第二,把二级市场的股票投资当作一级市场的实业投资来分析。
如果用自己的钱做实业投资,首先要考虑的问题就是:这是不是一门好生意。
人们只看到成功的“一将”,选择性地忽视了“枯了的万骨”。
什么行业易出长期牛股?行业集中度持续提高的行业。
用自己的钱做实业投资要考虑的第二个问题,就是这门生意的现金流状况如何,毕竟做生意的最终目的是赚取现金流。
好公司的两个标准:一是它做的事情别人做不了;二是它做的事情自己可以重复做。前者是门槛,决定利润率的高低和趋势;后者是成长的可复制性,决定销售增速。如果二者不可兼得,宁要有门槛的低增长(可持续),也不要没门槛的高增长(不可持续)。门槛是现有的,好把握;成长是将来的,难预测。
用自己的钱做实业投资要考虑的第三个问题就是行业的竞争格局以及公司是否具有比较优势。
作为一个后来者,想颠覆既有的龙头老大的地位,就得看自己能够为客户提供哪些不可比拟的价值,以及相对于竞争对手的比较竞争优势在哪里。
互联网的本质是“人生人”,优势在于能以极低成本服务无数客户,规模效应体现在“人多”,“二八”现象不明显,是典型的散户经济,得散户者得天下。银行业的本质是“钱生钱”,规模效应体现在“钱多”, 80%的业务来自 20%的客户,“二八”现象显著,得大户者得天下,而且那 20%的大客户是需要线下的高端服务的,这就是网上银行至今在欧美日韩都没有很成功的案例的重要原因。
互联网“人生人”主要靠两条:一是网络效应;二靠人多提升用户体验。
中国线下零售的分散和低效是中国线上电商迅速崛起的重要原因。
分析技术变化快的行业时不必看市场占有率,而要看是否适应最新的杀手级应用的潮流。
做投资要研究的就是这些不以人的意志为转移的规律,而不是整天去猜测市场的情绪变化。
宝石被人扔进泥里再踩上几只脚也仍是宝石,砖头被请进庙堂受人膜拜也仍是砖头。
市场的主题炒作往往是短期的,长期起决定性作用的仍然是行业竞争格局、公司竞争优势和定价权。只有坚持以实业的眼光去评估企业的价值,不受市场的极端情绪波动所影响,时间才会是我们的朋友。
02 人弃我取,逆向投资的关键 众人夺路而逃时,不挡路、不跟随。不挡路是因为不想被踩死,不跟随是因为乌合之众往往跑错方向。
新兴行业讲的是需求快速成长的事,不必纠结于供给。而传统行业则只有控制供给,企业利润才能快速增长。
长期看表现好的传统行业要么是寡头行业,要么是淘汰落后产能的行业,二者的供给增长相对于需求而言都受到了有效控制。
很多人认为小股票的成长性普遍好于大股票。如果这是事实的话,那么大多数行业的集中度就会越来越低。
以高估值买新兴行业而落入成长陷阱的是沉迷于“未得到”,以低估值买夕阳行业而落入价值陷阱的是沉迷于“已失去”。投资中风险收益比最高的还是那些容易被低估的“正拥有”。
人弃我取、逆向投资是超额收益的重要来源。
一只下跌的股票是否值得逆向投资的关键在于以下三点:
首先,看估值是否够低、是否已经过度反映了可能的坏消息。
其次,看遭遇的问题是否是短期问题、是否是可解决的问题。
最后,看股价暴跌本身是否会导致公司的基本面进一步恶化,即是否有索罗斯所说的反身性。
买股票之前问问自己,下跌后敢加仓吗?如果不敢,最好一开始就别买,因为价格的波动是不可避免的。
食品饮料是个适合逆向投资的领域。
大家都挤在树上摘葡萄时,也许就是该在地上捡苹果的时候了。
A股的情绪波动容易走极端,因此“人多的地方不去”是至理名言。
牢记管子所说的“不处不可久,不行不可复”,不去“击鼓传花”,不接最后一棒,把选股范围基本限制在低估值的大盘蓝筹里,以此躲过中小盘中的许多“地雷”。
一般说来,趋势的初期和末期,就是真理在少数人手里的时候。
买早了还得熬得住,这是逆向投资者的必备素质。
D瓜哥在前面的文章 使用 Hugo 搭建博客 中介绍了如何用 Hugo 搭建个人博客。部门准备系统地整理一下各个小组的文档。恰好 D瓜哥 对写文档非常感兴趣,正好写个材料分享一下血泪经验。
编辑进化之路 第一代:WordPress 缺点:写作和排版割裂,排版耗时且繁琐
第二代:MarkDown 缺点:方言众多,工具链不够完整。
现在已经改观很多。
第三代:AsciiDoc 轻量级标记语言的优点 思路与格式融为一体 在整理文档时,随手加入格式管理,不需要为格式分心,也无须浪费时间调整排版。
代码高亮 AsciiDoc 与 MarkDown 都支持
/** * @author D瓜哥 · https://www.diguage.com/ */ public class Main { public static void main(String[] args) { System.out.println("Hello, D瓜哥!"); } } 文本格式 文本格式,天然跨平台,支持性好,方便编辑与管理。
结合 Git,支持版本管理。
生态完善 Markdown Hugo: The world’s fastest framework for building websites — Hugo 使用 yuin/goldmark: A markdown parser written in Go. 来做转换工作。也支持 AsciiDoc,不过需要挑选比较合适的主题: Hugo Themes。
AsciiDoc Antora — The multi-repository documentation site generator for tech writers who writing in AsciiDoc.
Asciidoctor Diagram — 支持多种文本画图工具。
Asciidoctor EPUB3 Documentation — 可以直接将 AsciiDoc 文档转化成 EPUB 电子书。
Asciidoctor PDF — 可以直接将 AsciiDoc 文档转化成 PDF 文档。
常见插件的支持:Maven、IntelliJ IDEA、VS Code 等。
前几年应大势所趋,使用 Let’s Encrypt 给所有网站都上了 HTTPS。因为去年年中把博客托管到 GitHub 上了,导致一起申请 HTTPS 证书的站点无法按时更新证书。所以,所有证书都过期了。前几天有朋友发消息问我,Byte Buddy 的中文文档是不是我搞的?正好借机把证书更新了一下。
此后不久,无意间查看了一下网站服务器的操作系统和 Nginx 版本,发现竟然是 Ubuntu 16.04 + Nginx 1.12。Ubuntu 16.04 都”过期“了,正好得空升级一下。
升级操作系统 以前没有升级过操作系统大版本,正好借此机会练手:
# 升级操作系统版本执行,先做一下常规升级 sudo apt-get update sudo apt-get upgrade sudo reboot # 检查可以升级的版本 sudo do-release-upgrade -c # 开始升级 sudo do-release-upgrade 升级完成后,检查操作系统版本:
$ cat /etc/os-release NAME="Ubuntu" VERSION="20.04.3 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.3 LTS" VERSION_ID="20.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=focal UBUNTU_CODENAME=focal 有几点需要注意:
LTS 版本升级,只能一步一步升级,从 16.04 升级到 18.04,再从 18.04 升级到 20.04。不能跳级。
升级过程不能中断,需要逐步确认。
如果升级中断,系统就会处在一个中间阶段,不能升级,不能重启(我遇到的情况)。需要人工介入处理,继续升级完成才行:
sudo dpkg --configure -a # 执行上述命令失败是,删除两个锁文件,再次执行即可 sudo rm -rf /var/lib/dpkg/lock sudo rm /var/lib/dpkg/lock-frontend sudo dpkg --configure -a sudo apt-get update sudo apt-get dist-upgrade sudo do-release-upgrade sudo reboot