前置:分工、比较优势与交换 · 市场价格与弹性 · 国内生产总值与国民收入 · 利率、储蓄与投资
一种商品可以从国外更便宜地买到,消费者可能受益,本地生产者却可能失去订单;本币贬值后,同一家企业的出口报价更有吸引力,进口零件和外币债务又变贵。只说“贸易有益”或“贬值利好出口”,还没有把具体主体的账算完。
本篇先固定汇率分析开放与关税,再固定商品标价观察汇率变动。所有数字均为教学设定,两步有不同的固定条件,不能把其中一个结果不加调整地移到另一步。
开放市场怎样改变本地价格和数量
设一种商品的国内需求为 Qd=30−2P,供给为 Qs=2P,价格用本币计。没有贸易时,两者相等,得到 P=7.5、Q=15。
现在允许按固定世界价格 4 进口。本国市场足够小,购买量不影响这个外部价格,运输成本暂设为零,商品质量相同。国内价格降到 4,需求为 22,国内生产为 8,进口补足 22−8=14。
| 指标 | 无贸易 | 自由进口 |
| 国内价格 | 7.5 | 4 |
| 国内消费 | 15 | 22 |
| 国内生产 | 15 | 8 |
| 进口 | 0 | 14 |
消费者购买更多,本地生产者缩减产量。进口不是新增需求的同义词,也不是把原来 15 单位本地产出直接换成 15 单位外国商品;需求和国内生产都沿各自关系调整。
在无外部性、竞争和调整成本为零等条件下,这个开放模型的国内消费者与生产者剩余合计增加 24.5。但生产者自身可能受损。潜在总收益不能当成每位工人或企业已经收到补偿的证明。
加征每单位一元关税,谁的账变化
保持世界供给价格 4 不变,加每单位进口税 1,并假设完全执行、仍有进口,国内价格变为 5。需求降到 20,国内生产升到 10,进口降到 10。
消费者因价格从 4 到 5 而减少的剩余,是梯形面积 (22+20)/2×1=21;国内生产者增加的剩余为 (8+10)/2×1=9;政府税收为 1×10=10。
| 国内主体 | 剩余或财政收入变化 |
| 消费者 | −21 |
| 国内生产者 | +9 |
| 政府 | +10 |
| 合计 | −2 |
其中 19 从消费者转给国内生产者与政府,另有 2 没有成为任何国内主体的收益。一部分来自本地改用成本较高的生产替代进口,另一部分来自原本愿意按世界价格购买的消费消失;两块三角形各为 1。
不能把税收 10 当成纯新增收益,再忘记消费者已付出它;也不能把国内新增两单位生产直接当作净福利改善。这里刻意使用小国、固定外价与无其他市场失灵的模型;外国报价变化、报复、规模效应或国家安全等目标属于需要另建的机制,不能偷偷放进这个计算结果。
过渡中的人,不会自动变成总量数字
开放后受到竞争的工人可能需要转岗、搬迁或培训,设备也可能专用于旧行业。这些成本会落在特定地区和家庭,时间上早于新的机会。长期比较优势的收益空间,并不取消这些实际代价。
政策可以尝试支持转岗、保险、公共服务或调整速度,但是否有效,需要看执行对象和结果。补偿在算术上可能存在,与社会已经决定并落实补偿,是两件事。
同样,保护某些岗位可能让使用进口投入的其他企业承担成本。研究一项规则时,应沿上下游、消费者和财政找主体,而不是只展示受保护的一家工厂。
换到汇率:先写单位再算
用 L 表示本币,F 表示外币,定义汇率 e 为“每 1 F 需要多少 L”。从 e=7 到 e=8,购买同一单位外币要付更多本币,即 L 对 F 贬值。
| 固定原币标价的项目 | e=7 | e=8 |
| 进口品标价 10 F,本币账单 | 70 L | 80 L |
| 出口品标价 70 L,外国买方账单 | 10 F | 8.75 F |
| 外币债务 100 F,本币偿付额 | 700 L | 800 L |
进口与债务用外币金额乘 e,出口的外币报价用本币金额除以 e。若采用相反的汇率报价,数字方向也会反过来;“汇率升了”不先说明单位,就很容易产生误会。
正在呈现知识画面
改变条件,核对结果汇率定义为每 F 的 L 数。7 变为 8 时,10 F 进口成本从 70 L 到 80 L;70 L 出口品由 10 F 到 8.75 F;100 F 债务由 700 L 到 800 L。
{"id":"economics-25","title":"改变条件,核对结果","summary":"汇率定义为每 F 的 L 数。7 变为 8 时,10 F 进口成本从 70 L 到 80 L;70 L 出口品由 10 F 到 8.75 F;100 F 债务由 700 L 到 800 L。","height":750,"html":"<div class=\"controls\"><label for=\"rate\"><span data-i18n=\"rate\"></span><output id=\"out-rate\" for=\"rate\"></output><input id=\"rate\" type=\"range\" min=\"4\" max=\"10\" step=\"0.5\" value=\"7\"></label></div><button id=\"reset\" type=\"button\" data-i18n=\"reset\"></button><div id=\"graphic\"></div><div id=\"results\" class=\"results\" role=\"status\" aria-live=\"polite\" data-i18n-label=\"result\"></div><p class=\"scope\" data-i18n=\"scope\"></p>","css":"body{padding:20px}h2{font-size:19px;margin:0 0 14px}.controls{display:grid;gap:16px}label{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;font-size:15px}select,input{grid-column:1/-1;width:100%;min-width:0;font:inherit}select{padding:10px;background:var(--paper);color:var(--ink);border:1px solid var(--rule);border-radius:6px;white-space:normal}input{accent-color:var(--accent)}button{min-height:44px;margin:16px 0;font:inherit}.plot{display:block;width:100%;max-width:560px;height:auto;margin:auto}.plot text{fill:var(--ink);font-size:14px}.legend{display:flex;gap:12px;flex-wrap:wrap;margin:8px 0;font-size:14px}.legend i{display:inline-block;width:16px;height:3px;margin-right:5px;vertical-align:middle}.results{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:16px}.metric{border:1px solid var(--rule);padding:10px;border-radius:6px;min-width:0}.metric span{display:block;font-size:14px;min-height:3.5em;overflow-wrap:anywhere}.metric strong{font-size:22px;font-weight:600}.barrow{margin:14px 0;font-size:15px}.barlabel{display:flex;justify-content:space-between;gap:10px}.bar{height:16px;background:var(--surface);margin-top:5px}.bar i{display:block;height:100%;background:var(--accent)}.stack{display:flex;height:35px;margin:15px 0}.stack span{display:flex;align-items:center;justify-content:center;color:var(--paper);font-size:13px}.scope{font-size:14px;color:var(--muted);margin:14px 0 0;line-height:1.65}@media(max-width:380px){body{padding:14px 10px}.results{gap:6px}.metric{padding:8px}.metric strong{font-size:19px}}.accounts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.account{border:1px solid var(--rule);border-radius:8px;padding:12px;min-width:0}.account h3{font-size:16px;margin:0 0 12px}.account dl{margin:0}.account dt{font-size:13px;overflow-wrap:anywhere}.account dd{margin:2px 0 12px;font-variant-numeric:tabular-nums}.account .changed{font-weight:700;color:var(--accent)}.area-legend{font-size:14px;line-height:1.7}.area-legend span{display:block}.area-legend i{display:inline-block;width:12px;height:12px;margin-right:6px}@media(max-width:480px){.accounts{grid-template-columns:1fr}}","js":"const N=25,DEFAULTS={\"rate\": 7};\n/* Pure, deterministic teaching models. Values are synthetic, not estimates. */\nfunction economy(n,p){\n if(n===6){const q=p.remaining,P0=10,P1=12,Q0=100;return{metrics:{oldRevenue:P0*Q0,newRevenue:P1*q,retainedGain:(P1-P0)*q,lostRevenue:P0*(Q0-q),elasticity:Math.abs(((q-Q0)/((q+Q0)/2))/((P1-P0)/((P1+P0)/2)))},revenueAreas:{remaining:q,oldPrice:P0,newPrice:P1,oldQuantity:Q0}};}\n if(n===5){const shift=p.scenario===1?20:0,supply=p.scenario===2?-20:0,P=(100+shift-supply)/20,Q=20+supply+10*P;return{metrics:{price:P,quantity:Q},plot:{xmax:140,ymax:14,x:'quantity',y:'price',lines:[{key:'demand',points:[[0,(120+shift)/10],[120+shift,0]]},{key:'supply',points:[[Math.max(0,20+supply),0],[140,(120-supply)/10]]},{key:'base',points:[[0,5],[140,5]],dash:true}],dot:[Q,P]}};}\n if(n===8){const b=p.response,bs=10,t=p.tax,Pb=5+bs*t/(b+bs),Ps=5-b*t/(b+bs),Q=70-b*bs*t/(b+bs);return{metrics:{buyer:Pb,seller:Ps,quantity:Q,revenue:t*Q,loss:.5*t*(70-Q)},plot:{xmax:100,ymax:20,x:'quantity',y:'price',areas:[{key:'revenue',points:[[0,Ps],[Q,Ps],[Q,Pb],[0,Pb]]},{key:'loss',points:[[Q,Ps],[Q,Pb],[70,5]]}],lines:[{key:'demand',points:[[0,5+70/b],[Math.min(100,70+5*b),Math.max(0,5+(70-100)/b)]]},{key:'supply',points:[[20,0],[100,8]]},{key:'base',points:[[0,5],[100,5]],dash:true},{key:'wedge',points:[[Q,Ps],[Q,Pb]]}],dot:[Q,Pb]}};}\n if(n===18){let index=100+p.weight*p.rise/100;return{metrics:{index,inflation:index-100},bars:[{key:'base',v:100},{key:'new',v:index}],max:180};}\n if(n===19){let E=60,U=10,N=30;if(p.scenario===1){E+=5;U-=5;}if(p.scenario===2){U-=5;N+=5;}if(p.scenario===3){U+=5;N-=5;}return{metrics:{employment:E,unemployment:U,participation:100*(E+U)/100,urate:100*U/(E+U),erate:E},stack:[E,U,N],stackKeys:['employment','unemployment','outside']};}\n if(n===20){const step=p.scenario;let reserves=100,loan=0,deposit=80,equity=20,br=0,bd=0;if(step!==0){loan=60;deposit=140;}if(step===2){reserves-=60;deposit-=60;br=60;bd=60;}if(step===3){loan=40;deposit=120;}const vals={reserves,loan,deposit,equity,bankBreserves:br,bankBdeposits:bd,borrowerDeposit:step===2?0:loan,borrowerGoods:step===2?60:0,borrowerDebt:loan,merchantDeposit:bd,merchantGoods:step===2?0:60};const prev=step>1?economy(20,{scenario:1}).accounts:economy20initial();return{metrics:{reserves,loan,deposit,equity,bankBreserves:br,bankBdeposits:bd,assets:reserves+loan,liabilities:deposit+equity},accounts:vals,ledger:[['bankA',['reserves','loan','deposit','equity']],['bankB',['bankBreserves','bankBdeposits']],['borrower',['borrowerDeposit','borrowerGoods','borrowerDebt']],['merchant',['merchantDeposit','merchantGoods']]].map(([title,keys])=>({title,items:keys.map(key=>({key,value:vals[key],delta:vals[key]-prev[key]}))}))};}\n if(n===22){const c=p.consume,shock=p.shock,rounds=Array.from({length:8},(_,k)=>shock*c**k);return{metrics:{total:shock/(1-c),shown:rounds.reduce((a,b)=>a+b,0),multiplier:1/(1-c)},bars:rounds.map((v,k)=>({label:String(k+1),v})),max:100,rounds};}\n if(n===25){const e=p.rate;return{metrics:{importBill:10*e,exportBill:70/e,debtBill:100*e},bills:true};}\n if(n===26){const A=p.tech,s=p.save/100,d=.1,k=(s*A/d)**2,y=A*Math.sqrt(k),trajectory=[];let current=25;for(let t=0;t<=60;t++){const output=A*Math.sqrt(current),investment=s*output,depreciation=d*current;trajectory.push({t,k:current,y:output,consumption:(1-s)*output,investment,depreciation});current+=investment-depreciation;}return{metrics:{capital:k,output:y,consumption:(1-s)*y},trajectory,plot:{xmax:60,ymax:Math.max(10,...trajectory.map(a=>a.y))*1.1,x:'period',y:'perPersonFlow',lines:[{key:'baselineConsumption',points:[[0,7.5],[60,7.5]],dash:true},{key:'outputPath',points:trajectory.map(a=>[a.t,a.y])},{key:'consumptionPath',points:trajectory.map(a=>[a.t,a.consumption])}]}};}\n throw Error('Unknown lesson');\n}\nfunction economy20initial(){return{reserves:100,loan:0,deposit:80,equity:20,bankBreserves:0,bankBdeposits:0,borrowerDeposit:0,borrowerGoods:0,borrowerDebt:0,merchantDeposit:0,merchantGoods:60};}\nif(typeof module!=='undefined')module.exports={economy};\n\nfunction renderTeachingView(r,el){\n if(r.ledger){\n el.innerHTML='<div class=\"accounts\">'+r.ledger.map(a=>'<section class=\"account\"><h3>'+escape(viz.t(a.title))+'</h3><dl>'+a.items.map(v=>`<dt>${escape(viz.t(v.key))}</dt><dd class=\"${v.delta?'changed':''}\">${viz.number(v.value)} (${v.delta>0?'+':''}${viz.number(v.delta)})</dd>`).join('')+'</dl></section>').join('')+'</div><p class=\"scope\">'+escape(viz.t('delta'))+'</p>';\n $('#results').hidden=true;\n }\n if(r.revenueAreas){const a=r.revenueAreas,x=q=>45+q*2.65,y=p=>213-p*14,q=a.remaining;\n let s=`<svg class=\"plot\" viewBox=\"0 0 360 270\" role=\"img\" aria-label=\"${escape(viz.t('figure'))}\"><path d=\"M45 28V213H322\" fill=\"none\" stroke=\"var(--rule)\"/>`;\n const rect=(x0,x1,p0,p1,c)=>`<rect x=\"${x(x0)}\" y=\"${y(p1)}\" width=\"${(x1-x0)*2.65}\" height=\"${(p1-p0)*14}\" fill=\"${c}\" fill-opacity=\".48\" stroke=\"${c}\"/>`;\n s+=rect(0,q,0,10,'#5277ab')+rect(0,q,10,12,'#247756')+rect(q,100,0,10,'#b56838');\n for(const p of[0,10,12])s+=`<text x=\"37\" y=\"${y(p)+4}\" text-anchor=\"end\">${p}</text>`;\n for(const v of[0,50,100])s+=`<text x=\"${x(v)}\" y=\"235\" text-anchor=\"middle\">${v}</text>`;\n s+=`<text x=\"45\" y=\"20\">${escape(viz.t('price'))}</text><text x=\"310\" y=\"261\" text-anchor=\"end\">${escape(viz.t('quantity'))}</text></svg>`;\n el.innerHTML=s+'<div class=\"area-legend\">'+[['retainedBase','#5277ab'],['retainedGain','#247756'],['lostRevenue','#b56838']].map(([k,c])=>`<span><i style=\"background:${c}\"></i>${escape(viz.t(k))}</span>`).join('')+'</div>';\n }\n}\n\nconst $=s=>document.querySelector(s),col=['var(--accent)','var(--second)','#7581ae','#b36b47'];\nconst escape=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nfunction render(){\n let p={};for(const k of Object.keys(DEFAULTS)){p[k]=Number($('#'+k).value);let o=$('#out-'+k);if(o)o.textContent=viz.number(p[k]);}\n const r=economy(N,p);document.body.dataset.result=JSON.stringify(r.metrics);document.body.dataset.params=JSON.stringify(p);\n $('#results').innerHTML=Object.entries(r.metrics).map(([k,v])=>`<div class=\"metric\"><span>${escape(viz.t(k))}</span><strong data-metric=\"${k}\">${viz.number(v,2)}</strong></div>`).join('');\n const el=$('#graphic');el.replaceChildren();\n if(r.plot){const a=r.plot,x=q=>48+q/a.xmax*278,y=v=>205-v/a.ymax*164;\n let svg=`<svg class=\"plot\" viewBox=\"0 0 360 258\" role=\"img\" aria-label=\"${escape(viz.t('figure'))}\"><path d=\"M48 30V205H333\" fill=\"none\" stroke=\"var(--rule)\"/>`;\n for(const q of [0,a.xmax/2,a.xmax])svg+=`<text x=\"${x(q)}\" y=\"226\" text-anchor=\"middle\">${viz.number(q,1)}</text>`;\n for(const v of [0,a.ymax/2,a.ymax])svg+=`<text x=\"39\" y=\"${y(v)+4}\" text-anchor=\"end\">${viz.number(v,1)}</text>`;\n svg+=`<text x=\"48\" y=\"20\">${escape(viz.t(a.y))}</text><text x=\"326\" y=\"251\" text-anchor=\"end\">${escape(viz.t(a.x))}</text>`;\n (a.areas||[]).forEach((region,j)=>{svg+=`<polygon points=\"${region.points.map(([xx,yy])=>x(xx)+','+y(yy)).join(' ')}\" fill=\"${j===0?'#4c8c9d':'#bd7446'}\" fill-opacity=\".30\"/>`;});\n a.lines.forEach((l,j)=>{svg+=`<polyline fill=\"none\" stroke=\"${col[j]}\" stroke-width=\"${l.key==='wedge'?5:2.5}\" ${l.dash?'stroke-dasharray=\"5 4\"':''} points=\"${l.points.map(([xx,yy])=>x(xx)+','+y(yy)).join(' ')}\"/>`;});\n if(a.dot)svg+=`<circle cx=\"${x(a.dot[0])}\" cy=\"${y(a.dot[1])}\" r=\"5\" fill=\"var(--ink)\"/>`;\n el.innerHTML=svg+'</svg><div class=\"legend\">'+a.lines.map((l,j)=>`<span><i style=\"background:${col[j]}\"></i>${escape(viz.t(l.key))}</span>`).join('')+(a.areas||[]).map((a,j)=>`<span><i style=\"height:10px;background:${j===0?'#4c8c9d':'#bd7446'}\"></i>${escape(viz.t(a.key))}</span>`).join('')+'</div>';\n }else if(r.bars){el.innerHTML=r.bars.map(b=>`<div class=\"barrow\"><div class=\"barlabel\"><span>${escape(b.key?viz.t(b.key):viz.t('round')+' '+b.label)}</span><strong>${viz.number(b.v)}</strong></div><div class=\"bar\"><i style=\"width:${Math.abs(b.v)/Math.max(r.max,...r.bars.map(a=>Math.abs(a.v)))*100}%\"></i></div></div>`).join('')+(N===22?`<p class=\"scope\">${escape(viz.t('negative'))}</p>`:'');\n }else if(r.stack){el.innerHTML='<div class=\"stack\">'+r.stack.map((v,j)=>`<span style=\"width:${v}%;background:${col[j]}\">${v}</span>`).join('')+'</div><div class=\"legend\">'+r.stackKeys.map((k,j)=>`<span><i style=\"background:${col[j]}\"></i>${escape(viz.t(k))}</span>`).join('')+'</div>';}\nrenderTeachingView(r,el);\n}\nfor(const k of Object.keys(DEFAULTS))$('#'+k).addEventListener('input',render);\n$('#reset').addEventListener('click',()=>{for(const[k,v]of Object.entries(DEFAULTS))$('#'+k).value=v;render();});render();\n","audio":false,"strings":{"debtBill":"100 F 债务 / L","exportBill":"70 L 出口品 / F","figure":"当前参数下的模型图;准确值见下方结果。","importBill":"10 F 进口品 / L","rate":"汇率 / L 每 F","reset":"恢复基准","result":"计算结果","scope":"汇率定义为每 F 的 L 数。7 变为 8 时,10 F 进口成本从 70 L 到 80 L;70 L 出口品由 10 F 到 8.75 F;100 F 债务由 700 L 到 800 L。"}}
先在纸上预测三张账单,再改变 e。交互固定各自原币标价和数量,只展示换算,不包含价格重新谈判、套期保值、数量反应或贸易余额。它因此能解释直接敞口,不能直接预测企业最终利润。
为什么贬值不保证出口企业净受益
一家出口企业按 70 L 报价,L 贬值让外国顾客的账单从 10 F 降到 8.75 F,可能增加购买意愿。但若企业每件要进口 5 F 的零件,零件本币成本也从 35 L 到 40 L,利润空间承压。
企业可能调整本币标价,外国客户也可能受长期合同或需求变化影响。若有外币借款,还要承担偿债负担。最终结果需要把数量、产品定价、投入币种和债务一起计算,不能只看出口收入一侧。
整个经济的贸易余额也取决于进出口价格、数量和反应时间。短期合同数量不易改变,本币进口账单先变贵;长期替代与出口订单可能逐步调整。弹性篇的市场范围和期限在这里同样重要。
汇率变化从哪里来,核算又能说明什么
贸易支付、跨境投资、相对利率与风险预期都会影响外汇需求供给,具体汇率制度决定哪些价格和数量可以调整。无法仅凭一笔贸易顺差或一次降息,推出未来汇率必然怎么走。
名义汇率是货币之间的比价;相对商品价格还需要加入两地价格水平,才能讨论实际汇率和竞争力。生产率、质量与服务差异也不会因为货币换算而消失。
GDP 公式中的进口扣除只是在避免把外国产出记作境内产出,不是对进口福利的负面评价。贸易统计、国民收入、企业利润和家庭生活水平各有口径,先说清问题再选账表。
独立完成两次换算
本币每单位外币报价从 8 降到 6,一笔固定 100 F 债务的本币负担怎样变化?本币是升值还是贬值?
展开推理
负担从 800 L 降到 600 L,减少 200 L;买一单位外币需要更少本币,L 升值。只要本金、币种和合同没变,债务的外币金额仍为 100,不能说本金减少了 25 F。
关税案例中,政府收到 10、本地生产者得 9,能否说政策创造了国内净收益 19?如果想加入一个安全收益,应该怎么做?
展开推理
必须同时计入消费者损失 21,原模型净效应为 −2。若另有安全收益,应明确对象、可比较口径、条件和证据,再与资源成本比较;不能只给它一个标签,就自动认为它超过 2。模型外目标可以讨论,但必须明示加入,而不能改写已有账表。
资料与延伸阅读
以下资料用于核对概念与统计口径;本文数字、算例和图形为原创教学设定。
OpenStax · Production Possibilities and Comparative Advantage · OpenStax · The Foreign Exchange Market