math file
This commit is contained in:
parent
54d673b14e
commit
3fe4fb5c82
59
src/App.tsx
59
src/App.tsx
|
|
@ -17,6 +17,12 @@ import PriceSimulationChart from "./PriceSimulationChart";
|
||||||
import HelpText from "./HelpText";
|
import HelpText from "./HelpText";
|
||||||
// Utils
|
// Utils
|
||||||
import { getLast, getAvg, pause } from "./utils";
|
import { getLast, getAvg, pause } from "./utils";
|
||||||
|
import {
|
||||||
|
getInitialParams,
|
||||||
|
getPriceR,
|
||||||
|
getRandomDeltas,
|
||||||
|
getSlippage
|
||||||
|
} from "./math";
|
||||||
import { throttle } from "lodash";
|
import { throttle } from "lodash";
|
||||||
// General styles
|
// General styles
|
||||||
import "./app.css";
|
import "./app.css";
|
||||||
|
|
@ -84,7 +90,7 @@ export default function App() {
|
||||||
const [curveParams, setCurveParams] = useState({
|
const [curveParams, setCurveParams] = useState({
|
||||||
d0: 1e6, // Initial raise, d0 (DAI)
|
d0: 1e6, // Initial raise, d0 (DAI)
|
||||||
theta: 0.35, // fraction allocated to reserve (.)
|
theta: 0.35, // fraction allocated to reserve (.)
|
||||||
p0: 0.1, // Hatch sale Price p0 (DAI / token)
|
p0: 0.1, // Hatch sale price p0 (DAI / token)
|
||||||
returnF: 3, // Return factor (.)
|
returnF: 3, // Return factor (.)
|
||||||
wFee: 0.05 // friction coefficient (.)
|
wFee: 0.05 // friction coefficient (.)
|
||||||
});
|
});
|
||||||
|
|
@ -101,10 +107,17 @@ export default function App() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Simulation results
|
// Simulation results
|
||||||
const k = returnF / (1 - theta); // Invariant power kappa (.)
|
const {
|
||||||
const R0 = (1 - theta / 100) * d0; // Initial reserve (DAI)
|
k, // Invariant power kappa (.)
|
||||||
const S0 = d0 / p0; // initial supply of tokens (token)
|
R0, // Initial reserve (DAI)
|
||||||
const V0 = S0 ** k / R0; // invariant coef
|
S0, // initial supply of tokens (token)
|
||||||
|
V0 // invariant coef
|
||||||
|
} = getInitialParams({
|
||||||
|
d0,
|
||||||
|
theta,
|
||||||
|
p0,
|
||||||
|
returnF
|
||||||
|
});
|
||||||
|
|
||||||
const [priceTimeseries, setPriceTimeseries] = useState([0]);
|
const [priceTimeseries, setPriceTimeseries] = useState([0]);
|
||||||
const [withdrawFeeTimeseries, setWithdrawFeeTimeseries] = useState([0]);
|
const [withdrawFeeTimeseries, setWithdrawFeeTimeseries] = useState([0]);
|
||||||
|
|
@ -141,8 +154,7 @@ export default function App() {
|
||||||
let canContinueSimulation = true;
|
let canContinueSimulation = true;
|
||||||
async function simulateRandomDelta() {
|
async function simulateRandomDelta() {
|
||||||
const R_t: number[] = [R0];
|
const R_t: number[] = [R0];
|
||||||
const S_t: number[] = [S0];
|
const p_t: number[] = [getPriceR({ R: R0, V0, k })];
|
||||||
const p_t: number[] = [R0 / S0];
|
|
||||||
const wFee_t: number[] = [0];
|
const wFee_t: number[] = [0];
|
||||||
const slippage_t: number[] = [];
|
const slippage_t: number[] = [];
|
||||||
|
|
||||||
|
|
@ -151,37 +163,20 @@ export default function App() {
|
||||||
const updateEveryNth = 1;
|
const updateEveryNth = 1;
|
||||||
|
|
||||||
// Compute the random deltas
|
// Compute the random deltas
|
||||||
const deltaR_t: number[] = [];
|
const deltaR_t = getRandomDeltas({ numSteps, avgTxSize });
|
||||||
for (let i = 0; i < numSteps; i++) {
|
|
||||||
const rand = 1 - 2 * Math.random();
|
|
||||||
const sin = Math.sin((1 / 20) * (i / numSteps));
|
|
||||||
const ascending = Math.sin((Math.PI / 1) * (i / numSteps));
|
|
||||||
const deltaR = 1e5 * rand + 1e5 * sin + 2e4 * ascending;
|
|
||||||
deltaR_t.push(deltaR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize random deltas with the average transaction size
|
|
||||||
const deltaR_avg = getAvg(deltaR_t);
|
|
||||||
const deltaR_t_normalized = deltaR_t.map(
|
|
||||||
(deltaR: number) => (avgTxSize * deltaR) / deltaR_avg
|
|
||||||
);
|
|
||||||
|
|
||||||
setSimulationRunning(true);
|
setSimulationRunning(true);
|
||||||
for (let i = 0; i < numSteps; i++) {
|
for (let i = 0; i < numSteps; i++) {
|
||||||
const deltaR = deltaR_t_normalized[i];
|
const deltaR = deltaR_t[i];
|
||||||
|
|
||||||
// Protect against too strong negative deltas
|
|
||||||
const R = getLast(R_t);
|
const R = getLast(R_t);
|
||||||
const S = getLast(S_t);
|
|
||||||
const p = getLast(p_t);
|
|
||||||
|
|
||||||
const R_next = R + deltaR;
|
const R_next = R + deltaR;
|
||||||
const deltaS = (V0 * (R + deltaR)) ** (1 / k) - S;
|
|
||||||
const S_next = S + deltaS;
|
|
||||||
|
|
||||||
R_t.push(R_next);
|
R_t.push(R_next);
|
||||||
S_t.push(S_next);
|
p_t.push(getPriceR({ R: R_next, V0, k }));
|
||||||
p_t.push(R_next / S_next);
|
slippage_t.push(getSlippage({ R, deltaR, V0, k }));
|
||||||
|
|
||||||
// Consider withdraw fees on sales only
|
// Consider withdraw fees on sales only
|
||||||
if (deltaR < 0) {
|
if (deltaR < 0) {
|
||||||
wFee_t.push(getLast(wFee_t) - deltaR * wFee);
|
wFee_t.push(getLast(wFee_t) - deltaR * wFee);
|
||||||
|
|
@ -190,12 +185,6 @@ export default function App() {
|
||||||
wFee_t.push(getLast(wFee_t));
|
wFee_t.push(getLast(wFee_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
const p_next = getLast(p_t);
|
|
||||||
// const realizedPrice = deltaR / deltaS;
|
|
||||||
const spotPrice = p;
|
|
||||||
const slippage = Math.abs(p_next - spotPrice) / spotPrice / 2;
|
|
||||||
slippage_t.push(slippage);
|
|
||||||
|
|
||||||
// Stop the simulation if it's no longer active
|
// Stop the simulation if it's no longer active
|
||||||
if (!simulationActive || !canContinueSimulation) break;
|
if (!simulationActive || !canContinueSimulation) break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#root {
|
#root {
|
||||||
background-color: #152128;
|
background-color: #152128;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
import { getAvg } from "./utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the initial params given the "user friendly" params:
|
||||||
|
* - Initial raise, `d0` (DAI)
|
||||||
|
* - fraction allocated to reserve, `theta`
|
||||||
|
* - Hatch sale price, `p0` (DAI / token)
|
||||||
|
* - Return factor, `returnF`
|
||||||
|
*/
|
||||||
|
export function getInitialParams({
|
||||||
|
d0,
|
||||||
|
theta,
|
||||||
|
p0,
|
||||||
|
returnF
|
||||||
|
}: {
|
||||||
|
d0: number;
|
||||||
|
theta: number;
|
||||||
|
p0: number;
|
||||||
|
returnF: number;
|
||||||
|
}) {
|
||||||
|
const k = returnF / (1 - theta); // Invariant power kappa (.)
|
||||||
|
const R0 = (1 - theta) * d0; // Initial reserve (DAI)
|
||||||
|
const S0 = d0 / p0; // initial supply of tokens (token)
|
||||||
|
const V0 = S0 ** k / R0; // invariant coef
|
||||||
|
return { k, R0, S0, V0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the price at a specific reserve `R`
|
||||||
|
*/
|
||||||
|
export function getPriceR({ R, V0, k }: { R: number; V0: number; k: number }) {
|
||||||
|
return (k * R ** ((k - 1) / k)) / V0 ** (1 / k);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute slippage at a point `R`, given a `deltaR`
|
||||||
|
*/
|
||||||
|
export function getSlippage({
|
||||||
|
R,
|
||||||
|
deltaR,
|
||||||
|
V0,
|
||||||
|
k
|
||||||
|
}: {
|
||||||
|
R: number;
|
||||||
|
deltaR: number;
|
||||||
|
V0: number;
|
||||||
|
k: number;
|
||||||
|
}) {
|
||||||
|
const S = (V0 * R) ** (1 / k);
|
||||||
|
const deltaS = (V0 * (R + deltaR)) ** (1 / k) - S;
|
||||||
|
const realizedPrice = deltaR / deltaS;
|
||||||
|
const spotPrice = getPriceR({ R, V0, k });
|
||||||
|
return Math.abs(realizedPrice - spotPrice) / spotPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random delta given three components:
|
||||||
|
* 1. Climbing sin
|
||||||
|
* 2. Oscilating sin
|
||||||
|
* 3. Random component
|
||||||
|
*/
|
||||||
|
export function getRandomDeltas({
|
||||||
|
numSteps,
|
||||||
|
avgTxSize
|
||||||
|
}: {
|
||||||
|
numSteps: number;
|
||||||
|
avgTxSize: number;
|
||||||
|
}) {
|
||||||
|
const deltaR_t: number[] = [];
|
||||||
|
for (let i = 0; i < numSteps; i++) {
|
||||||
|
const rand = 1 - 2 * Math.random();
|
||||||
|
const sin = Math.sin((1 / 20) * (i / numSteps));
|
||||||
|
const ascending = Math.sin((Math.PI / 1) * (i / numSteps));
|
||||||
|
const deltaR = 1e5 * rand + 1e5 * sin + 2e4 * ascending;
|
||||||
|
deltaR_t.push(deltaR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize random deltas with the average transaction size
|
||||||
|
const deltaR_avg = getAvg(deltaR_t);
|
||||||
|
return deltaR_t.map((deltaR: number) => (avgTxSize * deltaR) / deltaR_avg);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue