# -*- coding: utf-8 -*-

# ------------------------------------------------------------------------------
# # Bayrak yerlilik yanlılığı: gemi sicili tercihinin portföy kuramıyla ölçülmesi ve Türk sahipli ticaret filosunda bayraktan kaçışın ayrıştırılması, 2014–2026
#
# *Flag home bias: measuring ship registry choice with portfolio theory and decomposing flagging out in the Turkish-owned merchant fleet, 2014–2026*
#
# **GOMD Yayınlar · Deniz ekonomisi 03** — https://gomd.pirireis.edu.tr/publications.php?id=me03
#
# Bu not defteri makaledeki **tüm sayıları, tabloları ve şekilleri** üreten kodun Colab sürümüdür. Veri, replikasyon paketinde (11 Kasım 2026 indirmesi) varsa oradan; yoksa özgün sağlayıcıdan (UNCTADstat) indirilir. Bütün sayılar `out/results.json` dosyasına yazılır.
#
# This notebook reproduces **every number, table and figure** of the paper. Data are taken from the replication package (retrieved 11 November 2026) if present; otherwise they are downloaded from the original provider. All numbers are written to `out/results.json`.
#
# *Makale hazırlık aşamasındadır; dergi adı ve tam metin kabulden sonra eklenecektir. / The paper is in preparation; journal name and full text will be added after acceptance.*
# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------
# ## 0. Kurulum / Setup
# ------------------------------------------------------------------------------
# [Colab Magic] !pip install -q pandas numpy statsmodels scipy matplotlib py7zr

# ------------------------------------------------------------------------------
# ## 1. Veri / Data
# Exact reproduction in Colab: upload the replication package (.zip) from the GOMD Publications page, unzip it, then run the cells.
# ------------------------------------------------------------------------------
VERI_KAYNAGI = 'kaynak'   # Colab'da 'zip' secenegi icin not defterine bakin / see the notebook for the 'zip' option in Colab
# Veri / Data. Paketteki veri varsa onu kullanır (11 Kasım 2026 indirmesi, birebir yeniden üretim);
# yoksa özgün kaynaktan indirir (güncel sürüm; sağlayıcı revizyonları nedeniyle sonuçlar küçük farklar gösterebilir).
# Uses the data shipped in the replication package if present (retrieved 11 Nov 2026, exact reproduction);
# otherwise downloads from the original provider (current release; results may differ slightly after provider revisions).
import os, glob, json, urllib.request
import pandas as pd
os.makedirs('data', exist_ok=True); os.makedirs('out', exist_ok=True); os.makedirs('fig', exist_ok=True)
def _unctad(code):
    d = 'data/US_' + code
    if glob.glob(d + '/*.csv'): return
    arc = d + '.7z'
    if not os.path.exists(arc):
        print('UNCTADstat indiriliyor / downloading:', code)
        req = urllib.request.Request('https://unctadstat-api.unctad.org/bulkdownload/US.%s/US_%s' % (code, code), headers={'User-Agent': 'gomd-replication/1.0'})
        with urllib.request.urlopen(req, timeout=300) as r, open(arc, 'wb') as f: f.write(r.read())
    import py7zr
    with py7zr.SevenZipFile(arc) as z: z.extractall(d)
for _c in ['FleetBeneficialOwners', 'MerchantFleet']: _unctad(_c)

