Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made price calculations for options consistent. #173

Open
wants to merge 11 commits into
base: Siren-Exchange-Auto-Series
Choose a base branch
from
6 changes: 3 additions & 3 deletions contracts/amm/AmmDataProvider.sol
Original file line number Diff line number Diff line change
Expand Up @@ -413,17 +413,17 @@ contract AmmDataProvider is IAmmDataProvider {
// behavior for any functions which call getPriceForSeriesInternal
(uint256 call, uint256 put) = IBlackScholes(
addressesProvider.getBlackScholes()
).optionPrices(
).optionPricesInUnderlying(
series.expirationDate - block.timestamp,
annualVolatility,
underlyingPrice,
series.strikePrice,
0
);
if (series.isPutOption == true) {
return ((put * 1e18) / underlyingPrice);
return (put);
} else {
return ((call * 1e18) / underlyingPrice);
return (call);
}
}

Expand Down
42 changes: 42 additions & 0 deletions contracts/amm/BlackScholes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,48 @@ contract BlackScholes is IBlackScholes {
return (call.preciseDecimalToDecimal(), put.preciseDecimalToDecimal());
}

/**
* @dev Returns call and put prices for options with given parameters.
* @param timeToExpirySec Number of seconds to the expiry of the option
* @param volatilityDecimal Implied volatility over the period til expiry as a percentage( we calculate our volatilty and it is returned with 8
* decimals so we need to update it to be the correct format for blackscholes
* @param spotDecimal The current price of the base asset
* @param strikeDecimal The strike price of the option
* @param rateDecimal The percentage risk free rate + carry cost
*/
function optionPricesInUnderlying(
uint256 timeToExpirySec,
uint256 volatilityDecimal,
uint256 spotDecimal,
uint256 strikeDecimal,
int256 rateDecimal
) external view override returns (uint256 call, uint256 put) {
uint256 tAnnualised = annualise(timeToExpirySec);
uint256 spotPrecise = spotDecimal.decimalToPreciseDecimal();
uint256 strikePrecise = strikeDecimal.decimalToPreciseDecimal();
int256 ratePrecise = rateDecimal.decimalToPreciseDecimal();
(int256 d1, int256 d2) = d1d2(
tAnnualised,
volatilityDecimal.decimalToPreciseDecimal(),
spotPrecise,
strikePrecise,
ratePrecise
);

(call, put) = _optionPrices(
tAnnualised,
spotPrecise,
strikePrecise,
ratePrecise,
d1,
d2
);
call = call.divideDecimalRoundPrecise(spotPrecise);
put = put.divideDecimalRoundPrecise(spotPrecise);

return (call.preciseDecimalToDecimal(), put.preciseDecimalToDecimal());
}

/*.000246212471428571
* Greeks
*/
Expand Down
8 changes: 8 additions & 0 deletions contracts/amm/IBlackScholes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ interface IBlackScholes {
int256 rateDecimal
) external view returns (uint256 call, uint256 put);

function optionPricesInUnderlying(
uint256 timeToExpirySec,
uint256 volatilityDecimal,
uint256 spotDecimal,
uint256 strikeDecimal,
int256 rateDecimal
) external view returns (uint256 call, uint256 put);

function pricesDeltaStdVega(
uint256 timeToExpirySec,
uint256 volatilityDecimal,
Expand Down
14 changes: 14 additions & 0 deletions scripts/deploy_addresses_provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { deployAddressesProvider } from "./lib/deploy_addresses_provider"

async function main() {
await deployAddressesProvider()
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error)
process.exit(1)
})
16 changes: 16 additions & 0 deletions scripts/deploy_siren_exchange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { deploySirenExchange } from "./lib/deploy_siren_exchange"

const ADDRESSES_PROVIDER = process.env.ADDRESSES_PROVIDER

async function main() {
await deploySirenExchange(ADDRESSES_PROVIDER)
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error)
process.exit(1)
})
33 changes: 33 additions & 0 deletions scripts/lib/deploy_addresses_provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as hre from "hardhat"
const { request, gql } = require("graphql-request")

const V2_SUBGRAPH_URL = process.env.V2_SUBGRAPH_URL
const DAY_DURATION = 24 * 60 * 60
const WINDOW_SIZE = 90
const WEEK_DURATION = 7 * DAY_DURATION

export async function deployAddressesProvider() {
const AddressesProvider = await hre.ethers.getContractFactory(
"AddressesProvider",
)
// now deploy all the contracts. Later we will initialize them in the correct order
const addressesProviderLogic = await AddressesProvider.deploy()
await addressesProviderLogic.deployed()
// const addressesProviderProxy = await Proxy.deploy(
// addressesProviderLogic.address,
// )
// await addressesProviderProxy.deployed()
console.log(
"Logic AddressesProviderLogic deployed to: ",
addressesProviderLogic.address.toLowerCase(),
)
// const addressesProvider = AddressesProvider.attach(
// addressesProviderProxy.address,
// )
// console.log(
// "AddressesProvider deployed to: ",
// addressesProvider.address.toLowerCase(),
// )
100000000
return {}
}
23 changes: 23 additions & 0 deletions scripts/lib/deploy_siren_exchange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as hre from "hardhat"
const { request, gql } = require("graphql-request")

