Featured post

贷款 – 步骤简谈

首先恭喜你找到一位放心、省心、有责任心和有能力的loan officer (简称LO)给你做贷款(在美国有时得自我宣传,请别见怪)。贷款过程取决于情况需要30-60天,比较少有的情况会超过60天的。整个过程有不少步骤,这里简单介绍一下,帮助了解全过程。如果不想了解也没关系,你的LO会一步一步引导你完成贷款全过程。注意给你打电话的人只有你的LO和最后约当面签字时间的人,lender不会打电话。

  • 1. 准备材料:按照LO提供的材料准备清单来,这一步最快有人半小时搞定,因为所有资料都有电子版,并且平时就整理好了。正常的话,花1-2小时focus time应该就可以搞定。慢的话可能要1-2天或更长。
  • 2. 做loan file与锁定利率:你的LO会用你提供的资料,花时间做你的loan file,这个过程中要pull credit report,并且可能问你额外的问题。在我这里不用自己填贷款申请表,自己填经常不知道怎么填或很容易填错
    • 做完loan file会提交给lender,之后如果利率在你预期内即可锁定,如果不在可以耐心等。一旦利率锁定,不能更改,利率涨跌都没关系了。
    • 注意贷款期间最好不要开新的credit(e.g 开信用卡、买车等),也最好避免大额资金转账,保持银行帐户clean和有足够余额
  • 3. 电子签字初始文档:1-3天内Lender会发一些文件电子签字。大部分是disclosures,快速过一眼即可。需要重点看的是Loan Estimate (LE),里面有很多数字。如果需要的话,你的LO会让你明白每一个数字,是的,每一个数字。1003 application也可以快速看一下,里面的数字如果跟LE不一致,以LE为准。有的lender可能会寄这些文档的hard copy到家,电子签过所以不用管
  • 4.1 初步Review: Lender会初步review你的loan: 这一步可能会让你提供新的文件,并不是都要
    • 如果appraisal被waived,签waiver文件。我这边10套房子中在我的争取下有8-9套能够拿到waiver,所以拿到waiver是大概率事件。
    • 如果appraisal不能被waive掉,就要做appraisal,可能要$700左右费用需要先付。投资房appraisal需要加$150左右,因为需要估租金
    • 找前一家lender拿payoff statement可能需要签authorization
    • Condo需要HOA questionnaire和master insurance policy,新Condo会需要很多其它文档。尽快联系你的HOA company,可能有$100-$300的费用。有的HOA给力,有的不给力。邮件2天不回就得打电话。
  • 4.2. Title and Escrow: Title and Escrow公司会联系你,与我合作很多的是一家很好的公司叫Chicago Title,联系人是 Lachmi Murjani (Lachmi.Murjani@ctt.com, Escrow Assistant) and Jun Lu (Jun.Lu@ctt.com, Escrow Officer)。第一封邮件是系统自动发的,发件人是noreply@title.com,注意查收因为可能会进spam folder。
    • 会让你填payoff authorization,escrow公司会找你现在lender拿payoff statement
    • 给你发wire instructions,里面有不少红色字体提醒wire transfer fraud
    • 会让你填questionnaire如下图。Lender Name和Loan Account Number填你现在的贷款;Pay Off Loan As Part of Closing 在refinance时要填YES,因为新贷款会取代旧贷款;Have your entered into a forbearance…? 一般填NO,因为我的客户财务状况都不错,不存在这种少见的情况
  • 5. 审核批准:
    1. 审核贷款的人的叫underwriter,中间可能找你要更多文档: 新的paystubs,bank statements,mortgage statement;解释credit report里的credit inquiries;HELOC subordination agreement;解释大额存款;需要保证银行帐户有足够余额等。underwriter在所有conditions都被解决后会批准你的贷款,进入CTC (Cleared to Close)。
    2. CTC前后lender会准备你的Initial Closing Disclosure(CD),这个文档跟之前看到的Loan Estimate很像,建议仔细看,有问题尽快告诉LO让lender修改。CD需要产权人配偶手签后扫描发给lender
  • 6. 签字和打款给escrow
    • escrow会打电话约签字,快签字那几天手机最好随身携带。可以去escrow office签字,也可以让escrow派人上门(escrow电话时会说收费$95,但大部分情况下已经包括在escrow fee里)。在车库门口或后院签字,戴口罩保持距离,比较安全。打电话的人对贷款的人信息了解不多,escrow会发邮件确认appointment,里面会提到escrow会另外发邮件要打多少钱等等,有问题可以回那封邮件
    • 已结婚并且夫妻都在产权上,需要都在场签字
    • 携带Driver’s license。如果lender是Provident Funding,需要带绿卡 或 I-797 with current visa
    • 建议签字前把Closing Disclosure上的数字都看一遍,避免在签字的时候对数字有疑问而影响签字
    • 签完字后尽快按wire instructions做wire transfer,或者提前准备Cashier’s check在签字时给escrow公司,注意需要用之前提交过的银行帐户,否则会导致不必要的麻烦。wire transfer一般10分钟就可以在网上完成(但有些网上银行譬如Discover Bank麻烦一些最好提前准备)
    • 如果已经付了房产税,但closing时在prepaids里交了6个月,escrow公司会退给你
  • 7. 签字后Funding
    • 有些lender会做funding review,可能会有新的conditions,譬如说VVOE(verbal verification of employment)不顺利,wire transfer的银行不是之前提交的,master insurance policy需要更新等等。lender也会找escrow company要不少材料
    • Funding review通过后就正式funding,escrow公司会负责disburse funds给各方并在country record,之后贷款正式结束。
    • 前一个lender那边的escrow account里的钱会退给你,如果一个月内没收到check,建议打电话问前lender。
    • 特别注意:半年内不能再做refinance或者卖房,否则会有penalty因为lender会亏损
  • 8. 新lender
    • 新lender会寄mail给你(这步一个月内寄到都正常,注意查收mail),有的lender譬如Rocket Mortgage/Quicken Loans会发电子邮件),拿到信后在网上setup account和设置自动还款。如果mail没收到或者弄丢了,建议在网上找客服电话打过去。一些lender用的网站 Dovenmuehle Mortgage – https://dmi.yourmortgageonline.com/ and One American – https://oneamericanmortgage.myloancare.com
    • 一般来说close之后的那个月的mortgage payment不用付,譬如说10月close,11月不用付月供, 12/1付第一次月供。
    • Lender有可能会把你的贷款卖给Fannie Mae or Freddie Mac,这在美国很常见,loan servicing(就是交月供的地方)也可能会转到其它公司。