# ------------------------------------------------------------------------------
# ## 2. Ayrıştırma, akranlar ve kümeleme / Decomposition, peers and clustering
# ------------------------------------------------------------------------------
# Makale 3: Türk sahipli ticaret filosunda bayrak tercihi (UNCTADstat bayrak x gerçek sahip matrisi, 2014-2026)
import pandas as pd, numpy as np, glob, json, matplotlib
matplotlib.use('Agg'); import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import linkage, fcluster, dendrogram
import statsmodels.api as sm
D='data/'; O='out/'; F='fig/'
bo=pd.read_csv(glob.glob(D+'US_FleetBeneficialOwners/*.csv')[0], low_memory=False, dtype={'FlagOfRegistration':str,'BeneficialOwnership':str})
bo=bo.rename(columns={'FlagOfRegistration Label':'flag','BeneficialOwnership Label':'owner','BeneficialOwnership':'ocode','Dead weight tons in thousands':'dwt','Number of ships':'ships'})[['Year','flag','owner','ocode','dwt','ships']]
bo['owner']=bo.owner.replace({'Turkiye':'Türkiye','Türkiye':'Türkiye'})
bo.loc[bo.owner.str.contains('rkiye'),'owner']='Türkiye'
ind=bo[(bo.ocode.str.len()==3)]           # tekil ekonomiler (3 haneli kod); kümeler 4 haneli
AGG=['Total all flags','National flag','Foreign flag']
tot=ind[ind.flag.isin(AGG)].pivot_table(index=['owner','Year'],columns='flag',values=['dwt','ships']).fillna(0)
tot.columns=['_'.join(c) for c in tot.columns]; tot=tot.reset_index()
tot=tot.rename(columns={'dwt_Total all flags':'T','dwt_National flag':'N','dwt_Foreign flag':'Fg','ships_Total all flags':'sT','ships_National flag':'sN','ships_Foreign flag':'sF'})
tot['r']=tot.N/tot['T']; tot['rs']=tot.sN/tot.sT
Y0,Y1=2014,2026; R={}
tr=tot[tot.owner=='Türkiye'].set_index('Year'); R['tr_series']={int(y):{k:round(float(v),3) for k,v in row.items() if k!='owner'} for y,row in tr.iterrows()}
# 1) LMDI: N = T * r
def lmdi(a,b): return (b-a)/np.log(b/a) if a!=b else a
def decomp(g,y0=Y0,y1=Y1):
    a,b=g.loc[y0],g.loc[y1]; L=lmdi(a.N,b.N); return dict(dN=b.N-a.N, scale=L*np.log(b['T']/a['T']), retention=L*np.log(b.r/a.r))
R['lmdi_tr']={k:round(float(v),1) for k,v in decomp(tr).items()}
R['lmdi_tr_sub']={f'{a}-{b}':{k:round(float(v),1) for k,v in decomp(tr,a,b).items()} for a,b in [(2014,2018),(2018,2022),(2022,2026)]}
R['counterfactual_2026_at_2014_retention']=round(float(tr.loc[Y1,'T']*tr.loc[Y0,'r']),1)
# 2) Akran karşılaştırması: 2026'da en büyük 35 sahip ülke
top=tot[tot.Year==Y1].sort_values('T',ascending=False).head(35).owner.tolist(); R['top35']=top
pan=tot[tot.owner.isin(top)].copy()
w=pan.pivot(index='owner',columns='Year',values='r')
peers=pd.DataFrame({'T2026':pan[pan.Year==Y1].set_index('owner')['T'],'r2014':w[Y0],'r2026':w[Y1]}); peers['dr']=peers.r2026-peers.r2014
peers['rank_T']=peers.T2026.rank(ascending=False).astype(int); peers['rank_r']=peers.r2026.rank(ascending=False).astype(int)
lm=[]
for o,g in pan.groupby('owner'):
    g=g.set_index('Year')
    if g.loc[Y0,'N']>0 and g.loc[Y1,'N']>0: d=decomp(g); lm.append(dict(owner=o,**d))
lm=pd.DataFrame(lm).set_index('owner'); peers=peers.join(lm).sort_values('T2026',ascending=False); peers.round(3).to_csv(O+'peers.csv')
R['tr_peer']={k:(round(float(v),3) if isinstance(v,(float,np.floating)) else int(v)) for k,v in peers.loc['Türkiye'].items()}
R['peer_median_r2026']=round(float(peers.r2026.median()),3); R['peer_median_r2014']=round(float(peers.r2014.median()),3)
R['world_r']={int(y):round(float(v),3) for y,v in bo[(bo.owner=='World')&bo.flag.isin(['National flag','Total all flags'])].pivot(index='Year',columns='flag',values='dwt').pipe(lambda d:d['National flag']/d['Total all flags']).items()}
R['n_decline']=int((peers.dr<0).sum()); R['rank_dr_tr']=int(peers.dr.rank().loc['Türkiye'])
# beta-yakınsama
x=np.log(peers.r2014.clip(lower=1e-3)); yv=(np.log(peers.r2026.clip(lower=1e-3))-x)/(Y1-Y0)
m=sm.OLS(yv,sm.add_constant(x)).fit(cov_type='HC1'); R['beta_conv']=dict(beta=round(float(m.params.iloc[1]),4),se=round(float(m.bse.iloc[1]),4),p=round(float(m.pvalues.iloc[1]),4),r2=round(float(m.rsquared),3),n=int(m.nobs))
# 3) Panel: logit(r) ~ ln T + ln ortalama gemi büyüklüğü + ülke ve yıl sabit etkileri
p=pan[(pan.r>0)&(pan.r<1)].copy(); p['lr']=np.log(p.r/(1-p.r)); p['lT']=np.log(p['T']); p['lsz']=np.log(p['T']/p.sT)
X=pd.get_dummies(p[['owner','Year']].astype(str),drop_first=True).astype(float); X['lT']=p.lT; X['lsz']=p.lsz
m2=sm.OLS(p.lr,sm.add_constant(X)).fit(cov_type='cluster',cov_kwds={'groups':p.owner.astype('category').cat.codes})
R['panel']={v:dict(b=round(float(m2.params[v]),3),se=round(float(m2.bse[v]),3),p=round(float(m2.pvalues[v]),4)) for v in ['lT','lsz']}; R['panel']['n']=int(m2.nobs); R['panel']['r2_within_like']=round(float(m2.rsquared),3)
# 4) Bayrak portföyü: Türkiye
named=[f for f in ind.flag.unique() if f not in AGG]
t=ind[(ind.owner=='Türkiye')&ind.flag.isin(named)].pivot(index='Year',columns='flag',values='dwt').fillna(0)
port=t.copy(); port['Türkiye (ulusal)']=tr.N; port['Diğer yabancı']=(tr.Fg-t.sum(axis=1)).clip(lower=0)
port=port.loc[:,(port.max()>150)|port.columns.isin(['Türkiye (ulusal)','Diğer yabancı'])]; sh=port.div(port.sum(axis=1),axis=0)
port.round(1).to_csv(O+'tr_portfolio_dwt.csv'); R['tr_portfolio_share']={int(y):{c:round(float(v),4) for c,v in row.items()} for y,row in sh.loc[[2014,2018,2022,2026]].iterrows()}
R['tr_hhi']={int(y):round(float((row**2).sum()),4) for y,row in sh.iterrows()}
R['tr_flag_change_dwt_2014_2026']={c:round(float(port.loc[Y1,c]-port.loc[Y0,c]),1) for c in port.columns}
ts=ind[(ind.owner=='Türkiye')&ind.flag.isin(named)].pivot(index='Year',columns='flag',values='ships').fillna(0)
R['tr_avg_size_kdwt']={int(y):dict(national=round(float(tr.loc[y,'N']/tr.loc[y,'sN']),1),foreign=round(float(tr.loc[y,'Fg']/tr.loc[y,'sF']),1)) for y in [2014,2020,2026]}
R['tr_flag_avg_size_2026']={c:round(float(t.loc[Y1,c]/ts.loc[Y1,c]),1) for c in ['Panama','Liberia','Marshall Islands','Malta'] if ts.loc[Y1,c]>0}
# 5) Portföy kümelemesi (CLR + Ward), 2026, ilk 35 sahip
P=[]
for o in top:
    g=ind[(ind.owner==o)&(ind.Year==Y1)].set_index('flag')
    v={f:float(g.dwt.get(f,0) or 0) for f in ['Panama','Liberia','Marshall Islands','Malta','Bahamas','Singapore','China, Hong Kong SAR','Cyprus']}
    if o in v: v[o]=0.0   # kendi bayrağı ulusal sayılır
    nat=float(g.dwt.get('National flag',0)); fg=float(g.dwt.get('Foreign flag',0))
    v['Ulusal']=nat; v['Diğer']=max(fg-sum(v[k] for k in v if k!='Ulusal'),0); P.append(pd.Series(v,name=o))