const V2_SUBGRAPH_URL = process.env.V2_SUBGRAPH_URL
const DAY_DURATION = 24 * 60 * 60
const WINDOW_SIZE = 90
const WEEK_DURATION = 7 * DAY_DURATION

export async function deploySirenExchange(addressesProvider: string) {
const SirenExchangeFactory = await hre.ethers.getContractFactory(
"SirenExchange",
)

const sirenExchange = await SirenExchangeFactory.deploy(addressesProvider)

await sirenExchange.deployed()
console.log(
"SirenExchange deployed to: ",
sirenExchange.address.toLowerCase(),
)

return {}
}
46 changes: 46 additions & 0 deletions subgraph/generated/PriceOracle/PriceOracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ export class SetSettlementPriceForDateCall__Inputs {
get date(): BigInt {
return this._call.inputValues[2].value.toBigInt();
}

get roundId(): BigInt {
return this._call.inputValues[3].value.toBigInt();
}
}

export class SetSettlementPriceForDateCall__Outputs {
Expand Down Expand Up @@ -583,3 +587,45 @@ export class UpdateImplementationCall__Outputs {
this._call = call;
}
}

export class UpdateOracleAddressCall extends ethereum.Call {
get inputs(): UpdateOracleAddressCall__Inputs {
return new UpdateOracleAddressCall__Inputs(this);
}

get outputs(): UpdateOracleAddressCall__Outputs {
return new UpdateOracleAddressCall__Outputs(this);
}
}

export class UpdateOracleAddressCall__Inputs {
_call: UpdateOracleAddressCall;

constructor(call: UpdateOracleAddressCall) {
this._call = call;
}

get underlyingToken(): Address {
return this._call.inputValues[0].value.toAddress();
}

get priceToken(): Address {
return this._call.inputValues[1].value.toAddress();
}

get newOracle(): Address {
return this._call.inputValues[2].value.toAddress();
}

get feedId(): BigInt {
return this._call.inputValues[3].value.toBigInt();
}
}

export class UpdateOracleAddressCall__Outputs {
_call: UpdateOracleAddressCall;

constructor(call: UpdateOracleAddressCall) {
this._call = call;
}
}
111 changes: 111 additions & 0 deletions subgraph/generated/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,15 @@ export class Account extends Entity {
this.set("address", Value.fromBytes(value));
}

get isAmm(): boolean {
let value = this.get("isAmm");
return value.toBoolean();
}

set isAmm(value: boolean) {
this.set("isAmm", Value.fromBoolean(value));
}

get erc20Balances(): Array<string> {
let value = this.get("erc20Balances");
return value.toStringArray();
Expand Down Expand Up @@ -3259,6 +3268,108 @@ export class WTokenSold extends Entity {
}
}

export class Position extends Entity {
constructor(id: string) {
super();
this.set("id", Value.fromString(id));
}

save(): void {
let id = this.get("id");
assert(id !== null, "Cannot save Position entity without an ID");
assert(
id.kind == ValueKind.STRING,
"Cannot save Position entity with non-string ID. " +
'Considering using .toHex() to convert the "id" to a string.'
);
store.set("Position", id.toString(), this);
}

static load(id: string): Position | null {
return store.get("Position", id) as Position | null;
}

get id(): string {
let value = this.get("id");
return value.toString();
}

set id(value: string) {
this.set("id", Value.fromString(value));
}

get account(): string {
let value = this.get("account");
return value.toString();
}

set account(value: string) {
this.set("account", Value.fromString(value));
}

get seriesId(): BigInt {
let value = this.get("seriesId");
return value.toBigInt();
}

set seriesId(value: BigInt) {
this.set("seriesId", Value.fromBigInt(value));
}

get token(): string {
let value = this.get("token");
return value.toString();
}

set token(value: string) {
this.set("token", Value.fromString(value));
}

get costBasis(): BigDecimal | null {
let value = this.get("costBasis");
if (value === null || value.kind == ValueKind.NULL) {
return null;
} else {
return value.toBigDecimal();
}
}

set costBasis(value: BigDecimal | null) {
if (value === null) {
this.unset("costBasis");
} else {
this.set("costBasis", Value.fromBigDecimal(value as BigDecimal));
}
}

get block(): BigInt {
let value = this.get("block");
return value.toBigInt();
}

set block(value: BigInt) {
this.set("block", Value.fromBigInt(value));
}

get modified(): BigInt {
let value = this.get("modified");
return value.toBigInt();
}

set modified(value: BigInt) {
this.set("modified", Value.fromBigInt(value));
}

get transaction(): string {
let value = this.get("transaction");
return value.toString();
}

set transaction(value: string) {
this.set("transaction", Value.fromString(value));
}
}

export class ERC20AccountBalance extends Entity {
constructor(id: string) {
super();
Expand Down
Loading