70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import { SECTOR, ASSET_TYPE, REGIME } from '../config/constants';
|
|
import type { MarketContext, AssetType, InflatedOverrides } from '../types';
|
|
|
|
export class MarketRegime {
|
|
private marketPE: number;
|
|
private techPE: number;
|
|
private reitYield: number;
|
|
private igSpread: number;
|
|
private rateRegime: string;
|
|
private volatilityRegime: string;
|
|
|
|
constructor(marketContext: Partial<MarketContext>) {
|
|
const b = marketContext?.benchmarks ?? ({} as MarketContext['benchmarks']);
|
|
this.marketPE = b.marketPE ?? 22;
|
|
this.techPE = b.techPE ?? 30;
|
|
this.reitYield = b.reitYield ?? 3.5;
|
|
this.igSpread = b.igSpread ?? 1.0;
|
|
this.rateRegime = marketContext?.rateRegime ?? REGIME.NORMAL;
|
|
this.volatilityRegime = marketContext?.volatilityRegime ?? REGIME.NORMAL;
|
|
}
|
|
|
|
getInflatedOverrides(type: AssetType, sector?: string): InflatedOverrides {
|
|
if (type === ASSET_TYPE.STOCK) return this._stock(sector);
|
|
if (type === ASSET_TYPE.ETF) return this._etf();
|
|
if (type === ASSET_TYPE.BOND) return this._bond();
|
|
return { gates: {}, thresholds: {} };
|
|
}
|
|
|
|
private _stock(sector?: string): InflatedOverrides {
|
|
if (sector === SECTOR.REIT) {
|
|
return {
|
|
gates: {},
|
|
thresholds: {
|
|
minYield: +(this.reitYield * (this.rateRegime === REGIME.HIGH ? 0.95 : 0.85)).toFixed(2),
|
|
maxPFFO: 20,
|
|
},
|
|
};
|
|
}
|
|
if (sector === SECTOR.TECHNOLOGY) {
|
|
return {
|
|
gates: {
|
|
maxPERatio: Math.round(this.techPE * 1.3),
|
|
maxPegGate: +(this.techPE / 15).toFixed(1),
|
|
},
|
|
thresholds: {},
|
|
};
|
|
}
|
|
const peMultiplier = this.rateRegime === REGIME.HIGH ? 1.2 : 1.5;
|
|
return {
|
|
gates: {
|
|
maxPERatio: Math.round(this.marketPE * peMultiplier),
|
|
maxPegGate: +(this.marketPE / 12).toFixed(1),
|
|
},
|
|
thresholds: {},
|
|
};
|
|
}
|
|
|
|
private _etf(): InflatedOverrides {
|
|
return { gates: { maxExpenseRatio: 0.75 }, thresholds: { minYield: 0.5 } };
|
|
}
|
|
|
|
private _bond(): InflatedOverrides {
|
|
const spreadMultiplier = this.rateRegime === REGIME.HIGH ? 0.9 : 0.8;
|
|
return {
|
|
gates: {},
|
|
thresholds: { minSpread: +(this.igSpread * spreadMultiplier).toFixed(2) },
|
|
};
|
|
}
|
|
}
|