上面说的是简化流程,在后台有很多事要做和可能发生的异常情况要处理,你的LO,lender,title&esrow company等公司会处理,请理解lender, title&escrow等公司不少事情都不在Loan Officer控制范围内。这整个过程中,给你打电话的人只有你的LO和最后约当面签字时间的人,给你发邮件的人只有Lender和Title/Escrow company,任何其它联系你贷款的人都跟本次贷款无关。请联系你的LO whenever in doubt。

做贷款要多久

现在做refinance几乎是全民运动,导致refinance比以前慢。另外每家lender不一样,利率好业务量大的会更慢。One American从lock rate那天到签字,绝大部情况要45-60天。有多套房子或其它复杂情况时间时间会更长(甚至有3个月的)。Quicken Loans 绝大部分情况下30-40天。Provident Funding 绝大部分情况45天内。

贷款 – 常见lenders

我之所以能够拿到很好的利率,主要原因是跟不少wholesale lenders打交道,然后在其中选最好最合适的。不同的lenders特点不一样,现在我把常用的几家lender简单比较一下,供大家参考。跟设计软件系统没有perfect design一样,贷款没有perfect lender,需要根据情况来做trade-offs,适合你朋友的lender不一定适合你,即使同一样lender,不同时期也会不一样。

One American Mortgage