P=pd.DataFrame(P); S=P.div(P.sum(axis=1),axis=0); Z=np.log(S+0.005); clr=Z.sub(Z.mean(axis=1),axis=0)
lk=linkage(clr.values,'ward'); cl=fcluster(lk,4,'maxclust'); S['cluster']=cl; S.round(4).to_csv(O+'portfolio_clusters.csv')
R['clusters']={int(k):list(S.index[S.cluster==k]) for k in sorted(set(cl))}; R['tr_cluster']=int(S.loc['Türkiye','cluster'])
R['cluster_means']={int(k):{c:round(float(v),3) for c,v in S[S.cluster==k].drop(columns='cluster').mean().items()} for k in sorted(set(cl))}
# 6) Senaryolar (2026 filosu sabit)
T26=float(tr.loc[Y1,'T']); sc={'2014 oranı (Türkiye)':float(tr.loc[Y0,'r']),'Akran medyanı 2026':float(peers.r2026.median()),'Dünya ortalaması 2026':R['world_r'][Y1]}
for o in ['Greece','Italy','Japan','Denmark','Norway']:
    if o in peers.index: sc[o+' 2026']=float(peers.loc[o,'r2026'])
R['scenarios']={k:dict(r=round(v,3),N=round(v*T26,0),extra=round(v*T26-float(tr.loc[Y1,'N']),0)) for k,v in sc.items()}
# 7) Türk bayraklı filo (bayrak esaslı): yaş ve tip
mf=pd.read_csv(glob.glob(D+'US_MerchantFleet/*.csv')[0],low_memory=False).rename(columns={'Economy Label':'eco','ShipType Label':'type','Dead weight tons in thousands':'dwt','Average age of vessels (years)':'age','Number of ships':'ships'})
mf.loc[mf.eco.astype(str).str.contains('rkiye'),'eco']='Türkiye'
a=mf[mf.eco.isin(['Türkiye','World'])&(mf.Year>=2011)]
R['flag_fleet_types']=sorted(a.type.unique().tolist())
tt=a[a.type.str.contains('Total')].pivot(index='Year',columns='eco',values=['dwt','age','ships'])
R['flag_fleet_tr']={int(y):dict(dwt=round(float(tt.loc[y,('dwt','Türkiye')]),0),ships=float(tt.loc[y,('ships','Türkiye')]),age_tr=float(tt.loc[y,('age','Türkiye')]) if pd.notna(tt.loc[y,('age','Türkiye')]) else None,age_world=float(tt.loc[y,('age','World')]) if pd.notna(tt.loc[y,('age','World')]) else None) for y in tt.index if y in (2014,2018,2022,2026)}
ty=a[(a.eco=='Türkiye')&(a.Year.isin([2014,2026]))&~a.type.str.contains('Total')].pivot(index='type',columns='Year',values='dwt'); R['flag_fleet_tr_types']={k:{int(y):round(float(v),0) for y,v in row.items()} for k,row in ty.iterrows()}
json.dump(R,open(O+'results.json','w'),ensure_ascii=False,indent=1)
# ---- şekiller
plt.rcParams.update({'font.size':9,'font.family':'DejaVu Sans'})
fig,ax=plt.subplots(1,2,figsize=(10,3.8))
ax[0].stackplot(tr.index,tr.N/1e3,tr.Fg/1e3,labels=['Türk bayrağı','Yabancı bayrak'],colors=['#c0392b','#95a5a6']); ax[0].set_ylabel('milyon DWT'); ax[0].legend(loc='upper left',frameon=False); ax[0].set_title('(a) Türk sahipli filo')
ax[1].plot(tr.index,tr.r*100,'o-',color='#c0392b',label='Türkiye (DWT)'); ax[1].plot(tr.index,tr.rs*100,'s--',color='#e67e22',label='Türkiye (gemi sayısı)')
ax[1].plot(list(R['world_r']),[v*100 for v in R['world_r'].values()],'k:',label='Dünya (DWT)'); ax[1].set_ylabel('ulusal bayrak payı (%)'); ax[1].legend(frameon=False); ax[1].set_title('(b) Ulusal bayrakta tutma oranı')
plt.tight_layout(); plt.savefig(F+'fig1.png',dpi=200); plt.close()
fig,ax=plt.subplots(figsize=(8,3.8)); cols=[c for c in sh.columns]; ax.stackplot(sh.index,*[sh[c]*100 for c in cols],labels=cols); ax.set_ylabel('Türk sahipli DWT içindeki pay (%)'); ax.legend(ncol=3,fontsize=7,frameon=False,loc='upper center',bbox_to_anchor=(0.5,-0.1)); plt.tight_layout(); plt.savefig(F+'fig2.png',dpi=200); plt.close()
fig,ax=plt.subplots(figsize=(6.5,5.2)); ax.scatter(peers.r2014*100,peers.r2026*100,s=np.sqrt(peers.T2026)/3,alpha=.6,color='#2980b9'); ax.plot([0,100],[0,100],'k--',lw=.7)
for o,rw in peers.iterrows():
    if rw.rank_T<=14 or o=='Türkiye': ax.annotate(o.replace('Republic of Korea','Kore').replace('China, Hong Kong SAR','Hong Kong'),(rw.r2014*100,rw.r2026*100),fontsize=7,color='#c0392b' if o=='Türkiye' else 'k')
