freqtrade_origin/setup.ps1

269 lines
8.7 KiB
PowerShell
Raw Normal View History

Clear-Host
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$Global:LogFilePath = Join-Path $env:TEMP "script_log_$Timestamp.txt"
2024-05-23 10:07:40 +00:00
$RequirementFiles = @("requirements.txt", "requirements-dev.txt", "requirements-hyperopt.txt", "requirements-freqai.txt", "requirements-freqai-rl.txt", "requirements-plot.txt")
$VenvName = ".venv"
2024-05-23 10:07:40 +00:00
$VenvDir = Join-Path $PSScriptRoot $VenvName
function Write-Log {
param (
[string]$Message,
[string]$Level = 'INFO'
)
2024-05-23 10:07:40 +00:00
if (-not (Test-Path -Path $LogFilePath)) {
New-Item -ItemType File -Path $LogFilePath -Force | Out-Null
}
2024-05-21 20:32:03 +00:00
switch ($Level) {
'INFO' { Write-Host $Message -ForegroundColor Green }
'WARNING' { Write-Host $Message -ForegroundColor Yellow }
'ERROR' { Write-Host $Message -ForegroundColor Red }
'PROMPT' { Write-Host $Message -ForegroundColor Cyan }
}
"${Level}: $Message" | Out-File $LogFilePath -Append
}
function Get-UserSelection {
param (
2024-05-23 10:07:40 +00:00
[string]$Prompt,
[string[]]$Options,
[string]$DefaultChoice = 'A',
[bool]$AllowMultipleSelections = $true
)
2024-05-23 10:07:40 +00:00
Write-Log "$Prompt`n" -Level 'PROMPT'
for ($I = 0; $I -lt $Options.Length; $I++) {
Write-Log "$([char](65 + $I)). $($Options[$I])" -Level 'PROMPT'
}
2024-05-23 10:07:40 +00:00
if ($AllowMultipleSelections) {
Write-Log "`nSelect one or more options by typing the corresponding letters, separated by commas." -Level 'PROMPT'
}
else {
Write-Log "`nSelect an option by typing the corresponding letter." -Level 'PROMPT'
}
[string]$UserInput = Read-Host
if ([string]::IsNullOrEmpty($UserInput)) {
$UserInput = $DefaultChoice
}
2024-05-23 10:07:40 +00:00
if ($AllowMultipleSelections) {
$Selections = $UserInput.Split(',') | ForEach-Object {
2024-05-23 10:07:40 +00:00
$_.Trim().ToUpper()
}
$ErrorMessage = "Invalid input: $Selection. Please enter letters within the valid range of options."
# Convert each Selection from letter to Index and validate
$SelectedIndices = @()
foreach ($Selection in $Selections) {
if ($Selection -match '^[A-Z]$') {
$Index = [int][char]$Selection - [int][char]'A'
if ($Index -ge 0 -and $Index -lt $Options.Length) {
$SelectedIndices += $Index
2024-05-23 10:07:40 +00:00
}
else {
Write-Log $ErrorMessage -Level 'ERROR'
2024-05-23 10:07:40 +00:00
return -1
}
2024-05-21 20:32:03 +00:00
}
else {
Write-Log $ErrorMessage -Level 'ERROR'
2024-05-23 10:07:40 +00:00
return -1
}
}
return $SelectedIndices
2024-05-23 10:07:40 +00:00
}
else {
# Convert the Selection from letter to Index and validate
if ($UserInput -match '^[A-Z]$') {
$SelectedIndex = [int][char]$UserInput - [int][char]'A'
if ($SelectedIndex -ge 0 -and $SelectedIndex -lt $Options.Length) {
return $SelectedIndex
2024-05-23 10:07:40 +00:00
}
else {
Write-Log "Invalid input: $UserInput. Please enter a letter within the valid range of options." -Level 'ERROR'
2024-05-23 10:07:40 +00:00
return -1
2024-05-21 20:32:03 +00:00
}
}
else {
Write-Log "Invalid input: $UserInput. Please enter a letter between A and Z." -Level 'ERROR'
2024-05-23 10:07:40 +00:00
return -1
}
}
}
function Exit-Script {
param (
2024-05-23 10:07:40 +00:00
[int]$ExitCode,
[bool]$WaitForKeypress = $true
)
# Disable virtual environment
deactivate
if ($ExitCode -ne 0) {
Write-Log "Script failed. Would you like to open the log file? (Y/N)" -Level 'PROMPT'
$openLog = Read-Host
if ($openLog -eq 'Y' -or $openLog -eq 'y') {
Start-Process notepad.exe -ArgumentList $LogFilePath
}
}
elseif ($WaitForKeypress) {
2024-05-21 20:32:03 +00:00
Write-Log "Press any key to exit..."
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null
}
2024-05-23 10:07:40 +00:00
return $ExitCode
}
2024-05-23 10:07:40 +00:00
function Test-PythonExecutable {
param(
2024-05-23 10:08:10 +00:00
[string]$PythonExecutable
2024-05-23 10:07:40 +00:00
)
$PythonCmd = Get-Command $PythonExecutable -ErrorAction SilentlyContinue
if ($PythonCmd) {
$Command = "$($PythonCmd.Source) --version 2>&1"
$VersionOutput = Invoke-Expression $Command
2024-05-23 10:08:10 +00:00
if ($LASTEXITCODE -eq 0) {
$Version = $VersionOutput | Select-String -Pattern "Python (\d+\.\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }
Write-Log "Python version $Version found using executable '$PythonExecutable'."
2024-05-23 10:08:10 +00:00
return $true
}
else {
Write-Log "Python executable '$PythonExecutable' not working correctly." -Level 'ERROR'
return $false
}
2024-05-23 10:07:40 +00:00
}
else {
2024-05-23 10:08:10 +00:00
Write-Log "Python executable '$PythonExecutable' not found." -Level 'ERROR'
return $false
2024-05-23 10:07:40 +00:00
}
2024-05-21 20:32:03 +00:00
}
2024-05-23 10:07:40 +00:00
function Find-PythonExecutable {
$PythonExecutables = @("python", "python3.12", "python3.11", "python3.10", "python3.9", "python3", "C:\Users\$env:USERNAME\AppData\Local\Programs\Python\Python312\python.exe", "C:\Users\$env:USERNAME\AppData\Local\Programs\Python\Python311\python.exe", "C:\Users\$env:USERNAME\AppData\Local\Programs\Python\Python310\python.exe", "C:\Users\$env:USERNAME\AppData\Local\Programs\Python\Python39\python.exe", "C:\Python311\python.exe", "C:\Python310\python.exe", "C:\Python39\python.exe")
2024-05-23 10:07:40 +00:00
foreach ($Executable in $PythonExecutables) {
if (Test-PythonExecutable -PythonExecutable $Executable) {
return $Executable
2024-05-23 10:08:10 +00:00
}
2024-05-23 10:07:40 +00:00
}
return $null
}
2024-05-23 10:07:40 +00:00
function Main {
"Starting the operations..." | Out-File $LogFilePath -Append
"Current directory: $(Get-Location)" | Out-File $LogFilePath -Append
2024-05-23 10:07:40 +00:00
# Exit on lower versions than Python 3.9 or when Python executable not found
$PythonExecutable = Find-PythonExecutable
if ($null -eq $PythonExecutable) {
2024-05-23 10:07:40 +00:00
Write-Host "Error: No suitable Python executable found. Please ensure that Python 3.9 or higher is installed and available in the system PATH."
Exit 1
}
2024-05-23 10:07:40 +00:00
# Define the path to the Python executable in the virtual environment
$VenvPython = "$VenvDir\Scripts\Activate.ps1"
2024-05-23 10:07:40 +00:00
# Check if the virtual environment exists, if not, create it
if (-Not (Test-Path $VenvPython)) {
2024-05-23 10:07:40 +00:00
Write-Log "Virtual environment not found. Creating virtual environment..." -Level 'ERROR'
& $PythonExecutable -m venv $VenvName
2024-05-23 10:07:40 +00:00
if (-Not (Test-Path $VenvPython)) {
Write-Log "Failed to create virtual environment." -Level 'ERROR'
Exit-Script -exitCode 1
}
2024-05-23 17:02:53 +00:00
Write-Log "Virtual environment created successfully."
2024-05-23 10:07:40 +00:00
}
# Pull latest updates only if the repository state is not dirty
Write-Log "Checking if the repository is clean..."
$status = & "C:\Program Files\Git\cmd\git.exe" status --porcelain
if ($status) {
Write-Log "Repository is dirty. Skipping pull."
}
else {
Write-Log "Pulling latest updates..."
& "C:\Program Files\Git\cmd\git.exe" pull | Out-File $LogFilePath -Append 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Log "Failed to pull updates from Git." -Level 'ERROR'
Exit-Script -exitCode 1
}
}
2024-05-23 10:07:40 +00:00
if (-not (Test-Path "$VenvDir\Lib\site-packages\talib")) {
# Install TA-Lib using the virtual environment's pip
Write-Log "Installing TA-Lib using virtual environment's pip..."
python -m pip install --find-links=build_helpers\ --prefer-binary TA-Lib | Out-File $LogFilePath -Append 2>&1
2024-05-23 10:07:40 +00:00
}
2024-05-23 10:07:40 +00:00
# Present options for requirement files
$SelectedIndices = Get-UserSelection -prompt "Select which requirement files to install:" -options $RequirementFiles -defaultChoice 'A'
2024-05-23 10:07:40 +00:00
# Cache the selected requirement files
$SelectedRequirementFiles = @()
$PipInstallArguments = ""
foreach ($Index in $SelectedIndices) {
$FilePath = Join-Path $PSScriptRoot $RequirementFiles[$Index]
if (Test-Path $FilePath) {
$SelectedRequirementFiles += $FilePath
$PipInstallArguments += " -r $FilePath"
2024-05-23 10:07:40 +00:00
}
else {
Write-Log "Requirement file not found: $FilePath" -Level 'ERROR'
2024-05-23 10:07:40 +00:00
Exit-Script -exitCode 1
}
}
if ($PipInstallArguments -ne "") {
python -m pip install $PipInstallArguments
2024-05-23 10:07:40 +00:00
}
2024-05-23 10:07:40 +00:00
# Install freqtrade from setup using the virtual environment's Python
Write-Log "Installing freqtrade from setup..."
python -m pip install -e . | Out-File $LogFilePath -Append 2>&1
2024-05-23 10:07:40 +00:00
if ($LASTEXITCODE -ne 0) {
Write-Log "Failed to install freqtrade." -Level 'ERROR'
Exit-Script -exitCode 1
}
$UiOptions = @("Yes", "No")
$InstallUi = Get-UserSelection -prompt "Do you want to install the freqtrade UI?" -options $UiOptions -defaultChoice 'B' -allowMultipleSelections $false
if ($InstallUi -eq 0) {
2024-05-23 10:07:40 +00:00
# User selected "Yes"
# Install freqtrade UI using the virtual environment's install-ui command
Write-Log "Installing freqtrade UI..."
python 'freqtrade', 'install-ui' | Out-File $LogFilePath -Append 2>&1
2024-05-23 10:07:40 +00:00
if ($LASTEXITCODE -ne 0) {
Write-Log "Failed to install freqtrade UI." -Level 'ERROR'
Exit-Script -exitCode 1
}
}
elseif ($InstallUi -eq 1) {
2024-05-23 10:07:40 +00:00
# User selected "No"
# Skip installing freqtrade UI
Write-Log "Skipping freqtrade UI installation."
}
else {
# Invalid Selection
2024-05-23 10:07:40 +00:00
# Handle the error case
Write-Log "Invalid Selection for freqtrade UI installation." -Level 'ERROR'
Exit-Script -exitCode 1
}
2024-05-23 10:07:40 +00:00
Write-Log "Update complete!"
Exit-Script -exitCode 0
}
2024-05-23 10:07:40 +00:00
# Call the Main function
Main