Pros: 利率很好,即使是投资房或cashout情况,另外有free lock extension,压力比较小,有异常情况退出没有penalty

Cons: 慢,W2和只有一套自住房的情况要45-60天,其它情况3-4月的都有。由于慢并且由于COVID,要文件(paystub, bank statement等)的次数会多一些

Quicken Loans

Pros: 很大的一个lender,上市公司,内部系统和流程做得比较好。大部分情况30-40天close,在有促销活动时,自住房子high balance loan的利率和15yr fixed利率很好

Cons: 有些时候利率一般,有时间压力,borrowers和loan officer响应都需要快,escrow company也会有时间压力

Provident Funding

这是一家不错但也比较挑剔的lender,审核比较严格,有很多自家规定,主要适合相对简单一些的情况

Pros: 利率不错。Close时间比较稳定,一般45天内。给borrowers的portal不错,告诉你贷款进展和给贷款人的TODO List

Cons: 审核比较严格并且有不少独特的规定,由于多种原因要做appraisal的概率比较大,lock利率后由于各种原因不做贷款了有penalty (找loan officer要但最后来自消费者)。如果45天不能close(比较少见),延期要收费。有一些时间压力,borrowers和loan officer响应都需要快。退出成本很多时候是$800+的appraisal fee + $500 penalty

贷款 – 询价篇

美国贷款利率由于多种原因现在处于近50年来历史低位,而且反常的是15yr/30yr fixed利率比ARM低(jumbo除外),从而触发一波波澜壮阔的refinance潮。做refinance首先涉及到一个询价的问题,今天分享一下这方面的经验。首先,每个人的情况都不一样(e.g. 房产估值,贷款额,信用分,收入,自住还是投资,是否cashout,是否买点或出closing cost等),每天的利率也不一样,你能拿到的利率跟你的朋友、同事和邻居可能都不一样,所以不要跟别人做过多比较。

如果工作和生活很忙,没有太多时间研究和比价,那就找一二位你信得过的loan officer来问一下,或找现银行/lender和一位你信得过的loan officer。也许拿到的不是市场最低,但仍然会是不错的deal。其实即使你花很多时间研究和比价,也不一定拿到最低。

如果你有足够时间、精力和兴趣来比价,可以多找几家来估,自己也研究一下适合自己情况的选项。但我在熟谙多个行业之后,经常说一句话,隔行如隔山,you don’t know what you don’t know。即使你在IT行业是partneer engineer/mgr,在另一个行业可能是entry level engineer。我知道一部分人花了大量时间研究比较,但是一些很基本的信息仍然不太了解。下面我分享一些有用信息供参考 (注意这里说的主要针对conforming/high balance loans,大额jumbo loans请直接联系大银行)。

  1. 因为每天利率不一样,每天可能变化多次,在不同的时间比价可能不准确。譬如说在一家好的broker估价的那天正好利率一般,但在另一家一般的broker那估的那天利率正好比较好,你可能觉得第二家更好但其实不一定。所以为了公平准确起见,最好在同一天同一时间段拿多个估价,因为上午下午可能也不一样。
  2. 估价需要好几个参数,不需要递交个人资料(工资单,w-2, SSN等),也不需要pull credit。有的公司或个人可能找你要不少资料,然后直接就pull你的credit,这种做法有想锁定客户的嫌疑。我从来不会这么做,quote时不要个人资料,也不pull credit,并且给客户足够时间shop around。不过,被pull了credit也不用太担心,30天内为了贷款pull的多次credit会被算为一次pull,对credit score的影响并不大,特别是在你信用分比较好的情况下。
  3. 建议找信得过靠谱的人,建议找信得过靠谱的人,建议找信得过靠谱的人。由于接触的人多,我知道很多找不认识的人做贷款利益受损/体验不好/没有peace of mind的实际例子。麻烦的地方是隔行如隔山,利益受损或者别人给你不真实的信息你可能都不知道。对不认识的人来说,如果没做好,损失一个不认识的客户没什么,反正现在做贷款的人多。而且很多人没有做长期business的mindset,能做一单就做一单。也有不少人是给银行打工的,没做好也没什么。所以为了低0.125%的利率或低一些cost找不认识或不确定靠谱不靠谱的人,没有peace of mind,没有人帮你回答和解决问题,不一定值得。贷款利率锁定后还有很多工作要做,后面的服务很重要。选做贷款的人要看哪家信得过,哪家更放心、更省心,哪家能够给你提供更多的value,哪家愿意为你争取最大利益,哪家能用帮你搞定unexpected situation,哪家你将来还会用到。
  4. IT圏朋友特别喜欢网上估价,方便而且不用跟人沟通,但在网上询价要特别注意一些“坑”
    1. 估价本身其实是不需要名字,邮件,电话的,更不需要pull credit。如果你提供了个人信息,之后收到多个骚扰电话不要奇怪
    2. 网上可能用很低的利率来“吸引人”(引人上勾),譬如说15yr fixed 2.125%,但实际上后面有不少cost。有些时候一听就知道是too good to be true
    3. 网上可能用好一丁点的利率吸引人,譬如你找broker拿到的是15yr fixed 2.5% no cost,网上可能给2.49% no cost
    4. 网上可能会说$1 lender fee,利率也不错。当你开始做的时候,他们会说还有一笔third party fees
    5. 在网上看到不错的利率,但有时你不知道最后给你做的人到底是谁,人品如何,是否会给你争取最大利益;能力如何,能不能搞定你的贷款,碰到unexpected情况怎么办等等;服务如何,是否快速反应,是否沟通顺畅等等。我好几年前在zillow mortgage上找过一家利率最低的做贷款,最后拿到的不是网上给的估价,他给的原因在我成为专业人士后才知道他骗了我,但我当时没有能力判断。
  5. 贷款可能有多个选项供选择:是否买点,是否付一些closing cost,是否cashout,是否把cost做进贷款里,是否要escrow account,15年还是30年,是否等ARM到期等等,很多问题的回答需要足够了解你的个人情况和做专业的分析,不是一个简单的no cost option就能cover的,也不是一般水平的人能做得好的。
  6. 不要不好意思去找你认识信得过的朋友询价,千万不要有询价就要找他/她的压力。一位好的broker,会很乐意提供询价和有用信息,不管做不做这一单。如果他/她介意,那大概率不是一位好的broker,不找也没关系。找认识信得过的人的好处是你可以得到真正实在的信息(不至于被欺骗),可以得到更多的attention,会为你争取最大利益,沟通更好,总的来说会提供更好的服务。
  7. 关于寄到家里的贷款广告:基本上可以扔掉,原因就是之前提到的,#1 利率每天变化,有时变化还很大,从寄信到收到到你打电话过去好多天过去了,他们不可能总是能提供他们说的,上面一定有不少fine prints. #2 打这种广告的人会用很低的利率拉你上勾,这基本上是唯一他们能提供的诱饵 #3 你对做广告的公司或人估计完全不熟,他们也不了解你 #4 打广告的人其实是发给很多人,只要有一小部分人上勾就可以 #5 你有可能用了一些”免费”的credit score monitoring service,你的信息被卖掉了
  8. 一旦选一家开始做了,特别是锁定利率后,最好不要随意退出。细节可参考我的另一篇blog:贷款 – refinance利率锁定后退出?

贷款 – refinance利率锁定后退出?

今天聊一小部分人碰到的困扰,那就是找loan agent/broker做refinance,并锁定了利率,然后利率变低或者有人给更好的quote,产生退出的念头怎么办?

首先,refinance中途退出没有法律责任,可能有一些财务上的损失(要付已经发生的credit report fee和appraisal fee),主要伤的是人品/reputation。虽然法律上有权利退出,但lock rate代表一种promise。如果这么做,是否还会break 别的promise?