ax.set_xlabel('ulusal bayrak payı 2014 (%)'); ax.set_ylabel('ulusal bayrak payı 2026 (%)'); plt.tight_layout(); plt.savefig(F+'fig3.png',dpi=200); plt.close()
q=peers.dropna(subset=['scale']).sort_values('dN'); fig,ax=plt.subplots(figsize=(7,6)); yv=np.arange(len(q)); ax.barh(yv,q.scale/1e3,color='#27ae60',label='Filo ölçeği etkisi'); ax.barh(yv,q.retention/1e3,color='#c0392b',label='Tutma oranı etkisi',left=np.where(np.sign(q.retention)==np.sign(q.scale),q.scale/1e3,0)); ax.plot(q.dN/1e3,yv,'k|',ms=9,label='Net değişim'); ax.set_yticks(yv); ax.set_yticklabels(q.index,fontsize=7); ax.set_xlabel('ulusal bayraklı tonajdaki değişim, 2014–2026 (milyon DWT)'); ax.set_xscale('symlog',linthresh=5); ax.legend(frameon=False,fontsize=8); plt.tight_layout(); plt.savefig(F+'fig4.png',dpi=200); plt.close()
fig,ax=plt.subplots(figsize=(9,4)); dendrogram(lk,labels=[o[:18] for o in clr.index],ax=ax,leaf_font_size=7,color_threshold=sorted(lk[:,2])[-3]); plt.tight_layout(); plt.savefig(F+'fig5.png',dpi=200); plt.close()
print(json.dumps({k:R[k] for k in ['lmdi_tr','lmdi_tr_sub','counterfactual_2026_at_2014_retention','tr_peer','peer_median_r2026','peer_median_r2014','world_r','n_decline','rank_dr_tr','beta_conv','panel','tr_portfolio_share','tr_hhi','tr_flag_change_dwt_2014_2026','tr_avg_size_kdwt','tr_flag_avg_size_2026','clusters','tr_cluster','cluster_means','scenarios','flag_fleet_tr','flag_fleet_tr_types']},ensure_ascii=False,indent=0)[:6500])

# ------------------------------------------------------------------------------
# ## 3. Yerlilik yanlılığı, pay kayması, akım matrisi, çekicilik / Home bias, shift-share, flow matrix, attractiveness
# ------------------------------------------------------------------------------
# Makale 3 - yenilik katmanı: (i) bayrak yerlilik yanlılığı endeksi, (ii) küresel eğilim / ülkeye özgü kayma (shift-share),
# (iii) en büyük entropili net bayrak geçiş matrisi, (iv) iki yönlü sabit etkili bayrak çekicilik endeksi.
import pandas as pd, numpy as np, glob, json, matplotlib
matplotlib.use('Agg'); import matplotlib.pyplot as plt
import statsmodels.api as sm
D='data/'; O='out/'; F='fig/'
bo=pd.read_csv(glob.glob(D+'US_FleetBeneficialOwners/*.csv')[0], low_memory=False, dtype={'FlagOfRegistration':str,'BeneficialOwnership':str})
bo=bo.rename(columns={'FlagOfRegistration Label':'flag','BeneficialOwnership Label':'owner','BeneficialOwnership':'ocode','Dead weight tons in thousands':'dwt','Number of ships':'ships'})[['Year','flag','owner','ocode','dwt','ships']]
bo.loc[bo.owner.str.contains('rkiye'),'owner']='Türkiye'; bo['dwt']=bo.dwt.fillna(0)
ind=bo[bo.ocode.str.len()==3]; AGG=['Total all flags','National flag','Foreign flag']
W=bo[bo.owner=='World']; named=[f for f in ind.flag.unique() if f not in AGG]
R=json.load(open(O+'results.json')); top=R['top35']; Y0,Y1=2014,2026; N={}
mf=pd.read_csv(glob.glob(D+'US_MerchantFleet/*.csv')[0],low_memory=False).rename(columns={'Economy Label':'eco','ShipType Label':'type','Dead weight tons in thousands':'dwt'})
mf.loc[mf.eco.astype(str).str.contains('rkiye'),'eco']='Türkiye'
ft=mf[mf.type.str.contains('Total')].pivot_table(index='eco',columns='Year',values='dwt')   # bayrak esaslı toplam filo
wt=ft.loc['World']
tot=ind[ind.flag.isin(AGG)].pivot_table(index=['owner','Year'],columns='flag',values='dwt').fillna(0).reset_index().rename(columns={'Total all flags':'T','National flag':'Nn','Foreign flag':'Fg'})
# (i) Yerlilik yanlılığı: HB = 1 - (gerçekleşen yabancı bayrak payı / kıyas payı); kıyas = dünya filosunda yabancı bayrakların payı = 1 - (ülke bayrağının dünya payı)
hb=[]
for o in top:
    if o not in ft.index: continue
    for y in range(Y0,Y1+1):
        g=tot[(tot.owner==o)&(tot.Year==y)]
        if g.empty or g['T'].iloc[0]<=0 or pd.isna(ft.loc[o].get(y)): continue
        fshare=g.Fg.iloc[0]/g['T'].iloc[0]; bench=1-ft.loc[o,y]/wt[y]
        hb.append(dict(owner=o,Year=y,HB=1-fshare/bench,flag_world_share=ft.loc[o,y]/wt[y],r=1-fshare))
