-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5dc11e6
commit 3b455e7
Showing
6 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
name: Build | ||
|
||
on: | ||
workflow_dispatch: | ||
push: | ||
branches: ["main"] | ||
tags: ["v*.*.*"] | ||
pull_request: | ||
branches: ["main"] | ||
|
||
permissions: | ||
contents: write | ||
|
||
jobs: | ||
build: | ||
runs-on: macos-latest | ||
steps: | ||
- name: 📥 Checkout repository | ||
uses: actions/checkout@v3 | ||
|
||
- name: 🧰 Download Typst | ||
uses: robinraju/release-downloader@v1.7 | ||
with: | ||
repository: typst/typst | ||
tag: v0.10.0 | ||
fileName: typst-x86_64-apple-darwin.tar.xz | ||
|
||
- name: 🧰 Extract Typst | ||
shell: bash | ||
run: | | ||
sudo mkdir /usr/local/typst | ||
sudo tar -xzf typst-x86_64-apple-darwin.tar.xz -C /usr/local/typst/ | ||
rm -f typst-x86_64-apple-darwin.tar.xz | ||
echo "/usr/local/typst/typst-x86_64-apple-darwin" >> $GITHUB_PATH | ||
- run: "echo $GITHUB_SHA > ./version.txt" | ||
|
||
- name: 📘 Compile | ||
shell: bash | ||
run: ./build.sh | ||
|
||
- name: 📦 Upload artifacts | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: oracle_spec | ||
path: ./*.pdf | ||
|
||
- name: 🚀 Release | ||
uses: softprops/action-gh-release@v1 | ||
if: github.ref_type == 'tag' | ||
with: | ||
name: ${{ github.ref_name }} | ||
tag_name: ${{ github.ref_name }} | ||
files: "./*.pdf" | ||
|
||
- run: "mkdir output && mv spec.pdf output/spec.pdf" | ||
|
||
- name: Publish | ||
uses: ryand56/r2-upload-action@latest | ||
with: | ||
r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} | ||
r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} | ||
r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} | ||
r2-bucket: ${{ secrets.R2_BUCKET }} | ||
source-dir: output | ||
destination-dir: ./ |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
|
||
def generate_price_data(initial_price, num_days, volatility): | ||
"""Generate price data using random walk.""" | ||
prices = [initial_price] | ||
for _ in range(num_days - 1): | ||
change = np.random.normal(0, volatility) | ||
new_price = max(0, prices[-1] + change) # Ensure price doesn't go negative | ||
prices.append(new_price) | ||
return prices | ||
|
||
def calculate_modified_ema(prices, period=20): | ||
"""Calculate Modified Exponential Moving Average.""" | ||
ema = [prices[0]] | ||
multiplier = 2 / (period + 1) | ||
for price in prices[1:]: | ||
if price < ema[-1]: | ||
ema.append(price) # Immediately adjust to price decrease | ||
else: | ||
ema.append((price - ema[-1]) * multiplier + ema[-1]) # Use EMA for price increase | ||
return ema | ||
|
||
def calculate_simple_ema(prices, period=20): | ||
""" | ||
Calculate Simple Exponential Moving Average with immediate price decrease reflection. | ||
This is the preferred model for our analysis. It has the following characteristics: | ||
1. Immediately adjusts to price decreases, providing quick responsiveness to market downturns. | ||
2. Uses standard EMA calculation for price increases, allowing for a smoother trend during upward movements. | ||
This combination allows for quick reaction to potential losses while maintaining trend stability during growth periods. | ||
""" | ||
ema = [prices[0]] | ||
multiplier = 2 / (period + 1) | ||
for price in prices[1:]: | ||
if price < ema[-1]: | ||
ema.append(price) # Immediately adjust to price decrease | ||
else: | ||
ema.append((price - ema[-1]) * multiplier + ema[-1]) # Use EMA for price increase | ||
return ema | ||
|
||
def plot_asset_price(asset_name, initial_price=100, num_days=365, volatility=1): | ||
"""Plot the price of an asset over time.""" | ||
days = range(num_days) | ||
prices = generate_price_data(initial_price, num_days, volatility) | ||
simple_ema = calculate_simple_ema(prices) | ||
|
||
plt.figure(figsize=(10, 6)) | ||
plt.plot(days, prices, label='Price') | ||
plt.plot(days, simple_ema, label='Simple EMA (Preferred Model)', color='red') | ||
plt.title(f"Price of {asset_name} Over Time") | ||
plt.xlabel("Days") | ||
plt.ylabel("Price") | ||
plt.grid(True) | ||
plt.legend() | ||
plt.savefig('img/example.png') | ||
plt.close() | ||
|
||
# Example usage | ||
plot_asset_price("XYZ", initial_price=100, num_days=365, volatility=1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#let special_version = read("./version.txt") | ||
#align(center, [ | ||
#v(2em) | ||
#[#set par(justify: true) | ||
#image("img/logo-black.png", width: 120pt)] | ||
#set text(size:18pt) | ||
|
||
Oracle Specifications | ||
#align(center, text(12pt, weight: 400)[ | ||
v. #special_version | ||
]) | ||
|
||
#datetime.today().display("[day] [month repr:long], [year]") | ||
]) | ||
#v(2em) | ||
= Simple EMA Oracle Specification | ||
|
||
== Overview | ||
This specification outlines the Simple Exponential Moving Average (EMA) oracle algorithm, which is designed to provide a responsive and adaptive measure of asset price trends. The algorithm is particularly suited for financial applications where quick reactions to market downturns are crucial while maintaining stability during upward trends. | ||
|
||
== Algorithm Description | ||
The Simple EMA algorithm uses a single piece of previous state to add a drag for any price increases while immediately reflecting price decreases. This approach combines the benefits of quick responsiveness to potential losses with the stability of trend following during growth periods. | ||
|
||
== Key Features | ||
1. Immediate reflection of price decreases | ||
2. Smoothed response to price increases using EMA calculation | ||
3. Single state variable for efficient implementation | ||
|
||
== Implementation Details | ||
|
||
=== Inputs | ||
- `prices`: A list of asset prices over time | ||
- `period`: The number of days for the EMA calculation (default: 20) | ||
|
||
=== Output | ||
- A list of EMA values corresponding to the input prices | ||
|
||
== Visual Representation | ||
|
||
The following graph illustrates the behavior of the Simple EMA algorithm compared to the actual price of an asset over time: | ||
|
||
#figure( | ||
image("img/example.png", width: 80%), | ||
caption: [ | ||
Comparison of Asset Price and Simple EMA over time. | ||
The red line represents the Simple EMA, which quickly adapts to price decreases while smoothing price increases. | ||
] | ||
) | ||
|
||
This visual representation demonstrates how the Simple EMA (red line) closely follows the asset price (blue line) during downward movements, while providing a smoother trend during upward movements. This behavior aligns with the algorithm's design to be responsive to potential losses while maintaining stability during growth periods. | ||
|
||
|
||
=== Pseudocode | ||
|
||
#figure([ | ||
#set text(font: "New Computer Modern Mono") | ||
|
||
*Input:* prices, period \ | ||
*Output:* ema | ||
|
||
ema \<\- [prices[0]] \ | ||
multiplier \<\- 2 / (period + 1) | ||
|
||
*for* price *in* prices[1:] \ | ||
#h(20pt)*if* price < ema[-1] \ | ||
#h(40pt)ema.append(price) \ | ||
#h(20pt)*else* \ | ||
#h(40pt)new_ema \<\- (price - ema[-1]) \* multiplier + ema[-1] \ | ||
#h(40pt)ema.append(new_ema) \ | ||
#h(20pt)*end if* \ | ||
*end for* | ||
|
||
*return* ema | ||
], caption: "Simple EMA Algorithm") | ||
|
||
== Notes | ||
1. The algorithm initializes the EMA with the first price in the series. | ||
2. For each subsequent price: | ||
- If the new price is lower than the previous EMA, it immediately becomes the new EMA value. | ||
- If the new price is higher, a standard EMA calculation is applied. | ||
3. This approach ensures quick adaptation to price drops while smoothing out price increases. | ||
|
||
== Reference Implementation | ||
For a reference implementation, refer to the `calculate_simple_ema` function in the `oracles.py` file. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DEV VERSION |