其次,退出在broker这边有一些后果

  1. 你的broker可能被lender/broker公司罚款。有的lender会看fallout比例,到一定比例lender会中止跟这位broker的合作
  2. 对broker所在公司有一些负面影响
  3. 一旦利率锁定,很多人开始为你服务。虽然你看到的主要是broker,后面可能还有loan processor, lender公司多个人, title公司多个人, escrow公司多个人, appraisal公司多个人等,退出意味这些人的付出白费,也意味着broker的credit会被影响。

最后,要考虑一些退出的好处是什么,很多时候就是0.125%的利率或者一小部分closing cost。今年迄今为止利率总体而言在下降,如果锁定3.0%还没close,利率降到了2.875%想要退出,那之后降到2.75%或更低要不要再次退出?要知道,如果利率一直下降,半年之后总可以再次refi。还有,为了一点小小的好处,退出后换一个人做refi,你对这位新的人了解有多少,靠谱不靠谱,更低的quote之后是不是有tricks,服务质量如何等等都需要问,不能只看表面上的数字。

有少数可以理解的原因退出没有多大影响 ,譬如说工作或房子出了大问题,不过这比较少见。对于中途退出有两条好的建议如下

  1. 确定找一个人做贷款之前尽量做好功课,找某一位多次 quote都没问题。锁定利率跟买股票类似,很难或几乎不可能拿到最低点,满足预期即可。利率每天都在变化,没人能预测未来。
  2. 如果一定要退出,跟broker说明白,尽量坦诚,也许能找到好的解决方案,退出是lose-lose,找到方案是win-win。如果找不到解决方案也没关系,好好沟通,以后也许还有合作机会,毕竟没有人是完美的,这个世界也不完美,有时中途退出这种不多见的体验对双方都是一种成长的机会。

Repurposing my blog

My original idea was to make this a purely technical blog. When I was working on building the core infrastructure in Azure I thought that I could write something about how it was built. However I couldn’t write much because most of the time I was working on confidential projects. Cloud computing is a very competitive area as you may know. The 2nd reason is that there is already so much useful info on technologies and I wouldn’t be able to provide the best value by focusing on only technical stuff.

Anyway I have decided to write whatever I think can provide more value. The audience is people in the United States. I will write in Chinese most of the time since there is less info in Chinese. The main focus will be IT and Real Estate.

Solving CORS issue became easy

// If you don’t have time just jump to the last section – takeaway. If you do that solving CORS issue will be easy.

CORS stands for cross origin resource sharing. Let me use a simple example to explain the basics.
Say that you have a web site http://foo.com and it has a client side javascript which uses AJAX to call http://bar.com to get some info. That is a CORS request. To make the request successfully the server needs some change to allow CORS requests.

What is considered cross origin? Use http://foo.com as an example the below urls are considered as different origins.
Https://foo.com (different scheme)
Https://foo.com:8080 (different port)
Https://api.foo.com (different subdomain)
Https://bar.com (different domain)

In some cases a complaint browser may send a preflight request before it allows the request to be sent. Let me use a real case to explain.
Scenario: Client side uses token authentication to get info from server side

1. The client side javascript sends a POST request to https://localhost:44300/Account with token (basically http header “Authorizattion”:”Bearer aAbdkkixlkid…”)

2. The browser determines a preflight request is needed and it sends preflight request
3. The server has to respond with status code 2XX AND with required headers. In this case Access-Control-Allow-Origin cannot be *. Access-Control-Allow-Headers has to contain Authorization.
4. The browser then sends the actual request.

preflight request

actual_request

Actual request

preflight_request

Takeaway

I spent a lot of time solving my particular case and read tens of links. In the end it I found that it could be much simpler and quicker if I knew the below two things.
1. Read just one link https://msdn.microsoft.com/en-us/magazine/dn532203.aspx
2. Do check the console message when useing developer tools in browser. I didn’t check the console message. Otherwise it could have saved me a lot of time. The below is a screenshot from Chrome. It tells exactly what went wrong. It makes trouble shooting much easier.

chrome_console

Big Bonus if you are using ASP.NET Web API