hb=pd.DataFrame(hb); hbw=hb.pivot(index='owner',columns='Year',values='HB'); hbw.round(4).to_csv(O+'home_bias.csv')
N['hb_tr']={int(y):round(float(v),4) for y,v in hbw.loc['Türkiye'].items()}
N['hb_median']={int(y):round(float(hbw[y].median()),4) for y in (Y0,2018,2022,Y1)}
N['hb_rank_tr']={int(y):int(hbw[y].rank(ascending=False).loc['Türkiye']) for y in (Y0,Y1)}; N['hb_n']=int(hbw[Y1].notna().sum())
N['hb_change']={o:round(float(hbw.loc[o,Y1]-hbw.loc[o,Y0]),3) for o in hbw.index}
N['hb_2026']={o:round(float(hbw.loc[o,Y1]),3) for o in hbw.index}; N['hb_2014']={o:round(float(hbw.loc[o,Y0]),3) for o in hbw.index}
N['tr_flag_world_share']={int(y):round(float(ft.loc['Türkiye',y]/wt[y]*100),3) for y in (Y0,Y1)}
# (ii) Shift-share: Türk sahipli tonajın bayraklara dağılımı; küresel (Türkiye dışı) eğilimi izleseydi?
cats=['Panama','Liberia','Marshall Islands','Malta','Bahamas','Singapore','China, Hong Kong SAR','Cyprus']
def portfolio(owner_mask,y):
    g=ind[owner_mask&(ind.Year==y)]
    v={c:g[g.flag==c].dwt.sum() for c in cats}; nat=g[g.flag=='National flag'].dwt.sum(); fg=g[g.flag=='Foreign flag'].dwt.sum()
    # ulusal bayrağı adlandırılmış listede olan ülkelerde çifte sayımı önle
    own=g[(g.flag==g.owner)&g.flag.isin(cats)].groupby('flag').dwt.sum()
    for c,val in own.items(): v[c]-=val
    v['Ulusal']=nat; v['Diğer']=fg-sum(v[c] for c in cats); return pd.Series(v)
