Full-stack iOS options trading assistant: - Python FastAPI backend with SQLite, APScheduler (15-min position monitor), APNs push notifications, and yfinance market data integration - Signal engine: IV Rank (rolling HV proxy), SMA-50/200, swing-based support/resistance, earnings detection, signal strength scoring and noise-resistant SHA hash for change detection - Recommendation engine: covered call and cash-secured put strike/expiry selection across 0DTE, 1DTE, weekly, and monthly horizons - REST API: /devices, /portfolio, /recommendations, /positions, /signals, /alerts - iOS SwiftUI app (iOS 17+): dashboard, recommendations, trades, portfolio, and alerts tabs with push notification deep-linking - Unit + integration tests for signal engine and API layer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
41 lines
1.3 KiB
Swift
41 lines
1.3 KiB
Swift
import Foundation
|
|
import UserNotifications
|
|
|
|
@MainActor
|
|
final class NotificationPermissions {
|
|
static let shared = NotificationPermissions()
|
|
private init() {}
|
|
|
|
func requestIfNeeded() async {
|
|
guard !LocalStore.shared.notificationPermissionRequested else { return }
|
|
LocalStore.shared.notificationPermissionRequested = true
|
|
|
|
let center = UNUserNotificationCenter.current()
|
|
|
|
// Register a custom category with a "View" action for deep linking
|
|
let viewAction = UNNotificationAction(
|
|
identifier: Constants.notificationActionView,
|
|
title: "View Position",
|
|
options: [.foreground]
|
|
)
|
|
let category = UNNotificationCategory(
|
|
identifier: Constants.notificationCategory,
|
|
actions: [viewAction],
|
|
intentIdentifiers: [],
|
|
options: []
|
|
)
|
|
center.setNotificationCategories([category])
|
|
|
|
do {
|
|
let granted = try await center.requestAuthorization(options: [.alert, .badge, .sound])
|
|
if granted {
|
|
await MainActor.run {
|
|
UIApplication.shared.registerForRemoteNotifications()
|
|
}
|
|
}
|
|
} catch {
|
|
print("Notification permission error: \(error)")
|
|
}
|
|
}
|
|
}
|