Web API presents a unique challenge that the “/Token” service is different from the normal Web API controllers and the nuget cors package only works for web API. Some people suggest adding the below in web.config. It will work for “/Token” service but NOT web api especially when you are using https. The chrome browser does not allow “*” in Access-Control-Allow-Origin.

<add name=”Access-Control-Allow-Origin” value=”*” />

The solution is adding the below code at the top in IdentityConfig.cs.

if (string.Equals(context.Request.Uri.PathAndQuery, “/Token”, StringComparison.OrdinalIgnoreCase))
{
context.Response.Headers.Add(“Access-Control-Allow-Origin”, new[] { “http://foobar.com” });
}

 

 

TF401189: The source branch has been modified since the last merge attempt

If you are using Visual Studio Online and setup your project using TFS doing a code review is straightforward in visual studio.

However ff you are using Visual Studio Online and setup your project Git you might wonder how you can conduct a code review. You may do a quick search and then try ‘new pull request’ . You might get a weird error message you don’t understand.

TF401189: The source branch has been modified since the last merge attempt

Then you do another search (bing or google) you won’t find anything useful.

After trial and error I found that the root cause is that I didn’t use a topic branch. It is that simple.

Two useful links as below

https://www.visualstudio.com/get-started/code/git/pullrequest
https://blogs.msdn.microsoft.com/visualstudioalm/2014/06/10/conduct-a-git-pull-request-on-visual-studio-online/ (unfortunately all the images are missing)

Debugging a weird process crash issue

I recently debugged a very interesting process crash issue. The code was running in the cloud so I could not just attach the debugger as easily as on my dev box. Besides using debugger should be the last option in my opinion. So I logged on to the machine. Well before that I had to go a through a process to get permission and get the environment ready for security/compliance reason. I observed that the process was recycling by using taskmgr. So I did the below things
1. Checked the logs. No exceptions. No errors. No logs related to the crash
2. Checked crash dump files. No files were there
3. Checked OS eventlog. No crash events. Normally for any process crash there is at least one event

I never saw a process crash like this. But I knew the related code which caused this. It was a background task kicked off by calling Task.Run(). I thought that there must be some unhandled exceptions but I checked the code. There was already a catch block which caught all exceptions. However it was still possible that the catch block might throw exception. So I put another catch all inside the catch block to make sure that no unhandled exception was thrown.

However it did not work. The process was still crashing. I asked around about how a process could crash since I was relatively new to the code base. I got some pointers but none of them could match what I observed.

Then I had to turn to the last option. I copied windbg to all the nodes (remember that this is distributed system and there are multiple replicas) and hooked it up with the process. Boom! I got an exception in the debugger and then the process crashed.

I looked at the exception which was a normal .net exception. I could not think of a reason how it could cause crash. Then I looked into the call stack and saw the below line.
000007f9`8538bb27 : 0000001b`9c29cf80 0000001c`2c50c880 0000001c`2c50c888 0000001c`2c50c890 : mscorlib_ni!System.Environment.Exit(Int32)+0x7b

That was really weird. My code was calling a library from another team. So I got the tool ILSpy (I don’t use .net reflector anymore btw) and looked into the code. Man the code was calling Environment.Exit() when a certain exception threw! That explained everything. As for why the coding was doing so this was a new library and I guess that the piece of code was copied from somewhere else.

From the above text it looked that it didn’t take much time. In reality two days passed.

StackOverflow Exception, Long time no see

I have not seen a stackoverflow exception for a long time. Today I happened to bump into one in random test code. I will explain how it happened. What the code is used for and why it was written this way are not interesting to me and are not in the scope of this post.

    public class ChildClass : BaseClass
    {
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                base.Dispose();
                //DO something
            }
        }
    }

    public class BaseClass
    {
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                //DO something
            }
        }
    }

As you can see the stackoverflow exception will happen as the below
1. Child.Dispose(bool)
2. Base.Dispose()
3. Child.Dispose(bool)
4. Base.Dispose()