tr0,tr1=portfolio(ind.owner=='Türkiye',Y0),portfolio(ind.owner=='Türkiye',Y1)
rw0,rw1=portfolio(ind.owner!='Türkiye',Y0),portfolio(ind.owner!='Türkiye',Y1)
g_all=rw1.sum()/rw0.sum(); g_flag=rw1/rw0
ss=pd.DataFrame({'tr2014':tr0,'tr2026':tr1,'world_growth':g_flag})
ss['ulusal_buyume']=tr0*(tr1.sum()/tr0.sum()-1)                    # Türk sahipli filonun kendi büyümesi (pay sabit)
ss['kuresel_bilesim']=tr0*(g_flag/g_all-1)*(tr1.sum()/tr0.sum())     # küresel bayrak eğilimi
ss['ulkeye_ozgu']=tr1-tr0-ss.ulusal_buyume-ss.kuresel_bilesim
ss.round(1).to_csv(O+'shift_share.csv'); N['shift_share']={k:{c:round(float(v),1) for c,v in row.items()} for k,row in ss.iterrows()}
N['rw_share']={str(y):{c:round(float(v),4) for c,v in (p/p.sum()).items()} for y,p in ((Y0,rw0),(Y1,rw1))}
# (iii) En büyük entropili net geçiş matrisi (pay bazında): çıkış_i x giriş_j / toplam
def flows(a,b):
    sa,sb=a/a.sum(),b/b.sum(); d=sb-sa; out=(-d).clip(lower=0); inn=d.clip(lower=0); tot_=out.sum()
    M=pd.DataFrame(np.outer(out,inn)/tot_ if tot_>0 else 0,index=a.index,columns=a.index); return M,tot_
Mx,tv=flows(tr0,tr1); Mx=Mx.loc[Mx.sum(axis=1)>0,Mx.sum(axis=0)>0]; (Mx*100).round(2).to_csv(O+'flag_flows_pp.csv')
N['flows_pp']={i:{j:round(float(Mx.loc[i,j]*100),2) for j in Mx.columns} for i in Mx.index}; N['turnover_pp']=round(float(tv*100),1)
turn=[]
for o in top:
    try:
        a,b=portfolio(ind.owner==o,Y0),portfolio(ind.owner==o,Y1)
        if a.sum()>0 and b.sum()>0 and (a>=-1).all() and (b>=-1).all(): turn.append((o,float(flows(a.clip(lower=0),b.clip(lower=0))[1]*100)))
    except Exception: pass
turn=pd.Series(dict(turn)).sort_values(ascending=False); N['turnover_all']={k:round(v,1) for k,v in turn.items()}; N['turnover_rank_tr']=int(turn.rank(ascending=False).loc['Türkiye']); N['turnover_median']=round(float(turn.median()),1)
# yıllık devir
N['turnover_annual_tr']={int(y):round(float(flows(portfolio(ind.owner=='Türkiye',y-1),portfolio(ind.owner=='Türkiye',y))[1]*100),2) for y in range(Y0+1,Y1+1)}
# (iv) Bayrak çekicilik endeksi: ln(s_ojt / s_o,diğer,t) = delta_jt + mu_oj + e  (yalnızca yabancı siciller; sahip x bayrak sabit etkisi)
rowsx=[]
for o in top:
    for y in range(Y0,Y1+1):
        p=portfolio(ind.owner==o,y).clip(lower=0); base=p['Diğer']
        if base<=0: continue
        for c in cats:
            if c==o or p[c]<=0: continue
            rowsx.append(dict(owner=o,Year=y,flag=c,lr=np.log(p[c]/base)))
dx=pd.DataFrame(rowsx); dx['oj']=dx.owner+'|'+dx.flag; dx['jt']=dx.flag+'|'+dx.Year.astype(str)
X=pd.get_dummies(dx[['oj','jt']],drop_first=False).astype(float)
dropc=['jt_%s|%d'%(c,Y0) for c in cats]; X=X.drop(columns=[c for c in dropc if c in X.columns])
m=sm.OLS(dx.lr,X).fit()
att=pd.DataFrame({c:[m.params.get('jt_%s|%d'%(c,y),0.0) for y in range(Y0,Y1+1)] for c in cats},index=range(Y0,Y1+1)); att.round(3).to_csv(O+'flag_attractiveness.csv')
N['attract_2026']={c:round(float(att.loc[Y1,c]),3) for c in cats}; N['attract_n']=int(m.nobs); N['attract_r2']=round(float(m.rsquared),3)
# Türkiye'nin sapması: Türkiye artıkları
dx['res']=m.resid; N['tr_resid_2026']={r.flag:round(float(r.res),3) for r in dx[(dx.owner=='Türkiye')&(dx.Year==Y1)].itertuples()}
N['tr_logratio_change']={c:round(float(dx[(dx.owner=='Türkiye')&(dx.flag==c)&(dx.Year==Y1)].lr.iloc[0]-dx[(dx.owner=='Türkiye')&(dx.flag==c)&(dx.Year==Y0)].lr.iloc[0]),3) for c in cats if len(dx[(dx.owner=='Türkiye')&(dx.flag==c)&(dx.Year.isin([Y0,Y1]))])==2}
json.dump(N,open(O+'novel.json','w'),ensure_ascii=False,indent=1)
# şekiller
plt.rcParams.update({'font.size':9})
fig,ax=plt.subplots(1,2,figsize=(10,3.8))
for o,c,lab in [('Türkiye','#c0392b','Türkiye'),('Greece','#2980b9','Yunanistan'),('Denmark','#27ae60','Danimarka'),('Japan','#8e44ad','Japonya'),('Norway','#e67e22','Norveç'),('Italy','#7f8c8d','İtalya')]:
    if o in hbw.index: ax[0].plot(hbw.columns,hbw.loc[o],'o-' if o=='Türkiye' else '-',color=c,label=lab,lw=2 if o=='Türkiye' else 1.2)
