导言 本书的目的 第一章 投资与投机：聪明投资者的预期收益 第二章 投资者与通货膨胀 第三章 1972年初的股价水平 第四章 防御型投资组合 第五章 防御型投资组合中的普通股 第六章 积极型投资组合本文总结自2011年，[美]本杰明·格雷厄姆的书籍-《聪明的投资者》（实际成书，第一版在1949年，此版在1971年），请支持正版图书。本文首发于个人博客https://lisper517.top/archives/4423/，转载请注明出处。投资有风险，入市需谨慎。导言 本书的目的短线、投机者、技术分析，基本采用的方法都是上涨买入、下跌卖出，长期来看是荒谬的。本书将投资者分为防御型（被动型）、进取型（积极型），前者的主要目的是避免重大损失，并且不想在投资上付出太多精力；后者则愿意为超出平均水平的回报而在投资上付出精力。一种价值投资的观点认为，可以先找出最可能增长的行业，再挑出其中的头部公司。但想事先找到这种行业的困难远超想象，一个例子是航空股。航空业的运输量快速增长，但投资回报却极低，原因是内卷式竞争、产能过度扩张（进入门槛低，无护城河——看起来很像光伏）。要记住，行业增长≠投资能获得回报。本书目的是为读者建立一套令人安心的投资策略，因为投资最大的敌人实际就是自己。即使是好公司，买入时也要警惕过高的价格——投资应该像买菜一样斤斤计较，而不应像买奢侈品一样不讲价还价。另外一个建议是购买市值不超过有形资产价值太多的股票（PB市净率不要超过1太多），这种保守策略可以尽量减少损失。另外需要注意，本书并不包括全面理财建议（包括储蓄、保险等），而仅仅探讨股票、债券。美股与A股的一点区别是，美股有约20%资本利得税，中国没有。第一章 投资与投机：聪明投资者的预期收益投资与投机的区别：投资是以深入分析为基础，确保本金的安全，获得适当的回报；否则就是投机。根据这样的原则，进行杠杆交易（保证金），追高，都是投机。如果想尝试，可以用极少量资金、单开一个账户试试投机。一、防御型投资者的预期收益1.1949-1964年本书6年前的版本，建议防御型投资者配置25-75%的债券，剩余的资金配置蓝筹股（规模巨大、经营稳定、业绩优良、在行业内占据主导地位，且长期具有良好声誉的大型公司股票。此处以道琼斯30为例），并在比例偏差过大时调整至预定的仓位。另一种策略是，若其中一种已处于危险的高位，或者处于有很强吸引力的低位时，调低或调高比例。按债券和股票对半分配，1949-1964的实际美股收益年化为6%左右（税前）。另外，如果此时期全部投资于股票，则年化率会大大高于10%，但股价多年上涨意味着“现在已经太高了，未来的收益将变差”。2.1964-1970年此时期，最高等级债券的利率从1964的4.5%，在1970达到了创记录的高位-7.5%，因此持有股票的收益低于债券。这再次证明资本市场无法预测。3.1972年初的预期投资策略1971年底，优质中期公司债券的税前收益率可达8%，短债的收益率（美国5年国债）也能达到6%；而道琼斯指数的股息率仅为3.5%，算上平均4%的增值收益后为税前7.5%、税后5.3%左右。综合来看，债券收益更高，因此看起来应该将全部资金投入债券，除非以下情况：（1）通货膨胀加速，使股票增值收益更高。（2）上市企业利润大增，并且不出现通货膨胀（低概率）。（3）股市即将迎来投机浪潮。因此，更稳妥的做法当然还是股债各配置一定比例资金。长期来看，投资者无法通过任何新股、热门股而获得超额收益，反而会亏损。4.三种补充做法（1）购买一支地位稳固的投资基金（市值大，时间长），以代替自己亲自构建股票组合。（2）利用共同信托基金或混合基金（可能是指股债混合基金）。（3）定额定投，程序化投资。二、激进型投资者的预期收益市场并不奖励勤奋，投入大量时间精力并不意味着能比防御型投资获得更高收益。因此，激进型投资者首先要清楚哪些行为是不可取的。常见的投机行为包括：1.追涨杀跌，或者做空。2.短线操作，买入一些短期内有利好消息的公司。3.长线择股，选择过去表现良好的公司，或者预计将有高盈利能力的公司。逻辑上说，想获得优于平均业绩，必须采用：（1）具有内在稳健性和成功希望的策略。（2）在专业投行不流行的策略。由于存在很多的特殊情况，作者认为老手可以承受很低风险，并获得20%年化（目前看来只有巴菲特做到），但最近这种机会似乎已经消失。过去，老手可以寻找的操作有：（1）不同证券的交叉套利。（2）资产清算，某些保护性对冲等。（3）资产并购，此时并购方往往会提出比公告日股价高出一定幅度的报价。但最近并购的收益不再稳健，开始出现亏损。（4）贱买贵卖，但1949年后似乎不再适用。（5）道氏理论（一种技术分析方法），在1897-1933年表现良好，但1934后失效。（6）捡烟蒂，比如购买廉价证券（PB<1），但1957后的十年间这种股票消失了。不过，1970年的股市低点时又开始出现。第二章 投资者与通货膨胀不要否定债券或股票，因为股票收益高而仅偏好股票，或者因为债券稳定而仅偏好债券，都是不可取的。观察1915-1970的历史，发生过许多次通货膨胀，最严重的是1915-1920期间，生活费用几乎上涨了一倍；1965-1970则上涨了15%。在1920-1965期间，有过3次价格下降期，6次不同程度的价格上涨。平均下来，通货膨胀每年为2.5%，1965-1970为4.5%。政府目前（1970）的政策是强烈反通货膨胀，因此未来几年可以假定通货膨胀率在3%。另外，通货膨胀率与股债收益并无明显关系。长期来看，股票的收益是高于债券的，那为何不只买股票呢？（1970年过去几十年，道琼斯、标普500的年化率8%，债券较低，但1970年时出现了一些年化8%的债券）这个问题需要从长期（25年）与中短期（5年内）来看。一、通货膨胀与公司利润新手可能会认为，通胀意味着公司利润上涨，进而反映在股价上。但根据历史数据，通胀与公司股价并无直接关系。当然，从大的方向看，通胀常常意味着经济发展，企业进入好年景，但对股价影响不大，这可能是因为工资成本增加等原因。另外需要关注的是公司债务。1950-1969年间，公司债务增长了4倍，但税前利润仅增加了一倍。有观点认为公用事业公司是通胀的受大受害者：①债务成本大幅上升。②价格管制，无法提价。但水电气成本的增长，远低于通胀率，因此未来这些公司将处于很强的战略地位。即使长期看涨，短期甚至中长期内股票的收益总是无法确定。比如，自1929-1932股市崩盘，通用电气、道琼斯指数耗时25年才重回高点。如果仅买入股票，投资者很可能被股市涨跌影响而误入歧途。二、股票外的抗通胀方法1.购入黄金是全球各地抗通胀、保值的标准策略。但1937-1972年的35年间，黄金的价格仅从35$/盎司涨到48，涨幅仅35%，甚至不如存银行。黄金实物的持有者无法获得资本收益，反而要支付维护费。2.也有名画、邮票、古董等，但入行门槛较高。3.房地产，但其价格同样不稳定，买家可能在地理位置、价格等方面犯错，而且单笔购入资金较多、较难小额购买。三、结论总的来说，投资者既不该仅投资债券，也不该仅投资股票，因为单独持有其中一种的风险较高。第三章 1972年初的股价水平本章主要通过回顾1871-1971年的历史数据，推断1972年的股市价格水平。下图（有些图做的不知所云、就不放了，仅给出标普指数图。这章里的一些数据也对不上，不知所云）包括考勒斯指数（标普500的前身）与道指。可以注意到，1900-1970包括3个不同的阶段、每个各占1/3：1.1900-1924，由一系列走势相似的3-5年周期组成，此时期年化3%。2.1925-1949，自从1929大萧条后，股市以不规则波动一直持续到1949，此时期年化1.5%。此时期结束时，公众对股票的兴趣已降至最低。3.1950-1971开启的牛市，其中1949-1968年曾有过较大回撤，但1968年标普指数达到顶峰、年化达到了14%。以10年期观察，总体上涨。但1970年美国公司整体利润出现恶化，许多公司出现亏损、破产，因此作者认为大繁荣的时代已在1970年结束。另外值得注意的是PE达到了15-18的水平。总的来说，无法判断1970以后的走势，可能涨也可能跌。第四章 防御型投资组合有观点认为能承受的风险越高、潜在回报越大，作者则认为收益与花费在投资上的精力、智慧相关（笔者认为运气比智力重要的多）。一、股债配置的基本问题建议股票持仓25%-75%，比如股债各配一半。如果能精确低买高卖，可以增加股票比例，可惜没人能做到。当一方上涨使比例差距超过5%时进行调仓。二、债券的构成主要考虑购买含税/免税债券，以及长期/短期债券。中国不用考虑有无税，主要考虑长短债。（1）E系列、H系列美国国债优点包括：①本金与利息的支付有绝对保障。②可以在任何时候赎回。③在至少10年期间，获得至少5%利息。④最初几年不会跌破本金。（2）其它联邦政府债券，州和市政债券品类众多，类似地方政府债（要谨慎。26年有一支3%年化的债券暴雷，就是因为标的资产为XX债）。（3）公司债券（4）储蓄存款（5）可转债另外需要关注的是债券的赎回条款，有些霸王条款导致发行机构能以低于市值的价格赎回。建议宁肯利率低一点，也不要购买短期内可赎回的债券，而要买发行20年后才能赎回的债券。三、不可转换的优先股好的优先股确实存在，但这种工具本质上是不好的。优先股的安全性取决于公司支付普通股股息的能力和意愿，优先股既没有债权人的法定求偿权，也不能像普通股一样分享公司利润。总的来说，优先股仅适用于进取型投资者，且只应该在跌至不合理的地位时买入。另外，美国法律关于税收的一些规定，也使得优先股更适合机构投资而非个人投资。四、证券的类型包括可转换的同类债券和收益债券，后者只有在公司有利润时才支付利息。优势包括：（1）只要公司有利润，就可以无条件获得利息。（2）如果没有利润或不支付利息，除了破产保护外还有其它的保护形式。收益债券的安全性高于优先股。第五章 防御型投资组合中的普通股一、普通股的优点（1）股票很大程度上使持有者免受通胀损失，债券则完全不能提供这种保护。（2）普通股可为投资者提供较高的年化。但仍要勿在高点买入，比如1929后过了25年，股市才恢复元气。二、普通股的投资规则1.适当分散化，持股数量应限制在10-30支。2.选择蓝筹股——大型、知名、财务稳健的公司。3.选择长期分红的公司。4.控制市盈率范围在25以内。这样的规则排除了高成长公司。三、成长股与防御型投资成长股指显著高年化的股票，特点是价格、PE一般都较高。典型例子是IBM，在1961-1962、1969-1970曾下跌50%。总的来说，虽然成长股的利润率诱人，但并不适用防御型投资策略。四、投资组合的改变可以咨询一些专业的经纪公司，并阐明自己的选股选择。（不知道是否适用中国）五、定投法目前可能尚无比定投法更好的投资法。六、投资者的个人情况（1）拥有20w美元，并以此养活自己和子女的寡妇。（2）拥有10w美元的中年医生，且每年还能额外剩下1w。（3）周薪200，每年剩下1000的年轻人。如果无法在投资方面付出相当程度的时间精力，那么最好还是选择防御型策略更好。最好年轻时开始投资，承受的损失有限。七、关于风险一般来说， 优质债券 < 优质优先股 < 优质普通股 。但是风险与安全性有很大的差别，判断一项投资的安全性，唯一标准是能否按时还本付息，而非某一时间点的价格。八、蓝筹股大型、知名、财务稳健的公司，且长期分红。（1）大型、知名，资产或营业额不低于5000w美元，规模至少位于行业前1/3。（2）财务稳健，对工业企业来说，市值至少应该是总资本（含银行债务）的一半；对铁路、公用事业公司来说则是至少30%。以上的标准只是参考，具体可以由投资者自行选择。第六章 积极型投资组合
小狗钱钱1 小狗钱钱2本文总结自2014年，[德]博多·舍费尔的书籍-《小狗钱钱》（四川少年儿童出版社），请支持正版图书。本文首发于个人博客https://lisper517.top/archives/4414/，转载请注明出处。投资有风险，入市需谨慎。这是一本童话书，主要是家长和儿童一起看，培养理财观念。小狗钱钱1前言本书主要讲了“钱钱”（一只会说话的狗）教一个12岁女孩（吉娅）理财的故事。第一章 白色拉布拉多犬吉娅救了一条狗“钱钱”，这条狗会心灵感应说话。钱钱让我列下10条最想实现的愿望。第二章 梦想储蓄罐和梦想相册钱钱让我从中选出3条最最重要的愿望，如下：1.参加美国夏令营。2.一台笔记本电脑。3.帮助父母还清债务。钱钱让我每天看这3条愿望，并且找一些图片（比如美国风景之类的），做一个梦想相册，每天翻看提醒自己。很多人只是口头上有愿望，但从没有认真行动过。不要问能不能做到，而要相信一定能做到。并且为前两个愿望各自准备了1个梦想储蓄罐。不改变理财观、单纯增加收入是没用的，支出会和收入同步增长。第三章 达瑞，一个很会挣钱的男孩首先要相信自己能做到，才会真的开始去行动。赚钱的关键：一是为别人解决问题；二是把精力放在自己知道、能做的事情上。不要拿国别、地域做借口。一个叫达瑞的男孩做了这些事情：1.帮人取报纸，将报纸从报箱塞到房门底下，人们可以免受寒风。每月1$。2.帮人丢垃圾。每月1$。3.喂宠物、看房子、浇花。4.9岁时，用电脑写广告。5.雇佣别的孩子，花费一半。6.受出版商、电视台邀请。第四章，堂兄的挣钱方法堂兄的方法是面包配送。吉娅也想到了好办法，帮人遛狗。堂兄的建议：1.一份工作不太保险，多找些更有保障。2.遇到困难不要退缩，遇到顺境也不要得意忘形。顺风谁上都一样，逆境才能检验一个人。3.只有做自己真正喜欢的事情，才能获得成功。4.不要羞于谈钱，不要因为正当追求财富而感到羞愧。第五章 钱钱以前的主人钱钱以前和主人（金先生）一起开车时遭遇车祸，才被我们捡到。原主人请求我们暂时照顾钱钱，并每月去疗养院探望他。第六章 爸爸妈妈犯的错误给陷入债务问题的人的忠告：1.不用信用卡，因为用信用卡往往比用现金花钱更多。2.尽可能少地还贷款，即分期贷款，这样每月剩下的生活费更多。3.对于消费贷款，将每月剩下生活费的一般作储蓄，另一半还消费贷。如果可以的话，不要申请消费贷。4.每次花钱之前想想自己的梦想，花这笔钱真的有必要吗？第七章 金先生家金先生要支付过去一年我照顾钱钱的费用，并且要求我至少存一半。如果有一只会下金蛋的鹅，就不应宰了它。储蓄、投资就像鹅，得到的现金流就是金蛋。花了非必要的钱，就是杀死了这只鹅。第八章 陶穆太太我帮助陶穆太太在外出度假时看管她的狗，陶穆太太是理财高手。第九章 冒险经历堂兄帮我开了一个银行账户，回来时我们发现陶穆太太的房子被盗。第十章 在地下室我们在地下室发现了陶穆太太的一大笔钱、金饰品，没有被盗。然后警察来了。第十一章 爸爸妈妈不明白我帮爸爸妈妈和金先生安排了一次会面。第十二章 陶穆太太归来要想过的更幸福，人应该改变自身，而与金钱关系不大。幸福的人有钱会更幸福，悲观的人有钱会更不幸。金钱不会使人变坏，而是放大原有的特质。帮我开银行账户的海内女士，邀请我在学校演讲如何理财。第十三章 巨大的危机因为拖欠房贷，银行正在考虑收回我们的房产。与金先生交谈后，每月房贷下调了32%，并且爸妈将扣除生活费后的一半进行储蓄。第十四章 投资俱乐部穆陶太太、我、堂兄、我的朋友，一起组成了投资俱乐部“金钱魔法师”。我们约法三章：1.把钱投资在安全的地方。2.在安全的前提下，尽量追求高回报。3.投资应该简单明了。首先讲解股票，股票获利的方式包括：1.分红。2.股票涨价后卖出。第十五章 演讲我的演讲很成功，并且也有出版商找到了我。第十六章 俱乐部的投资行动陶穆太太向我们介绍了基金。买入基金，基金管理人会投资卖股票或者其它东西。如果打算购买基金，要准备长期持有5-10年。基金的挑选原则：1.至少10年历史。2.选择大型、跨国股票基金。3.比较基金走势图，选择年化率较高的。第十七章 爷爷奶奶害怕风险过了一段时间，我们的基金下跌了25%，但陶穆太太劝我们逢低买入。我想拿爷爷奶奶为我攒的嫁妆钱，但他们不肯。金先生劝我拿一部分钱继续买基金，另一部分留作现金。第十八章 大冒险的结局我成功买到了笔记本电脑，爸爸妈妈也解决了贷款问题。钱钱后来再没有和我说话。小狗钱钱2讲的更多是人生哲理、冒险情节而非理财知识，略。
《富爸爸穷爸爸》-[美]罗伯特·清琦，[美]莎伦·莱希特
序言 第一章 富爸爸，穷爸爸 第二章 富人不为钱工作 第三章 为什么要教授财务知识 第四章 事业与职业 第五章 税收的历史与公司的力量 第六章 富人的投资 第七章 不为钱工作 第八章 克服困难 第九章 开始行动 第十章 更多的事情本文总结自2013年，[美]罗伯特·清琦、[美]莎伦·莱希特的书籍-《富爸爸穷爸爸》（四川文艺出版社），请支持正版图书。本文首发于个人博客https://lisper517.top/archives/4404/，转载请注明出处。投资有风险，入市需谨慎。笔者是感觉书中的内容有些过时，作者偏好高风险资产、房地产，但是举例集中在95年左右，没有经历08年验证（小周期与大周期）。书中的例子，15w美元房子租金每月1000，售租比150；中国150万可能2000，可能750。根据网络搜索，作者在08年危机之前撤出、持有现金，并抄底优质资产，不知道真假。不论如何，书中的内容还是有一些借鉴意义的。序言“好好学习，找份好工作”是大多数人的固有认知，但理财训练也很重要，并且难以获得。第一章 富爸爸，穷爸爸穷爸爸（亲生爸爸）受过良好的教育，但财商不高，一生清贫；富爸爸（好友迈克的爸爸）教育程度不高，但有富人的思考方式。第二章 富人不为钱工作富爸爸（当时还不富有）提供给我和迈克一份工作，到他的小超市工作，每周六工作3小时、每小时10美分。工作3周后我决定退出，迈克却说，富爸爸说如果我要退出时就带我去见富爸爸。穷人、中产阶级为钱工作，因为这些人寻求稳定，害怕付不起账单、害怕被解雇。之后富爸爸再次让我继续之前的工作，但这次连薪水也没有了。又工作了几周，富爸爸再次与我和迈克谈话。大多数人的生活是上班、获取薪水，然后消费、付账，如此重复。收入提高，支出也提高，循环往复。一些富有的人也没能逃脱这个循环，而且往往比之前贫穷时更加恐惧了。贪婪、恐惧，大多数人被感情而非思考驱动。实际上，钱并非真正的财富。之后我和迈克继续免费在小超市工作。后来我们发现了商机，小超市会把过旧的绘本扔掉处理，而我们把这些绘本收集起来向周围的孩子们收费开放。但后来因为流氓骚扰，阅览室关闭了。不过这就是我们上的第一堂课。第三章 为什么要教授财务知识最大的财富并非钱，而是所受的教育，灵活的头脑，因为知识方可创造财富。想要致富的第一步，是学习财务知识（打下稳固的地基）。首先要明白的是资产和负债的区别，并购买资产，这是唯一的规则。大多数人搞错了资产和负债的概念，穷人得到负债却以为是资产。资产就是能产生现金流的东西，负债则会持续让你花钱。由于穷人的观念根深蒂固，因此他们有钱之后总是购买负债，导致收入增加的同时负债也增加。比如说，一对新婚夫妇，一开始住在拥挤的公寓，但二人都有工作。随着薪水的增加，二人换更大的房子、买车、家具，孩子出生后又需要更加努力工作……这是一场无法终结的“仓鼠赛跑”。房子是负债而非资产，花30年偿还现金流是非常愚蠢的。房子并非总是升值，而且还要考虑机会成本（现金流贴现）。机会成本，比如100元拿来买年化2%的货币基金而非买房，一年后拥有102元——因为金钱是随时间增值的，现在的100元等于一年后的102元，现在的102元等于过去的100元；如果购买房子，除了损失2%的无风险年化收益，还要支出购买家具、维修、水电费。不要过早买房，而应该早早开始证券投资。买房是可以的，但在买房之前要先买入资产，让资产创造的现金流能覆盖房子的支出。房子也可以替换成其他负债，像跑车、潮流单品……收入和负债等比例增大，而却没有资产，结果就是为老板、政府（纳税）、银行（贷款）工作一辈子。财富，是支持一个人生存多长时间的能力。换言之，如果今天开始停止工作，你能存活的时间长短，可以衡量你目前的财富。第四章 事业与职业职业和事业的区别，职业的重点在于收入项，你可能作为老师、医生、律师等来获得收入，这些是职业；你的事业则由你的资产决定，你可能投资房地产、股票、开公司等等。你需要照常工作，但同时也要选择自己感兴趣的事业（资产）。真正的资产可以分为：（1）不需要本人到场也可以赚钱的业务。如果必须自己到场工作，那就是职业而非事业。 （2）股票，债券，基金。 （3）可产生收入的房地产（租金？）。 （4）票据（放贷？）。 （5）版权，如音乐、书、专利。 （6）其它可产生收入，或有增值潜力的东西。当你的现金流增加时，可以购买一些负债（奢侈品）。穷人与富人的区别之一，就是富人只会在最后才买负债，而穷人过早购买负债、只是为了让自己看上去很富有。第五章 税收的历史与公司的力量劫富济贫是美好的童话，实际上税收是将中产阶级的财富转移给穷人，富人税负很少。英国和美国早期是不纳税的，只有一些因战争而临时征收的钱。在1900年左右，慢慢培养起了公众缴纳所得税的意识。大众赞成收税，是由于误以为税收有劫富济贫的意味，但实际上中产和穷人受到税负更多，富人总有办法从税负中脱身。成立公司（无实体公司）是富人避税的常用手段，雇佣会计、律师，因为要支付的工资远远小于向政府缴纳的税收。财商的构成包括4个方面：1.财务知识，帮助你读懂财务报表，辨别一项生意的优势和劣势。2.投资，包括大的策略、具体方案。3.了解市场，供需关系、基本面（一项投资的经济意义）。4.法律，其作用有：减税优惠，诉讼保护。第六章 富人的投资要获取财务知识，既要学习，又要有足够的勇气、不畏难。遇到一次致富的机会，需要你去主动寻找机会，需要有足够的钱，需要意识到这个机会的价值。在市场恐慌抛售时，应该买入被低估的好资产，而非储蓄。实际上，人的一生中会遇到很多足以致富的机会。在房地产市场萧条时，我曾经到破产事务律师办公室或法院寻找，比如一幢7.5万元的房子，此时可以2万拿下，转手以6万卖出。我主要做这样的房地产事业，也会投资股票。（在中国可能很难复制，可能做法拍房？但作者后面提到，在世界各处都能这样做，不要畏难）投资者分为两类：1.最普遍的人，进行一揽子投资，通过房地产公司、股票经纪人等。2.自己创造投资机会的投资者，自行组织一项交易。第二种投资者最可能称为职业投资者。要成为第二种投资者，还需要具备以下能力：（1）寻找其他人都忽视的机会。（2）如何增加资金。多数人只会找银行贷款，但有时你可以通过其它方法“借”到资金。（3）把精明的人组织起来，为你工作或和你一起工作。第七章 不为钱工作人们在职业上普遍追求专业化，认为想要获得更高的收入、就要对当前的职业技能深入研究。但如果想致富，知识的广度更重要，很多知识了解个大概即可，因为技能越单一、越专业化，越容易陷入一种职业选择。对年轻人来说，在找工作时不只看工资，还应看能学到什么，年轻人有试错的时间。应该掌握的最重要技能是销售、市场营销。第八章 克服困难掌握了财务知识的人有时仍无法致富，可能因为以下5个原因。一、恐惧对亏损的恐惧。不要恐惧、回避，风险越大、潜在收益越大。如果你不害怕失败，那失败就只会变为成功路上的插曲。大部分人进行均衡投资，但想快速致富的方法就是集中一点（小资金想快速翻倍就要梭哈，但是小心风险），这尤其适合起步的年轻人。二、愤世嫉俗杞人忧天，自我怀疑。开始行动比忧虑重重好的多。三、懒惰不要习惯性用假装忙碌来回避问题。不要质疑自己能否做到，而要问自己如何做到。学会用贪婪克服懒惰。四、不良习惯先把钱留给自己，再把钱留给别人。笔者举一个小例子，每月工资到了不要急着提前还款，而是把钱先转入货币基金等获取收益，到时间再还信用卡。五、自负如果知道自己在某个问题上有欠缺，就应该学习精进，而不是用自大来掩饰。第九章 开始行动如果不知道如何致富，可以尝试以下的步骤：1.精神的力量大多数人都“想要”致富，但他们的意愿还不够强烈。你需要一个强有力的理由，想要环游世界、想要自由自在；不想要工作一辈子，不想要为了房子车子耗尽一生……2.选择的力量现在开始选择学习，唯一真正的资产是你的头脑。不要急着投资，而先学习如何投资。学习不同的观点，即使你现在并不认同。3.关系的力量慎重选择朋友，朋友的关键在于能从他们身上互相学到什么，而非有无钱财。4.快速学习学习什么，就会成为什么。5.先控制自己先控制自己，才能控制财富。控制购买负债的欲望，先购买资产。6.雇佣聪明人给专业人士优厚的报酬，律师、会计、房地产经纪人、股票经纪人，付给这些人的钱只是你能赚到的钱一小部分。但是也要挑选合适的人，真正聪明的人。7.无私的力量投资总是有亏有赚，投资前要确定自己的回报。8.用资产购买负债把购买豪车、住房的欲望转换为动力，在你拥有足够的现金流之前先买资产而非负债。9.榜样的力量树立投资榜样，沃伦·巴菲特、彼得·林奇、乔治·索罗斯、唐纳德·特朗普、吉姆·罗杰斯等等。国内可以看看段永平。10.给予的力量先付出才能获得回报。第十章 更多的事情先停下忙碌的工作，评估一下哪些做法有效、哪些是无用功。其它建议：（1）低价买入，高价卖出，不要追涨杀跌。当你买入的的时候，未来（2）先寻找需要买进的人，再去寻找卖家。（3）寻找需要一起买入的人，大额买入，以便从卖家处拿到优惠。（4）从小交易入手，逐渐做大。
前言 第一部分 有的人冲动，有的人沉稳 第二部分 判断大势的风向标 第三部分 有时需淡泊，有时需勇气 第四部分 股市杂谈 第五部分 我眼中的大势（2007-2024） 问题本文总结自2025年，李大霄的书籍-《李大霄投资战略（第三版）》，请支持正版图书，做好人买好股得好报。本文首发于个人博客https://lisper517.top/archives/4388/，转载请注明出处。投资是一场修行，投资观念反映了人生观、价值观。建议特别关注 b站-李大霄 。前言股票投资是反人性的，在低位买入、高位卖出，人生哲理。一般来说投资需要按风险从低到高，依次从货币基金、债券基金、混合基金、指数基金、股票基金、蓝筹股历练。投资市场看似没有门槛，但其实准入要求极高。不可辞职炒股，不可上杠杆，坚持价值投资、余钱投资，坚定立场、眼光长远。第一部分 有的人冲动，有的人沉稳一、投资品种的选择与风险投资品种按风险、收益从低到高排序：（1）银行存款，货币基金（2）国债，保险产品，债券基金，企业债券（3）混合基金，指数基金，股票基金，蓝筹股（4）三板，创业板，三线股，二线股（5）期货，外汇，权证（高杠杆）杠杆率越高、风险也越高，比如外汇最高杠杆率可达400倍，股指期货一般6-12倍。普通人不要上杠杆，能管理好自己的财富已属不易。二、投资首先应“不差钱”（一）确定目标投资前应先想好目标，可能的风险、能否承受，投入资金规模，后续有无补充资金。（二）流程控制1.财力用作投资的钱一定是扣除必要生活支出，且保留一些应对突发情况的救急钱，剩下的钱才可投资。2.投资时间年轻人与老年人的投资风格，前者时间充裕、可接受稍高风险，老年人则需要降低波动和风险。3.性格冲动、沉稳，果断、犹豫，是否喜欢风险，不同的性格会造就不同投资风格。三、投资而非投机投资需要符合投资条件，具备投资水平。投机需要市场有投机氛围，并且掌握投机技巧。初级阶段投资者往往缺乏耐心，有投机倾向。四、“坐轿”与“抬轿”“坐轿”者买入好股票后不动即可获取可观收益，“抬轿”者常做短线、快进快出。建议还是“坐轿”，省心省力却事半功倍。五、财富的转移1.投机时，财富从小机构流向大机构，从新股民流向老股民，从散户流向庄家，低技巧者流向高技巧者，心态差、无耐心者流向心态好、有耐心者，但有时也可能相反。2.投资时，价值投资，上市公司将公司做好、利润做多，投资者与公司共同富裕。一些公司从上市就开始毁灭，因为从来不分红、不创造回报。另外一点是要与国家利益一致（为国接盘，为国高位站岗）。六、少交易与频繁交易资金少、无耐心者往往频繁交易，但交易的最高境界应是少交易，低位买入、高位卖出。七、体力与智力的比拼平时锻炼、养好身体，关键时刻才能思维敏捷。多了解股市知识，不要在一知半解的情况下投资。拓展投资眼光，从A股到港股，进一步到美、日、欧、澳。八、股市赚钱概率股市通常是1赚2平7亏，1成人赚、7成人亏，2成人不赚不亏、白花精力。做医生、工程师等其它职业都需要长时间的学习与时间打磨，投资也是一样，成为合格的投资人需要长时间学习实践，隐性准入门槛很高。九、市场的周期1.做股票的长期持有者巴菲特的长期投资、价值投资并非持有不动，而是对上市公司的情况有非常清晰的了解，才能在较低的价格买入，做好等待10年的准备。2.做错要认及时止损。如果买入好股票，你的损失能更小。3.企业的生命现在社会较浮躁，很多上市企业只追求六七年而非百年老店，不应跟风炒作。十、巴菲特与价值投资其投资理念总结就是：在最低价格买入，然后耐心等待。1973、1982、2008年，每次股灾恐慌时巴菲特就会大举购入股票，如果没有好标的则更多持有现金。精华有三：一是不贪婪，卖在人声喧哗处。二是不跟风，勿追涨。三是不投机。十一、李嘉诚略。第二部分 判断大势的风向标一、股市的4大风向标1.上市公司的买卖时机上市公司大量减持或大量增持时。2.中石油中石油是否购入股票。3.汇金公司中央汇金投资有限责任公司，俗称国家队、汪汪队。4.社保基金社保基金是否入市。二、其它市场除了A股，也要关注货币、资源、重要商品市场。1.货币市场港币对A股影响较大，因此主要看港币。汇率制度的波动范围窄，上方（卖方）、下方（买方）通过卖出或买进美元来维持汇率稳定。从美元对港币的波动，可以看出香港政府对港币还是对美元的需求更强。从2010年态势看，港币量已经非常大，到了强下方兑换的区域，说明香港资金量非常充裕。2.资源市场在2008年之前澳元非常便宜，因为澳洲的资源便宜。澳股资源股价格便宜，而A股有色金属较贵。但由于资源的稀缺性，外汇储备可能会增加一些实物、股权。3.重要商品价格主要是原油、粮食。美元与原油一般是反向关系，原油的特点是上涨时间长、高位下跌快。粮食在居民消费物价指数中的权重较大。三、政策动向1.重大政策出台的动向2.关键言论关注《人民日报》、新华社的社论，当前我国的周期，准备施行的经济政策等。3.与国家站在一起为国接盘。四、估值水平过高时需要摘“熟苹果”1.判断估值正常股价不应偏离公司的内在价值过多，我们要做的就是在低估时买入、高估时卖出。2.警惕估值过多偏离五、重大历史事件的提前量比如2008年奥运，很多人认为会涨。但这种重大历史事件需要提前8-12月，至少6个月卖出。六、B股B股有也有沪深两市，深B股用港币，沪B股用美元。随着人民币国际化，B股有很大的投资机会。在普通的证券营业部就可以开通B股。第三部分 有时需淡泊，有时需勇气一、讲与听-3000点需要坚持忠言逆耳，不能光听自己喜欢听的，同时要判断讲话者的意图、寻找过往发言来验证。想要获利需要在低点买入，但大部分人的通病是越高越买。二、警惕“舆论一边倒”所有人都说要继续跌或者还要涨的时候，往往是反转的开始。三、要承受不被认同的孤独人总是喜欢抱团的，股市也因此经常出现群体性的行为。但必须克服从众心理，才能获得成功。如果夫妻都买股票，最好账号分开，买卖也不要争论讨论。四、投资要经得住考验最容易放弃的是长期下跌，涨回一点点，很多人就急着卖出保本。行百里者半九十，选择了好标的就要坚持判断，不要倒在黎明前。五、墨菲定律真理往往在独立思考的人手中。1664点需要勇气买入，6124点需要淡泊卖出。六、追涨杀跌切忌切忌。过去表现不代表未来。七、淡泊和勇气高位需要淡泊，低位需要勇气。不要试图赚走所有钱，把鱼尾留给别人，让别人也能赚一些。八、乐观才能胜出不要对股市失去信心，长期来看总是向上的，只有乐观才能胜出。暂时失利不代表什么，关键是能否吸取教训。九、坚持是艰难的坚持价值投资，做波段是很难的。十、把钱交给有正面作用的公司首先要思考自己是什么样的人，然后要了解自己投资的公司。要做对社会有贡献的人，投资对社会有贡献的公司。第四部分 股市杂谈一、投资方法与社会效率投资如何赚钱？甲赚乙，乙赚丙，这就是一个零和、负和游戏。好的方式是企业做大做强，投资人分享企业发展成果；投资人也能安心工作，这对社会有积极影响。二、正确选择和理解股票评论A股只有做多没有做空机制，因此看多的评论更讨人喜欢，券商评论员也可能常常诱导看多，市场缺乏独立评论员。而且，看空容易树敌，被他人指责，更导致市场缺乏看空的声音。从另外一面看，当市场寒冬时，看多的声音就显得难能可贵。三、赌经济还是赌政策经济下行，但政策利好，应该相信经济还是政策呢？在中国，政策的力量可能更大（无形的大手 VS 有形的小手？）。四、李大霄的风格和追求略。五、寒冷不会永远持续坚持投入，一个人钻研某个方向二十年，总是能有所成就。六、牛市和熊市的回忆1.话题熊市时大家聚会总是对股市避而不谈，牛市时大家总是积极讨论。2.联系熊市中，李大霄接到的电话、邮件、短信少，牛市相反。3.目标熊市中大家对货币基金格外青睐，却对真正合适价位的好股票视而不见；牛市大家对过高的股价视而不见，10%年化都觉得太低。4.电视和报纸熊市中电视、报纸减少股市报道，牛市时媒体纷纷开设证券栏目。5.现场股评略。6.招聘熊市时证券从业人员愧于表达身份，牛市时相反。7.思考人性的弱点总是从众，反向操作很难。8.加大分红是利好还是利空从长远来看是利好。七、股票低迷时需要家庭支持家庭、亲人、朋友的关心，在股票低迷时尤为重要。八、恐惧踏空还是恐惧套牢作者没有明确的结论，笔者认为还是要避免套牢，市场永远不缺赚钱的机会，但没有资金就没有一切。九、一家之言物极必反，阴盛阳来。十、抓大放小大公司、国有企业更加稳健，小公司、创新企业风险大但回报也大。另外，优先从全世界挑选最好的股票，其次才是选国内最好，再其次是国内第二，不要搞错顺序。十一、股市低迷时不要失去信心股市与经济发展有时会出现背离，但大方向是一致的。十二、血汗钱别做股指期货普通人不建议做融资融券、股指期货，这是专业人士的专属领域。大多数人管理自己的财富已属不易，不要加杠杆。第五部分 我眼中的大势（2007-2024）略。远离高估的小、新、差、题材、伪成长股票（黑五类）。问题
第一部分 功能协调 第一章 整体牙科学的理念 第二部分 功能紊乱 第三部分 治疗 问题本文总结自2015年，[美]Peter E. Dawson的书籍-《功能合学 从颞下颌关节到微笑设计》，请支持正版图书。本文首发于个人博客https://lisper517.top/index.php/archives/4326/，转载请注明出处。第一部分 功能协调第一章 整体牙科学的理念第二部分 功能紊乱第三部分 治疗问题1.全文搜索为什么
第一章 病例选择 第二章 髓腔解剖 第三章 橡皮障隔离术 第四章 开髓 第五章 根管预备 第六章 根管冲洗和根管封药 第七章 根管充填 第八章 根管再治疗 第九章 显微根尖手术 第十章 根管治疗后的牙体修复 第十一章 C形根管系统的诊疗 第十二章 牙内陷的诊疗 第十三章 牙髓再生术 第十四章 镍钛根管器械分离的预防及处理 第十五章 锥形束CT的应用 问题本文总结自2022年，彭彬的书籍-《根管治疗图谱（第2版）》，请支持正版图书。本文首发于个人博客https://lisper517.top/index.php/archives/4322/，转载请注明出处。第一章 病例选择第二章 髓腔解剖第三章 橡皮障隔离术第四章 开髓第五章 根管预备第六章 根管冲洗和根管封药第七章 根管充填第八章 根管再治疗第九章 显微根尖手术第十章 根管治疗后的牙体修复第十一章 C形根管系统的诊疗第十二章 牙内陷的诊疗第十三章 牙髓再生术第十四章 镍钛根管器械分离的预防及处理第十五章 锥形束CT的应用问题1.全文搜索为什么
《全局诊断-牙科诊断和治疗计划的新视角》-J. William Robbins，Jeffrey S. Rouse[美]
第一章 全局诊断：跨学科治疗计划制订的艺术与科学 第二章 全局分析诊断表 第三章 5个CORE问题 第四章 美学牙冠延长术 第五章 组织移植 第六章 成人牙列的牙槽骨压低治疗 第七章 牵引助萌术 第八章 正颌手术 第九章 牙颌面整形 第十章 牙槽骨发育过度：全局诊断中最难处理的部分 第十一章 序列治疗 第十二章 CORE模板 第十三章 病例研究 问题本文总结自2017年，[美]J. William Robbins，Jeffrey S. Rouse的书籍-《全局诊断-牙科诊断和治疗计划的新视角》，请支持正版图书。本文首发于个人博客https://lisper517.top/index.php/archives/4320/，转载请注明出处。第一章 全局诊断：跨学科治疗计划制订的艺术与科学第二章 全局分析诊断表第三章 5个CORE问题第四章 美学牙冠延长术第五章 组织移植第六章 成人牙列的牙槽骨压低治疗第七章 牵引助萌术第八章 正颌手术第九章 牙颌面整形第十章 牙槽骨发育过度：全局诊断中最难处理的部分第十一章 序列治疗第十二章 CORE模板第十三章 病例研究问题1.全文搜索为什么
第一章 定投的理论基础 第二章 定投实践 第三章 辅助工具本文的目的是描述定投的投资策略。本文首发于个人博客https://lisper517.top/archives/4264/，转载请注明出处。本文内容来自各种网络资料以及 b站视频 ，个人总结。任何投资都有风险，本文不构成任何投资建议。理财产品收益率超过6%就要打问号，超过8%很危险，超过10%就要做好损失全部本金的准备（郭树清，陆家嘴金融论坛，2018-06-14）。一定用闲钱投资，不要拿马上急用的钱、贷款借来的钱投资。投资书单：《富爸爸穷爸爸》、《小狗钱钱》、《穷查理宝典》、《大道：段永平投资问答录》、《积极性资产配置指南》、《滚雪球》、《资产配置的艺术》等。第一章 定投的理论基础一、定投的概念定投即“定期定额投资”，指在固定的时间（如每月1日，每周一，或者每天），以固定的金额（如每月1000元），投资到指定的同一投资标的（如某支指数基金）中。定投像一种“理财储蓄计划”，让你忽略市场短期波动，通过长期、持续的投入来平滑成本、积累资产。一、定投的特点1.淡化择时定投假设市场总是在波动，不去预测市场的高点或低点，而只需严格按照定投计划操作，避免了“追涨杀跌”。2.平均投资成本在价格高时，定投能买到较少的份额，但已持有的部分在上涨；在价格低时，虽然持有的部分下跌，但定投能买到更多的份额。综合下来看，定投降低了平均购入成本。另外，对于资金不充裕的人来说，无法一次性拿出大量本金，定投也使资金投入更平滑。3.复利效应利滚利，非常恐怖。4.强制储蓄对于年轻人来说，定投也可以避免乱花钱。当然，也不能排除定投亏钱的可能。5.减少波动相比于一次性投入，在下跌时，定投可以减少回撤；但相应地，上涨时定投的收益更少。6.微笑曲线与哭泣曲线当走势先下跌后上涨时（画出一条微笑形的曲线），定投收益高于一次性投入（最适合定投）；当走势先上涨后下跌时（哭泣曲线），定投收益最差。因此定投相对来说应该追跌杀涨（越跌越买），但最重要的还是选择标的。第二章 定投实践一、选择投资标的定投最适合的是长期上涨、但短期有波动的资产。1.首选宽基指数基金，如纳斯达克100、标普500这些指数的基金（难度稍微大一点的有沪深300、中证500、上证50、科创50等）。2.次选行业、主题指数基金，如消费、医药、科技、新能源、AI等。3.再次选其它主动管理型基金，根据基金经理风格不同而有变化，可能重仓某支个股、板块，也可能一些经理喜欢分散投资。4.其它国债，收益稳定但较低；个股期货，风险太高。笔者的建议是尽量分散投资，既有稳健的国债，也可以适当加一些激进的投资。目前（2025-12-20）关注的有：（1）宽基指数，纳斯达克100、标普500、沪深300、上证50等。前两者关注更多，算风险中等。 （2）贵金属，黄金白银等。黄金近几年涨疯了，目前可能处于高位，应该算风险较大。 （3）现金流ETF，一些现金流充沛的公司，算风险较大。 （4）红利ETF，稳定高分红的公司，也称低波红利（低波动性），算风险较低。但是投资此类ETF需要做好长期打算，五年十年。 （5）短融ETF，短期债券（消费债等等），和国债的风险差不多。 （6）国债，风险最低。风险可以自己评估，最简单的道理：收益越高、风险越大。不要把鸡蛋放在一个篮子里，比如所有资金只拿1/3投资，其它2/3留作它用；在这1/3里，又作如下划分：（1）宽基指数投50%。（2）红利低波，20%（3）现金流，10%。（4）贵金属，10%。（5）短融，5%。（6）国债，5%。上面只是随便举例，不构成投资建议。总之，通过合适搭配，最终目标是跑赢通胀，使所有加和、总的年化收益达到5%，或者8%，甚至10%。二、选择投资平台在支付宝、银行等平台交易称为场外交易（还有京东、且慢、天天基金等），各种券商平台交易则称为场内交易。一般普通人投资在支付宝即可，购入手续费打一折（0.1%左右）。场外交易的优点是方便快捷，可设置自动扣款，省心。缺点有：①整体费率更贵。包括申购费（1.2%左右。支付宝打一折就是0.1%），管理费、托管费（加起来0.2-1%左右不等，看具体基金）等。②交易不自由，比如可能有单日买入限额，T+N（发起买入操作后需要再过N天才能实际入仓，一般是1-2天）等。但是可以设置每日定投规避限额，并且定投本来也是需要长期持有的，笔者感觉影响不大。如果选择场外交易，买的一般都是带“联接”的，长期持有的话选后缀为A的，短期操作选C类。A类的管理费、托管费更低，但买入费更高，而且如果持有时间短就想卖的话还要收费（一般需要持有1周到2年，卖出时才不会收手续费，这也是为了鼓励长期持有）。场内交易的特点有：①整体费率更便宜，但前提是能申请到万分之0.5手续费、5块以下免收的券商账户，否则算下来可能不如支付宝的性价比。②有溢价，一般溢价在1-8%。溢价8%就不适合买入。当然，卖出的时候选择合适时机，也能吃到这部分溢价。A股港股建议在1%以内溢价买，境外ETF建议5%以下再考虑（境外ETF总是有溢价，因为外汇管制等）。有时也可能会折价，可以净值更低的价格买入。③实时交易，不限额、不限T+N。④各家券商平台只能买到自家的金融产品，可能需要下多个APP。三、设置自动扣款每日，每周，或者每月自动购买即可。设置完后就不要再频繁操作，反而容易追涨杀跌、亏钱。定投最考验的是定力，选择了对的标的，就要坚定执行定投计划，以一年、三年甚至五年十年为期望，短期下跌10%，甚至30%、50%都是可能的。不要被某一处损失动摇，比如因为贵金属跌了、其它涨了，就错误地卖出所有贵金属。牢记大目标是总年化达到8%，一处亏了再从其它地方赚就是了。以上介绍的方法属于无脑定投，一定选好标的（长期上涨，短期波动），不要选择长期也波动很大的。四、调仓在定投早期可以不用管（3个月或者半年，具体看每期投资金额。这个初期过程叫建仓）。但定投也不是只买不卖，每季度看一下（或者半年、一年），是否需要调仓（调整仓位）。比如说，定投一开始是这样的：（1）宽基指数占50%。 （2）红利低波，20% （3）现金流，10%。 （4）贵金属，10%。 （5）短融，5%。 （6）国债，5%。经过一段时间定投，有些涨、有些跌，占比可能变成这样：（1）宽基指数占60%。 （2）红利低波，18% （3）现金流，8%。 （4）贵金属，8%。 （5）短融，3%。 （6）国债，3%。此时需要再次平衡，将占比过高的卖出，买入占比较低的，使占比回到一开始。这种再平衡是一种较弱的低买高卖策略。五、定投策略（一）定期定额法每隔一段时间投入固定金额，最传统、经典的定投法。（二）固定市值法每次投入固定市值。举例，某基金初始为1元，每期投入1000固定的市值，该基金的波动与投入金额的关系如下：（1）净值为1，投入1000元，持有1000市值。（2）净值上涨10%至1.1，此时持有市值为1100元、份额为1000。本期需要买入2*1000-1100即900元，买入后持有市值2000元、份额1000+900/1.1即1818.18。（3）净值下跌25%至0.825，此时持有市值为1500、份额为1818.18。本期需要买入3*1000-1500即1500元，买入后持有市值3000元、份额3636.36。（4）净值上涨50%至1.2375，此时持有市值为4500、份额为3636.36。本期需要买入4*1000-4500即-500元（卖出500元），卖出后持有市值4000元、份额3232.32。……依此类推固定市值法的优点：①优于定期定额法，而且波动越大、优势越明显。尤其是微笑曲线时，能多出5%左右收益；震荡下跌时损失也更小。②容易执行，执行的方法就是 期数 * 每期金额 - 当期市值 ，也就是说保持 每次操作后的市值 = 期数 * 每期金额 。③适合有增量资金的人，即资金主要来自每月的固定收入。缺点：①在熊市下跌时容易过早买光资金。②急速上涨时无法吃到超额收益。但这种情况很少，如果你选择标的确实适用于定投（做好人买好股得好报）。总的来说还是最推荐新手用这种方法。（三）逢低加码法类似网格交易，把资金划分成更多份，当净值下跌时买更多。当时这种方法需要每日关注，稍微耗费更多精力。（详见 b站视频 ）具体的操作方法，设定阈值为2%（也可以设3%、5%等），如果在两次定投之间，净值曾下跌超过阈值，就算触发阈值（不能只看定投前一天的净值）。定投12个月，将资金分为12*1.5即18份（也可以就划12份）：（1）净值为100，投1份资金。（2）净值下跌2%至98，触发阈值、需要加码，投2份资金。（3）净值上涨至102，投1份。（4）净值下跌4%至97.92，比上一次加码的低点（98）稍低，仍然投2份资金。（5）净值上涨至102，投1份。（6）净值下跌3%至99，但是99比上一次加码的低点（97.92）高，因此还是只投1份。……依此类推，总之就是每比上一次加码的低点跌2%、加1份资金。逢低加码法的特点：①相比固定市值法，逢低加码法在市场大涨时也会买入（前者甚至可能卖出）。②固定市值法有可能在熊市时过早打光子弹，逢低加码法在一开始就划分好了资金。因此前者适合有固定收入的人，后者适合存量资金。③操作略复杂，适合有一定经验的人。六、定投的止盈策略（零）定投止盈的原则1.早期不止盈，中后期考虑止盈早期仓位不大，止盈意义也不大，比如打算定投24月，前1/4即6个月都可以算建立仓位、可以不止盈；中后期时定投慢慢失去了平均投资成本的作用（钝化效应），此时可以考虑止盈。2.尝试分批止盈分2-3次卖出，锁定部分利润，同时也能参与后续上涨。3.止盈后再投资卖出获利后参与新一轮定投。（怎么感觉像dubo，不怕你赢钱，就怕你不玩）4.止盈不止损（最重要）如果选择了对的标的，即使下跌也要坚持买入（不止损）；但需要有合适的止盈（因为钝化效应，后面每期增加的定投对摊低成本的效果微乎其微）。正常人对下跌的承受极限是15%，超出可能会导致纪律性缺失、卖出止损等。只能说一定要保持理性。（一）目标收益率法达到目标收益率后即全部或分批卖出。比如设定15%到20%。简单易执行，但是可能错过后续上涨。也可以卖一部分，比如分成4份，卖出1/2（2份）或者3/4（3份），落袋为安、落草为寇。注意这里的止盈点是 盈利/已投入资金 ，比如100元分10份，投了8期就盈利13元，此时利润率是 13/(8*10) 即16.25%，相对于全部资金的收益率是 13/100 即13%，但也需要止盈了。卖出得到的现金，可以继续投入相同的品种（如果目前估值还不是太高），也可投入其它低估的板块，或者买入债券等等。（二）参考市盈率法参考市盈率（PE）历史百分位，达到70%或者80%时卖出（历史PE需要在一些平台查看，比如券商平台等）。这种方法不适用于非指数型主动基金（标的不是指数，而是基金经理个人根据经验选择）。比如一支个股，市盈率是其市值/公司每年利润，可以简单理解为需要多少年回本。打个比方，买下一栋房子（购买资金即市值），租出去（每年租金相当于公司每年利润），需要多少年回本。一般来说PE达到历史平均80%时下跌的风险较大。（三）最大回撤法设置一个目标收益率（比如25%），再设置一个回撤阈值（比如10%），当盈利达到25%后又回撤（下跌）时止盈。需要持续关注市场。第三章 辅助工具笔者参考AI做出来的 excel表格 。手工填入每次的定投操作、购入单价即可。另外还要搭配一个填写单价的脚本（ 持仓汇总 里的 当前市价 列），这里不提供，可以手动填或者问AI。如果需要查看市盈率等，很多地方都可以，这里推荐wind，手机APP端免费（PC端收费）。
《深度学习入门 基于Python的理论与实现》-斋藤康毅（笔记）
步骤/目录： 无本文首发于个人博客https://lisper517.top/index.php/archives/4260/，转载请注明出处。本文的原文写作日期为2020年11月17日，主要目的是总结《深度学习入门 基于Python的理论与实现》。笔者的毕业论文有很多东西来自这本书。下面的内容有些缩进或者图片缺失，可以参考 原word文档 。本书主要用numpy来处理运算，用matplotlib将结果可视化。对于没有基础的人十分友好，只需要高中的线代知识就可以看懂。 1.x=x.flatten() 将矩阵及张量转换为一维数组。x>15，结果得到一个由True和False组成的一维列表，x[x>15]即可输出所有大于15的成员。 矩阵与一维数组的*乘，（数组长度与矩阵列数相同）将一维数组扩张为矩阵形状后简单相乘，符合交换率，符号为*； 矩阵与数组dot乘，（数组长度与矩阵列数相同）将一维数组与每行对应索引相乘求和，得到一维数组，长度为矩阵的行数：如[[1, 2], [3, 4], [7, 8]] dot [5,6]，则得[1*5+2*6, 3*5+4*6,7*5+8*6]，不符合交换律，用np.dot计算。 一次绘图流程：p42 2.感知机：接受一个或多个输入，输出一个信号。有多个输入时，可以给各个输入配置权重。机器学习就是人给机器一些数据，机器根据这些数据选出权重的过程。 P56从图像上，感知机是一条直线，有局限性。叠加多个感知机可以构造类似曲线。 3.对于单层感知机，实际上有两个函数，比如首先有y=b+x1*w1+x2*w2，其中b为偏置，w1、w2为权重；然后通过激活函数，比如h(x)=1或0（当y<=0时为0，否则为1。这种函数的输出是跳跃的，可称为阶跃函数）。若把激活函数换成其他形式，就接近神经网络的概念了。常用的一个激活函数（sigmoid函数）：1/(1+exp(-x))，其中exp(-x)为e的-x次方。 接受numpy数组为参数的阶跃函数见p69。 激活函数也可以使用ReLU函数，其在x<=0时输出0，在x>0时则为线性关系。P74 对于输出层的激活函数，如果是分类问题（类似阶跃函数）用softmax函数，回归问题（连续输出数值）用恒等函数。P89 softmax函数的输出是连续的，总和为1，可以看作概率。为了节省算力，对未知模型进行预测时通常也可以省略输出层的softmax激活函数（接受数据进行学习时可以不省略）。 在分类问题中，输出层的神经元数量通常等于类别的数量。哪个神经元的输出最大，就会归类为该类别。 4.正规化：将数据进行处理，使其限制在某个范围内。正规化是一种预处理。 批处理：相同的神经网络，多个输出，多个结果。批处理可以大大加快运算速度。P101 5.损失函数：描述当前神经网络与测试数据（即监督数据）在多大程度上不拟合。一般可用均方误差函数和交叉熵。均方考虑了非正确解、越接近0（越小）越好，交叉熵只包含正确解、越接近0（越小）越好。 机器学习就是要使得损失函数值最小。如果训练数据太多，可以从中随机选择部分数据来学习，称为mini batch。 不用精确度作为评价标准，因为要设定参数的导数（变化梯度），如果用精确度为指标，容易导致导数为0，参数无法更新（精确度常常是跳跃的，微调无法产生影响，而损失函数是连续变化的）。这也是sigmoid函数优于阶跃函数的地方（激活函数）。 对于矩阵，y[0,2]的写法等同于y[0][2] 梯度指示的方向是损失函数减少量最多的地方，不一定指向损失函数值最小的地方。所以，机器学习可能会陷入局部最小值、鞍点或者学习平原。 鞍点处的梯度也为0，比如一个马鞍形曲面，(0,0,0)处的形状就很像马鞍。 梯度，就是一个一维数组。一个函数有多个输入，那么梯度就是这个多维函数（在某一点处）的导数。梯度数组的大小和输入多少相等，意义是对每一个输入，在保持其他输入不变时求该输入的导数，最终组成一个导数数组。为了使损失函数减小，需要沿负梯度方向下降。 6.反向传播法算梯度的速度比微积分法快许多，主要应用了复合函数的求导（相乘）。 7.有时SGD（随机梯度下降），即沿着梯度最大的地方下山的方法，不一定能最快下山。还有其他一些方法。 Momentum（动量法），如果某一方向上的梯度较小，但是持续很久，就适合用这种方法。模拟静止小球在山中的运动，某一方向累计的梯度会给小球积累该方向的速度，于是在该方向上移动越来越快。 AdaGrad（Adaptive适应梯度法），对梯度中的每一个导数都有一个学习率，该学习率还会不断衰减。AdaGrad是通过记录过去所有梯度的平方和实现的，最终学习率会衰减到0。不想让学习率衰减太快可以用RMSProp法，其会更多地考虑最近的梯度、逐渐减小久远梯度的权重。 Adam（直观上讲，类似于融合了AdaGrad与Momentum法，2015年提出），甚至可对一些超参数调校。 一些技巧： （1）权重的初始值：对于sigmoid或tanh等激活函数，使用Xavier方法，上一层的节点个数为n，本层的初始值大概是标准差1/sqrt(n)的高斯分布； 对relu激活函数，可以使用He初始值。 在手头数据集少时，可以“学习迁移”，即训练完一个数据集，将权重的最终值作为下一次学习的初始值。 （2）调整激活值的分布：使用batch normalization，优点是增大学习率（学的快）、对初始值不会过于敏感、抑制过拟合。 （3）抑制过拟合：过拟合主要是由于训练数据少、网络参数太多（层数多、节点多等）。过拟合的表现常常是训练数据准确度高，测试数据准确度不佳。对简单网络，常用权值衰减来抑制过拟合。对复杂网络，可用Dropout方法，随机删除一些节点。另外，可以用已有的数据生成新的数据，比如对手写数字图片，可对图片进行平移、旋转等操作。 （4）高效寻找超参数：对于网络层数与节点数、batch大小、学习率、权值衰减等超参数，需要高效寻找之。可在训练数据和测试数据之外再分一个验证数据，用来对探讨超参数取什么值，然后让超参数不断*10，在对数尺度上变化，并观测其对学习的影响。一般来说，测试数据应该只在最后用一次。 （5）GPU运算：GPU擅长大量的并行运算，比如矩阵的乘法；而CPU擅长连续的复杂运算。使用GPU，可以将训练和测试时间大大缩短。据书中称，NVIDIA的显卡比AMD的更合适。 （6）分布式学习：和用GPU一样，可缩短学习时间。Google的TensorFlow和微软的CNTK都很重视分布式学习。 8.CNN（Convolutional Neural Network），书中之前实现的网络，隐藏层的结构是Affine+Relu（或者其他激活函数），最后一层是Affine+Softmax，而CNN的隐藏层是Conv（卷积层）+Relu+Pooling（池化层），最后一层不变。普通Affine的问题是没有考虑图片的形状，比如矩阵中相距较远的两个点关联度较小，近大。从原理上，卷积层使用了类似滤波器的方法，用了矩阵的*乘，并且偏置只有一个。*乘，即相同大小矩阵的对应位置乘积之和。 池化层则是将层中的数据减少形成特征化的数据，比如只取最大值、只取平均值。 CNN是图像识别中常用的操作。通过观察，CNN的不同Conv层，大概在进行从基础到抽象的观察。 在各种CNN中，书中介绍了CNN元组LeNet及2012年提出的AlexNet。据称，AlexNet是深度学习热潮的导火索。 Google旗下的Deep Mind公司，开发出了AlphaGo和DQN。其中DQN可以接受游戏的图像输入（比如每秒4帧），学习如何玩游戏，甚至可以做出超越人类的手柄操作。
步骤/目录： 无本文首发于个人博客https://lisper517.top/index.php/archives/4259/，转载请注明出处。本文的原文写作日期为2020年10月22日，主要目的是用Python重构按键精灵。主体程序，主要是一些功能的实现，具体应用需要自己写。写的比较乱：import win32gui, win32api, win32con, win32ui import time from time import sleep import random from random import uniform import logging from logging import info, warning, error from config import VK_CODE import copy import cv2 as cv import traceback # mode为test意为调试模式，real则为实际应用 # In 'test' mode, it will print some hidden info for Debug mode = 'test' # 模式图的存储路径 # The save path of pattern pics pattern_path = 'yourpath\\' # 设置logging的书写格式 # Setting logging configs logging.basicConfig( level=logging.DEBUG, format= '%(lineno)d : %(asctime)s : %(levelname)s : %(funcName)s : %(message)s', filename='yourpath\\log{}.txt'.format( time.strftime('-%Y-%m-%d')), filemode='w') # 用当前时间初始化随机数 # Set random seed random.seed(time.time()) def Get_PosAndHwnd(hwnd=0, ClassName=None, TitleName=None): '''接受句柄、类名、标题名，返回第一个匹配的窗口位置和句柄。 Accepts Handle, ClassName or TitleName of a window, returns the rect-pos of the first window that matches. Args: hwnd: 目标句柄 target handle. ClassName: 目标窗口类名 target ClassName. TitleName: 目标窗口标题 target TitleName. Returns: x1, y1, x2, y2, hwnd 前四个参数描述窗口在显示器中的位置，hwnd为句柄。 x1-y2 describes the pos of the window in screen, last arg is the handle. ''' try: if hwnd == 0: hwnd = win32gui.FindWindow(ClassName, TitleName) x1, y1, x2, y2 = win32gui.GetWindowRect(hwnd) info('找到窗口，句柄：{}，标题名：{}，类名：{}，坐标：{}'.format( hwnd, win32gui.GetWindowText(hwnd), win32gui.GetClassName(hwnd), (x1, y1, x2, y2))) return x1, y1, x2, y2, hwnd except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('Get_PosAndHwnd 出现错误') def Activate_Hwnd(hwnd): '''激活指定句柄的窗口。每次转换时使用。 Activates the window with the matching hwnd. Args: hwnd: 目标句柄 target handle. Returns: No return. ''' try: win32gui.SendMessage(hwnd, win32con.WM_ACTIVATE, win32con.WA_ACTIVE, 0) # WA_CLICKACTIVE为通过鼠标激活，WA_ACTIVE为鼠标以外的东西（如键盘）激活，WA_INACTIVE为取消激活 # WA_CLICKACTIVE means activate by mouse, WA_ACTIVE means other equipments( like keyboard).WA_INACTIVE means inactivate it. info('激活句柄为 {} 标题为 {} 的窗口'.format(hwnd, win32gui.GetWindowText(hwnd))) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('激活窗口 出现错误') def LeftClick(hwnd, x1, y1, times='first', platform='PC'): '''左键单击（自带延时） Left Click the window (located by hwnd) once (with human-like delay). Args: hwnd: 目标窗口的句柄 target hwnd. x1, y1: 需要点击的坐标 target pos. times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). platform: 目前无用。'PC'表示当前操作的是桌面版，不是安卓模拟器('AM')。 Useless now. 'PC' means target window is PC, not Android manipulator ('AM'). Returns: No return. ''' try: if platform == 'PC': # 对于桌面版 # for PC tmp_pos = win32api.MAKELONG(x1, y1) #elif flag == 'AM': # 对于模拟器 # for Android manipulator #click_pos = win32gui.ScreenToClient(hwnd, (x1, y1)) # 注意坐标是整个窗口还是客户区的，用ScreenToClient转换 # switch between screen/client pos #tmp_pos = win32api.MAKELONG(click_pos[0], click_pos[1]) if times == 'first': Activate_Hwnd(hwnd) win32gui.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, tmp_pos) # 鼠标点击格式为SendMessage(hWnd,WM_LBUTTONDOWN,fwKeys,MAKELONG(xPos,yPos)); # fwKeys可以取：MK_CONTROL、MK_LBUTTON、MK_MBUTTON、MK_RBUTTON、MK_SHIFT等，多个值用|隔开 sleep(uniform(0.05, 0.08)) win32gui.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0000, tmp_pos) # 抬起时有些电脑上fwKeys显示为0000，有些可能为MK_LBUTTON # Use spy++ for details sleep(uniform(0.07, 0.095)) info('对句柄 {} 标题 {} 的坐标 {} 进行 左键单击 动作'.format( hwnd, win32gui.GetWindowText(hwnd), (x1, y1))) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('左键单击 出现错误') def LeftClick_sequence(hwnd, points, times='second', platform='PC'): '''左键依序单击（依次点击多个点） Click a sequence of points in order. Args: hwnd: 目标窗口的句柄 target hwnd. points: 需要点击的坐标 target points in the form like ((x1,y1),(x2,y2)...). times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). platform: 目前无用。'PC'表示当前操作的是桌面版，不是安卓模拟器('AM')。 Useless now. 'PC' means target window is PC, not Android manipulator ('AM'). Returns: No return. ''' try: if times == 'first': Activate_Hwnd(hwnd) for point in points: LeftClick(hwnd, point[0], point[1], 'second', platform) info('对句柄 {} 标题 {} 的坐标 {} 进行 左键依序单击 动作'.format( hwnd, win32gui.GetWindowText(hwnd), points)) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('左键单击 出现错误') def LeftDoubleClick(hwnd, x1, y1, times='first', platform='PC'): '''左键同一位置双击 Click the same pos twice. Args: hwnd: 目标窗口的句柄 target hwnd. x1, y1: 需要点击的坐标 target pos. times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). platform: 目前无用。'PC'表示当前操作的是桌面版，不是安卓模拟器('AM')。 Useless now. 'PC' means target window is PC, not Android manipulator ('AM'). Returns: No return. ''' try: if times == 'first': Activate_Hwnd(hwnd) info('左键同一位置双击--第一次点击') LeftClick(hwnd, x1, y1, 'second', platform) info('左键同一位置双击--第二次点击') LeftClick(hwnd, x1, y1, 'second', platform) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('左键同一位置双击 出现错误') def LeftDifDoubleClick_Rect(hwnd, x1, y1, times='first', platform='PC', delta=(0, 4)): '''左键不同位置双击，范围为双正方形 Left click 2 pos, in a double-square-like area. _________ | ___ | | | | | | |___| | |_______| (x1, y1) is at the center, (x2, y2) between the squares (borders included). Args: hwnd: 目标窗口的句柄 target hwnd. x1, y1: 第一次点击的坐标 first pos to click. times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). platform: 目前无用。'PC'表示当前操作的是桌面版，不是安卓模拟器('AM')。 Useless now. 'PC' means target window is PC, not Android manipulator ('AM'). delta: 第二个点的横坐标在x1+delta[0] 到 x1+delta[1]间（包括端点），纵坐标同样。 x2 varies between x1+delta[0] to x1+delta[1], y2 the same (both ends included). Returns: No return. ''' try: if times == 'first': Activate_Hwnd(hwnd) info('左键正方形双击--第一次点击') LeftClick(hwnd, x1, y1, 'second', platform) point_list = [] for delta_x in range(delta[0], delta[1] + 1): for delta_y in range(delta[0], delta[1] + 1): point_list.append((x1 + delta_x, y1 + delta_y)) point_list.append((x1 + delta_x, y1 - delta_y)) point_list.append((x1 - delta_x, y1 + delta_y)) point_list.append((x1 - delta_x, y1 - delta_y)) point_list = list(set(point_list)) point_list.remove((x1, y1)) x1, y1 = random.sample(point_list, 1)[0] info('左键正方形双击--第二次点击') LeftClick(hwnd, x1, y1, 'second', platform) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('左键正方形双击 出现错误') def LeftDifDoubleClick_Cir(hwnd, x1, y1, times='first', platform='PC', r=4): '''左键不同位置双击，范围为圆形。 Left Click 2 pos in a circle. (x1, y1)为圆心，r为半径，(x2, y2)在圆内及圆上。 (x1, y1) is the center, r the radius. Generates (x2, y2) in the circle (or on the border). Args: hwnd: 目标窗口的句柄 target hwnd. x1, y1: 第一次点击的坐标 first pos to click. times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). platform: 目前无用。'PC'表示当前操作的是桌面版，不是安卓模拟器('AM')。 Useless now. 'PC' means target window is PC, not Android manipulator ('AM'). r: 圆的半径。 radius. Returns: 返回两次点击的坐标(x1,y1,x2,y2)。 Returns 2 clicked pos in (x1,y1,x2,y2). ''' try: if times == 'first': Activate_Hwnd(hwnd) info('左键圆形双击--第一次点击') LeftClick(hwnd, x1, y1, 'second', platform) m, n = x1, y1 point_list = [] final_point_list = [] for delta_x in range(r + 1): for delta_y in range(r + 1): point_list.append((delta_x, delta_y)) point_list.remove((0, 0)) for i in range(len(point_list)): x = point_list[i][0] y = point_list[i][1] if x * x + y * y <= r * r: final_point_list.append((x1 + x, y1 + y)) final_point_list.append((x1 + x, y1 - y)) final_point_list.append((x1 - x, y1 + y)) final_point_list.append((x1 - x, y1 - y)) final_point_list = list(set(final_point_list)) x1, y1 = random.sample(final_point_list, 1)[0] info('左键圆形双击--第二次点击') LeftClick(hwnd, x1, y1, 'second', platform) return (m, n, x1, y1) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('左键圆形双击 出现错误') def Random_Areas_LeftClicks(hwnd, click_areas, times='first', platform='PC', r=4, click_strategy=1): '''从几种点击策略中选一种执行，在一定范围对目标窗口进行点击。 Select a click strategy/combination, click the window in some given areas. --------- 单个点击区域如右。A single click_area looks like left. | ---- | 如果只点击一次或者点击两次中的第一个坐标，该坐标位于小矩形中（包括边界）。 | | | | If only click once, or the first click in 2 clicks, it locates in the minor rect (borders included). | | | | 小矩形的每条边距大矩形距离为r个像素点。 | | | | Each border of the minor rect is r-pixel far from the outside rect. | ---- | --------- 第二次点击的区域不会超出大矩形的范围（包括边界)）。对于一个点击区域[x1,y1,x2,y2]，其中的小矩形为[x1+r,y1+r,x2-r,y2-r]。 The second is in the big rect (borders included). For a click_area like (x1,y1,x2,y2), the minor rect is [x1+r,y1+r,x2-r,y2-r]. Args: hwnd: 目标窗口的句柄 target hwnd. click_areas: 可选的点击范围（矩形）。格式为[[x1,y1,x2,y2],[x3,y3,x4,y4]...]，只有一个区域则可以写成[x1,y1,x2,y2]。 Possible rect-areas to click, given in the form of [[x1,y1,x2,y2],[x3,y3,x4,y4]...]. If only one area, [x1,y1,x2,y2] is also acceptable. times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). platform: 目前无用。'PC'表示当前操作的是桌面版，不是安卓模拟器('AM')。 Useless now. 'PC' means target window is PC, not Android manipulator ('AM'). r: 圆的半径。 radius. click_strategy: 选择的点击策略。看看源码，很容易写自己的策略。主要包括点击方式和概率。 A strategy for clicking, includes combination of clicking functions and its weights. Look at the src code, easy to construct your own click_strategy. Returns: 返回两次点击的坐标(x1,y1,x2,y2)。如果只点击一次，返回(x1, y1, -1, -1) Returns 2 clicked pos in (x1,y1,x2,y2). If only clicked once, return (x1, y1, -1, -1). ''' try: # 缩小边界，并加上一个值，表示区域点的坐标个数（包含边界） total = 0 areas = copy.deepcopy( click_areas ) # python中传列表参是浅拷贝，为了防止改变原click_areas需要写这一句。传字符串、数字是深拷贝 if isinstance(areas[0], int): areas = [areas] for i in range(len(areas)): areas[i][0] = areas[i][0] + r areas[i][1] = areas[i][1] + r areas[i][2] = areas[i][2] - r areas[i][3] = areas[i][3] - r areas[i].append((areas[i][2] - areas[i][0] + 1) * (areas[i][3] - areas[i][1] + 1)) total = total + areas[i][4] rand = random.randint(0, total - 1) # 找出第一次点击位置落在哪个区域，并找出具体坐标 # find out the first click is in which area, and the exact pos. x = 0 y = 0 for i in range(len(areas)): rand = rand - areas[i][4] if rand < 0: rand = rand + areas[i][4] w = areas[i][2] - areas[i][0] + 1 x = rand % w + areas[i][0] y = rand // w + areas[i][1] # 现在python中整型之间用/也会得到float break if click_strategy == 1: # 1号策略，包括左键单击、左键同一位置双击、左键圆形双击三种 #总结果数为173，左键单击:左键同一位置双击:左键圆形双击 的比例为 131:29:13 rand = random.randint(1, 173) if times == 'first': Activate_Hwnd(hwnd) if rand <= 131: # weighs 131 info('随机区域左键 选择 左键单击，坐标{}'.format((x, y))) LeftClick(hwnd, x, y, 'second', platform) return (x, y, -1, -1) elif rand >= 161: # weighs 13 info('随机区域左键 选择 左键圆形双击，第一次点击坐标{}'.format((x, y))) return LeftDifDoubleClick_Cir(hwnd, x, y, 'second', platform, r) else: # weighs 29 info('随机区域左键 选择 左键同位置双击，坐标{}'.format((x, y))) LeftDoubleClick(hwnd, x, y, 'second', platform) return (x, y, x, y) elif click_strategy == 2: # 2号策略，仅包括左键单击，用于只能单击的情况 if times == 'first': Activate_Hwnd(hwnd) info('随机区域左键 选择 左键单击，坐标{}'.format((x, y))) LeftClick(hwnd, x, y, 'second', platform) return (x, y, -1, -1) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('随机区域左键 出现错误') def press_key(hwnd, key='esc', times='second'): '''单次按键（自带延时） Press a key once (with human-like delay). Args: hwnd: 目标窗口的句柄 target hwnd. key: 需要按的键，详见config.VK_CODE。 The key to press, see also in config.VK_CODE. times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). Returns: No return. ''' try: if times == 'first': Activate_Hwnd(hwnd) win32api.SendMessage(hwnd, win32con.WM_KEYDOWN, VK_CODE[key], 0) # 暂时将lParam写为0 # 这里不知道是否要暂停 # I don't konw whether to pause here. time.sleep(0.01) win32api.SendMessage(hwnd, win32con.WM_CHAR, VK_CODE[key], 0) sleep(uniform(0.05, 0.08)) win32api.SendMessage(hwnd, win32con.WM_KEYUP, VK_CODE[key], 0) sleep(uniform(0.07, 0.095)) info('对句柄 {} 标题 {} 的窗口 按 {} 键一次'.format(hwnd, win32gui.GetWindowText(hwnd), key)) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('单次按键 出现错误') def press_keys(hwnd, keys, times='second'): '''依序按键 Press a sequence of keys in order. Args: hwnd: 目标窗口的句柄 target hwnd. keys: 需要按的键，详见config.VK_CODE。 Keys to press, see also in config.VK_CODE. times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). Returns: No return. ''' try: if times == 'first': Activate_Hwnd(hwnd) for key in keys: press_key(hwnd, key, 'second') info('对句柄 {} 标题 {} 的窗口 依序按 {} 键'.format(hwnd, win32gui.GetWindowText(hwnd), keys)) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('依序按键 出现错误') def ClientRect_PrtSc(hwnd, area=None, filename=''): '''根据句柄、截图位置和图片路径，对窗口的客户区截图并存到指定位置。 Press PrtSc for a window's client area, save the pic in the indicated path. 从https://blog.csdn.net/zhuisui_woxin/article/details/84345036和https://www.cnblogs.com/Evan-fanfan/p/11097850.html改编 Made some changes and corrected some errors from 2 links above (took me some time to figure the errors). Args: hwnd: 目标窗口的句柄 target hwnd. area: 需要的区域。为None时表示整个客户区。 Needed area. If None, means get the whole client area. filename: 指定路径。为''时表示文件名根据hwnd生成。 Indicate the path. If '', means 'path\{}.bmp'.format. Returns: No return. ''' try: hwnd = hwnd if filename == '': filename = 'yourpath\\{}.bmp'.format( hwnd) hwndDC = win32gui.GetDC( hwnd) # 获取窗口的设备上下文Device Context。GetWindowDC包括了非客户区，而GetDC仅为客户区 # GetWindowDC also gets the non-client area, while GetDC only gets the client area. mfcDC = win32ui.CreateDCFromHandle(hwndDC) # 获取mfcDC saveDC = mfcDC.CreateCompatibleDC() # 创建可兼容DC saveBitMap = win32ui.CreateBitmap() # 创建bitmap以保存图片 '''MonitorDev = win32api.EnumDisplayMonitors( None, None) # 获取显示器信息，枚举显示器，笔记本据说可能有问题''' x1, y1, x2, y2 = win32gui.GetClientRect( hwnd) #GetClientRect获取客户区窗口位置，GetWindowRect获取整个窗口的位置信息 x, y, w, h = (0, 0, 0, 0) if area == None: x = 0 y = 0 w = x2 - x1 h = y2 - y1 else: x, y, m, n = area w = m - x h = n - y saveBitMap.CreateCompatibleBitmap(mfcDC, w, h) # 为bitmap开辟空间 # 对saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)的理解： # 1.mfc相当于一个虚拟屏幕。这里的参数w和h决定了这个屏幕的大小。 # 2.屏幕的初始状态是黑色，每个坐标都是#000000 # 3.之前有mfcDC = win32ui.CreateDCFromHandle(hwndDC)，又有hwndDC = win32gui.GetDC(hwnd) # mfcDC和hwnd窗口之间建立了某种关联，可以将hwnd窗口中的图像放到虚拟屏幕上 saveDC.SelectObject(saveBitMap) # 将截图保存到saveBitMap中 saveDC.BitBlt((0, 0), (w, h), mfcDC, (x, y), win32con.SRCCOPY) # 对saveDC.BitBlt(坐标1, (w, h), mfcDC, 坐标2, win32con.SRCCOPY)的理解： # BitBlt的功能大概是把从hwnd窗口截到的图放到虚拟屏幕上，信息转入saveDC。 # 1.坐标1是针对窗口截图的，指定截图放在黑色背景上的位置（指定左上角） # 2.w和h窗口截图的长宽，而坐标2指定了开始截图的位置 # 这两个参数决定了从hwnd窗口的哪里截图、截多大的图 # 3.mfcDC已经和hwnd窗口建立了关联，所以不需要指定虚拟屏幕从哪个窗口获得截图 # 4.SRCCOPY意为将截图直接拷贝到虚拟屏幕中 # 接下来的saveBitMap.SaveBitmapFile(saveDC, filename)则是对虚拟屏幕截图并保存到指定位置 # Google for more info. saveBitMap.SaveBitmapFile(saveDC, filename) # 清除数据 # GetDC一类的需要用ReleaseDC释放，CreateDC一类的用DeleteDC释放，DeleteObject则删除一个逻辑笔、画笔、字体、位图、区域或者调色板 win32gui.DeleteObject(saveBitMap.GetHandle()) saveDC.DeleteDC() mfcDC.DeleteDC() win32gui.ReleaseDC(hwnd, hwndDC) info('对句柄 {} 标题 {} 的窗口截图并保存'.format(hwnd, win32gui.GetWindowText(hwnd))) except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('客户区截图 出现错误') def G(pattern_filename): '''将pattern的文件名加上路径前缀与类型后缀并返回 Add path prefix and '.bmp' for a pattern pic file and return it. Args: pattern_filename: 模式图片名。Pattern pic file name. Returns: opencv2 可用的路径。The usable path for opencv2. ''' try: global pattern_path # 在全局变量中 # a global variable. return pattern_path + pattern_filename + '.bmp' except: global mode if mode == 'test': traceback.print_exc() elif mode == 'real': error('加模式图路径 出现错误') def Find_Pic(hwnd, pattern, return_pos='l', find_pattern_in_area=None, filename=''): '''寻找图片，找到则返回小图在大图中的位置坐标及模板图大小，否则返回(-1,-1,tw,th)。 Find the pattern pic in the target pic. Return the location and pattern's size if found, or (-1,-1,pattern-weight,pattern-height) if not. https://blog.csdn.net/wz2671/article/details/102751549和https://www.cnblogs.com/ssyfj/p/9271883.html很有帮助。 Above 2 links help. Args: hwnd: 目标窗口的句柄 target hwnd. pattern: 模式图，小图。 The pic to be found, pattern pic, smaller pic. return_pos: 为'l'时返回找到的左上角坐标，'c'则返回中心（偏左上）。 If 'l', return the left-top corner, 'c' the centor pos (if odd, lefter and topper). find_pattern_in_area: 指定在大图的哪个区域查找。None表示在全部区域中找。 In which area of the bigger pic to find. None means the whole area. filename: 指定路径。为''时表示文件名根据hwnd生成。 Indicate the bigger-pic's path. If '', means 'path\{}.bmp'.format. Returns: 如果找到，以(x, y, pat_w, pat_h)形式返回小图在大图中的位置；没找到则返回(-1, -1, pat_w, pat_h)。 The location and pattern's size in the form of (x, y, pat_w, pat_h) if found, or (x, y, pat_w, pat_h) if not. ''' try: hwnd = hwnd ClientRect_PrtSc(hwnd, find_pattern_in_area, filename) if filename == '': # 没有提供文件名则需要改成默认文件名 filename = 'youpath\\{}.bmp'.format( hwnd) pat = cv.imread(pattern) # pattern src = cv.imread(filename) # source # imread的文件名必须带上格式后缀 theight, twidth = pat.shape[:2] # 获取pattern的高和宽 result = cv.matchTemplate(src, pat, cv.TM_SQDIFF_NORMED) # 执行模板匹配，采用的匹配方式cv2.TM_SQDIFF_NORMED # matchTemplate(大图像, 小图像(子图像、模式图像)m, 匹配方式, result 和 mask 可选) # 返回一个矩阵result，大小为(W-w+1)*(H-h+1)，比大图像少了右、下一圈，是子图像左上顶点在大图像中可能出现的位置 # result矩阵中的每个位置，其值表示子图像左上顶点放在该位置时，子图像与大图像上相应区域的匹配度 # result中的点位置和大图像保持一致。 # 关于匹配方式：（） # 1.TM_SQDIFF是平方差匹配；TM_SQDIFF_NORMED是标准平方差匹配。利用平方差来进行匹配,最好匹配为0；匹配越差,匹配值越大。 # 2.TM_CCORR是相关性匹配；TM_CCORR_NORMED是标准相关性匹配。采用模板和图像间的乘法操作,数越大表示匹配程度较高, 0表示最坏的匹配效果。 # 3.TM_CCOEFF是相关性系数匹配；TM_CCOEFF_NORMED是标准相关性系数匹配。将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。 # 总结：随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价)。 min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result) # minMaxLoc(矩阵Mat)，在一个矩阵中找出最大值、最小值、对应序号 # 对于TM_SQDIFF_NORMED模式下最匹配的位置，如果不匹配值大于1%，就认为没有找到。 if min_val > 0.01: return (-1, -1, twidth, theight) global mode if mode == 'test': # 以下代码绘制矩形边框，并将匹配区域标注出来，用于调试 # codes after are used for debug, draw the big/small pic and the location. cv.rectangle(src, min_loc, (min_loc[0] + twidth, min_loc[1] + theight), (0, 0, 225), 1) # 在src图像矩阵中加上矩形，范围是模板图的范围 # rectangle(目标图像, 矩形的一个顶点, 矩形对角线上的另一个顶点, 矩形线条颜色, 线条粗细)返回空值 strmin_val = str(min_val) print('\n匹配度' + strmin_val) cv.imshow("MatchResult----MatchingValue=" + strmin_val, src) # 将画上了矩形的图像在窗口中显示出来 cv.imshow('pattern pic', pat) # imshow(窗口名称, 图像矩阵)，在窗口中显示图像，窗口自动调整到图像大小 # cv.imwrite('1.png', template, [int(cv.IMWRITE_PNG_COMPRESSION), 9]) # imwrite(文件名, 图像矩阵, 格式编码) 将图像矩阵以特定编码保存，暂时用不到 # IMWRITE_PNG_COMPRESSION为png格式，0-9为压缩级别，9为不压缩，消耗时间最少 cv.waitKey(0) # 等待键盘输入任意值，参数表示等待时间（ms），0表示一直等 cv.destroyAllWindows() # 关闭所有窗口 if return_pos == 'c': x = min_loc[0] + twidth // 2 y = min_loc[1] + theight // 2 elif return_pos == 'l': x = min_loc[0] y = min_loc[1] info('在句柄 {} 标题 {} 的窗口找到模式{}'.format(hwnd, win32gui.GetWindowText(hwnd), pattern)) return (x, y, twidth, theight) except: if mode == 'test': traceback.print_exc() elif mode == 'real': error('找图 出现错误') def print_hitted_points(hitted_points, hwnd, deltas): '''测试用函数，根据hwnd找到截图文件（不要重新截图）并标注出点击过的点。 Used for debug, find the big pic by hwnd (No PrtSc again) and mark the clicked pos. Args: hitted_points: 点击过的点。clicked points. hwnd: 用于找到大图。Used to find the big pic. deltas: 如果大图是客户区的一部分截图，该变量可描述大图左上角顶点在整个客户区中的位置。 If the big pic is only part of the window, deltas would help describe big-pic's location (deltas is the left-top corner pos). Returns: No return. ''' try: x1, y1, x2, y2 = hitted_points x1, x2 = x1 - deltas[0], x2 - deltas[0] y1, y2 = y1 - deltas[1], y2 - deltas[1] print('deltas = {}, '.format(deltas)) print('hitted_points = ({},{}) ({},{})'.format(x1, y1, x2, y2)) # 这样就得到了应该标注的坐标 filename = 'yourpath\\{}.bmp'.format( hwnd) src = cv.imread(filename) if x2 < 0 and y2 < 0: cv.circle(src, (x1, y1), 1, (0, 0, 225), 4) # cv.circle(img, point, point_size, point_color, thickness)本来用来画圆的 # 参数分别是图像矩阵、圆心、半径、线的颜色、稠度 # 稠度可以取0、4、8，画出来点的大小不同 cv.imshow('single one----hitted points', src) elif x1 == x2 and y1 == y2: cv.circle(src, (x1, y1), 1, (0, 0, 225), 4) cv.imshow('double same----hitted points', src) else: cv.circle(src, (x1, y1), 1, (0, 0, 225), 4) cv.circle(src, (x2, y2), 1, (0, 0, 225), 4) cv.imshow('double diff----hitted points', src) cv.waitKey(0) cv.destroyAllWindows() except: traceback.print_exc() def FindPic_RandomLeftClick(hwnd, pattern, max_try=20, time_interval=0.5, click_strategy=1, times='first', click_areas=None, find_pattern_in_area=None, r=4, platform='PC', click_pos='l', filename=''): '''从指定的句柄窗口寻找图片，若最大次数内找到则执行随机区域左键点击，否则返回False。返回点击的坐标(x1,y1,x2,y2)，若只点击了一次则返回(x1,y1,-1,-1)。 这是一个整合程度高函数，可能要看一下其中用到的其他函数。 Find a pattern pic in the hwnd window, if not found after max_try, return False; if found, operate a click_strategy, and return clicked pos. If clicked only once, return (x1,y1,-1,-1). This func is highly intergrated. Turn to some called sub-funcs if confused. Args in detail: hwnd: 要截图并点击的窗口句柄。The window to PrtSc and click. pattern: 要寻找的模式小图。The pattern-pic's path to be found. max_try: 指定最多寻找的次数。If not found, after max_try, it will let go. time_interval指定每次寻找的间隔时间（实际查找间隔比该时间多一点）。 Interval between each try (a little longer than given, in fact). click_strategy表示点击策略，详见Random_Areas_LeftClicks函数。 Indicate the click strategy, see also in Random_Areas_LeftClicks(). times: 'first'表示从其他窗口转过来点击，用于调用Activate_Hwnd(hwnd)。 If 'first', means target window is inactive/unfocused, thus call Activate_Hwnd(hwnd). click_areas: 可选的点击范围（矩形）。格式为[[x1,y1,x2,y2],[x3,y3,x4,y4]...]，只有一个区域则可以写成[x1,y1,x2,y2]。为None时表示就点模式小图所在的区域。 Possible rect-areas to click, given in the form of [[x1,y1,x2,y2],[x3,y3,x4,y4]...]. If only one area, [x1,y1,x2,y2] is also acceptable. If None, means to click the area where pattern pic is found. find_pattern_in_area: 指定在窗口客户区的哪个区域寻找模式图，为None时表示在整个客户区寻找。 Which rect-area of the client area of the window to find the pattern pic. If None, means find in the whole area of the client area. find_pattern_in_area从技术上是只截取客户区该区域的图实现的。 If not None, technically, it works by only PrtSc the partly area of the window's client area. r: 指示对指定的点击区域，应该内收多少个像素点。对于高或宽<4的模式图，可能需要自己把r设置成更小的值。 Shrink r pixels for each click_area. For pat-pic smaller than 4 pixels, adjust r to a smaller value. platform: 目前无用。'PC'表示当前操作的是桌面版，不是安卓模拟器('AM')。 Useless now. 'PC' means target window is PC, not Android manipulator ('AM'). click_pos: 可取值'l'或'c'，l表示left_top，后者表示center。详见Find_Pic()。 Possible values are 'l' and 'c'. See also in Find_Pic(). 用于指示在窗口中找到模式图后，是返回其左上坐标还是中心点坐标（模式图长宽为奇数时返回值偏左上）。 'l' means left-top corner pos, 'c' means center pos, used by Find_Pic(). 现在暂时只用'l'模式，'c'模式可能用于以后功能拓展。 For now 'l' is enough, 'c' may help expand furthur functions. filename: 手动指定大图文件，从该文件中查找模式图。一般用不到。 Indicate the big-pic's path manually, not used in ordinary applications. Returns: 若最大次数后仍未找到模式图则返回False。 若找到模式图，返回点击的坐标(x1,y1,x2,y2)，若只点击了一次则返回(x1,y1,-1,-1)。 If pattern pic not found after max_try, return False; if found, return clicked pos in (x1,y1,x2,y2). Return (x1,y1,-1,-1) if only clicked once. ''' try: global mode x, y = -1, -1 deltas = ( -1, -1 ) # 这是截图区域与整个客户区的左上顶点的相对位置。用于测试 # Used for debug, in print_hitted_points(). for i in range(max_try): x, y, twidth, theight = Find_Pic(hwnd, pattern, 'l', find_pattern_in_area, filename) if x == -1 and y == -1: if mode == 'test': print('\r第{}次没找到'.format(i + 1), end='') sleep(time_interval) continue else: if find_pattern_in_area == None: # 若使用默认的全客户区查找，返回的坐标是相对于整个客户区的 delta_x, delta_y = 0, 0 else: # 指定了查找区域，则返回的坐标是相对于查找区域的，需要转换一下 delta_x, delta_y = find_pattern_in_area[ 0], find_pattern_in_area[1] if click_areas == None: # 不给出点击区域，则默认点击区域是窗口找到模式图片的区域 click_areas = x + delta_x, y + delta_y, x + twidth + delta_x, y + theight + delta_y if mode == 'test': deltas = (delta_x, delta_y) break if x == -1 and y == -1: info('未能找到并随机点击：对句柄 {} 标题 {} 的窗口未找到模式{}，等待了{}次*{}秒'.format( hwnd, win32gui.GetWindowText(hwnd), pattern, max_try, time_interval)) return False else: if mode == 'test': # 在测试模式下，画出点击了窗口上的哪些点 hitted_points = Random_Areas_LeftClicks( hwnd, click_areas, times, platform, r, click_strategy) print_hitted_points(hitted_points, hwnd, deltas) return hitted_points elif mode == 'real': return Random_Areas_LeftClicks(hwnd, click_areas, times, platform, r, click_strategy) except: if mode == 'test': traceback.print_exc() elif mode == 'real': error('找图并随机左键点击 出现错误') if __name__ == '__main__': try: click_areas = [292, 175, 314, 192] find_pattern_in_area = [44, 82, 245, 313] # [44, 82, 100, 150] print(FindPic_RandomLeftClick(3212840, G('pattern1'), click_strategy=2)) except: traceback.print_exc() 配置文件：# 键盘码 VK_CODE = { 'backspace': 0x08, 'tab': 0x09, 'clear': 0x0C, 'enter': 0x0D, 'shift': 0x10, 'ctrl': 0x11, 'alt': 0x12, 'pause': 0x13, 'caps_lock': 0x14, 'esc': 0x1B, 'spacebar': 0x20, 'page_up': 0x21, 'page_down': 0x22, 'end': 0x23, 'home': 0x24, 'left_arrow': 0x25, 'up_arrow': 0x26, 'right_arrow': 0x27, 'down_arrow': 0x28, 'select': 0x29, 'print': 0x2A, 'execute': 0x2B, 'print_screen': 0x2C, 'ins': 0x2D, 'del': 0x2E, 'help': 0x2F, '0': 0x30, '1': 0x31, '2': 0x32, '3': 0x33, '4': 0x34, '5': 0x35, '6': 0x36, '7': 0x37, '8': 0x38, '9': 0x39, 'a': 0x41, 'b': 0x42, 'c': 0x43, 'd': 0x44, 'e': 0x45, 'f': 0x46, 'g': 0x47, 'h': 0x48, 'i': 0x49, 'j': 0x4A, 'k': 0x4B, 'l': 0x4C, 'm': 0x4D, 'n': 0x4E, 'o': 0x4F, 'p': 0x50, 'q': 0x51, 'r': 0x52, 's': 0x53, 't': 0x54, 'u': 0x55, 'v': 0x56, 'w': 0x57, 'x': 0x58, 'y': 0x59, 'z': 0x5A, 'numpad_0': 0x60, 'numpad_1': 0x61, 'numpad_2': 0x62, 'numpad_3': 0x63, 'numpad_4': 0x64, 'numpad_5': 0x65, 'numpad_6': 0x66, 'numpad_7': 0x67, 'numpad_8': 0x68, 'numpad_9': 0x69, 'multiply_key': 0x6A, 'add_key': 0x6B, 'separator_key': 0x6C, 'subtract_key': 0x6D, 'decimal_key': 0x6E, 'divide_key': 0x6F, 'F1': 0x70, 'F2': 0x71, 'F3': 0x72, 'F4': 0x73, 'F5': 0x74, 'F6': 0x75, 'F7': 0x76, 'F8': 0x77, 'F9': 0x78, 'F10': 0x79, 'F11': 0x7A, 'F12': 0x7B, 'F13': 0x7C, 'F14': 0x7D, 'F15': 0x7E, 'F16': 0x7F, 'F17': 0x80, 'F18': 0x81, 'F19': 0x82, 'F20': 0x83, 'F21': 0x84, 'F22': 0x85, 'F23': 0x86, 'F24': 0x87, 'num_lock': 0x90, 'scroll_lock': 0x91, 'left_shift': 0xA0, 'right_shift ': 0xA1, 'left_control': 0xA2, 'right_control': 0xA3, 'left_menu': 0xA4, 'right_menu': 0xA5, 'browser_back': 0xA6, 'browser_forward': 0xA7, 'browser_refresh': 0xA8, 'browser_stop': 0xA9, 'browser_search': 0xAA, 'browser_favorites': 0xAB, 'browser_start_and_home': 0xAC, 'volume_mute': 0xAD, 'volume_Down': 0xAE, 'volume_up': 0xAF, 'next_track': 0xB0, 'previous_track': 0xB1, 'stop_media': 0xB2, 'play/pause_media': 0xB3, 'start_mail': 0xB4, 'select_media': 0xB5, 'start_application_1': 0xB6, 'start_application_2': 0xB7, 'attn_key': 0xF6, 'crsel_key': 0xF7, 'exsel_key': 0xF8, 'play_key': 0xFA, 'zoom_key': 0xFB, 'clear_key': 0xFE, '+': 0xBB, ',': 0xBC, '-': 0xBD, '.': 0xBE, '/': 0xBF, '`': 0xC0, ';': 0xBA, '[': 0xDB, '\\': 0xDC, ']': 0xDD, "'": 0xDE, '`': 0xC0 }