ax[0].plot(hbw.columns,hbw.median(),'k--',label='Medyan (35 ülke)'); ax[0].set_ylabel('bayrak yerlilik yanlılığı endeksi'); ax[0].legend(frameon=False,fontsize=7,ncol=2); ax[0].set_title('(a) Yerlilik yanlılığı')
for c in ['Panama','Liberia','Marshall Islands','Malta','Singapore','Bahamas']: ax[1].plot(att.index,att[c],label={'Liberia':'Liberya','Marshall Islands':'Marshall Adaları','Singapore':'Singapur','Bahamas':'Bahamalar'}.get(c,c))
ax[1].axhline(0,color='k',lw=.5); ax[1].set_ylabel('çekicilik endeksi (2014 = 0, log puan)'); ax[1].legend(frameon=False,fontsize=7,ncol=2); ax[1].set_title('(b) Küresel sicil çekiciliği')
plt.tight_layout(); plt.savefig(F+'fig6.png',dpi=200); plt.close()
lab={'Ulusal':'Türk bayrağı','Diğer':'Diğer yabancı','Marshall Islands':'Marshall Ad.','Liberia':'Liberya','Singapore':'Singapur','China, Hong Kong SAR':'Hong Kong','Bahamas':'Bahamalar'}
fig,ax=plt.subplots(figsize=(6.2,3.6)); im=ax.imshow(Mx.values*100,cmap='Reds'); ax.set_xticks(range(len(Mx.columns))); ax.set_xticklabels([lab.get(c,c) for c in Mx.columns],rotation=35,ha='right'); ax.set_yticks(range(len(Mx.index))); ax.set_yticklabels([lab.get(c,c) for c in Mx.index])
for i in range(Mx.shape[0]):
    for j in range(Mx.shape[1]): ax.text(j,i,('%.1f'%(Mx.values[i,j]*100)).replace('.',','),ha='center',va='center',fontsize=8)
ax.set_xlabel('pay kazanan sicil'); ax.set_ylabel('pay kaybeden sicil'); plt.colorbar(im,label='yüzde puan'); plt.tight_layout(); plt.savefig(F+'fig7.png',dpi=200); plt.close()
s2=ss.rename(index=lab); fig,ax=plt.subplots(figsize=(7.5,3.8)); x=np.arange(len(s2)); ax.bar(x-.27,s2.ulusal_buyume/1e3,.27,label='Filo büyümesi',color='#27ae60'); ax.bar(x,s2.kuresel_bilesim/1e3,.27,label='Küresel sicil eğilimi',color='#2980b9'); ax.bar(x+.27,s2.ulkeye_ozgu/1e3,.27,label='Türkiye\'ye özgü kayma',color='#c0392b'); ax.set_xticks(x); ax.set_xticklabels(s2.index,rotation=35,ha='right'); ax.axhline(0,color='k',lw=.5); ax.set_ylabel('milyon DWT'); ax.legend(frameon=False); plt.tight_layout(); plt.savefig(F+'fig8.png',dpi=200); plt.close()
print(json.dumps(N,ensure_ascii=False)[:5200])

# ------------------------------------------------------------------------------
# ## Şekiller / Figures
# ------------------------------------------------------------------------------
print('Sekiller / figures:', sorted(glob.glob('fig/*.png')))
